1/*
2Copyright (c) 2012, Broadcom Europe Ltd
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 notice, this list of conditions and the following disclaimer in the
11 documentation and/or other materials provided with the distribution.
12 * Neither the name of the copyright holder nor the
13 names of its contributors may be used to endorse or promote products
14 derived from this software without specific prior written permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#define EGL_EGLEXT_PROTOTYPES /* we want the prototypes so the compiler will check that the signatures match */
29
30#include "interface/khronos/common/khrn_int_common.h"
31#include "interface/khronos/common/khrn_client.h"
32#include "interface/khronos/common/khrn_client_rpc.h"
33#include "interface/khronos/egl/egl_client_config.h"
34#include "interface/khronos/include/EGL/egl.h"
35#include "interface/khronos/include/EGL/eglext.h"
36
37#if EGL_BRCM_global_image
38
39static EGLint get_bytes_per_pixel(EGLint pixel_format) /* returns 0 for invalid pixel formats */
40{
41 switch (pixel_format & ~EGL_PIXEL_FORMAT_USAGE_MASK_BRCM) {
42 case EGL_PIXEL_FORMAT_ARGB_8888_PRE_BRCM: return 4;
43 case EGL_PIXEL_FORMAT_ARGB_8888_BRCM: return 4;
44 case EGL_PIXEL_FORMAT_XRGB_8888_BRCM: return 4;
45 case EGL_PIXEL_FORMAT_RGB_565_BRCM: return 2;
46 case EGL_PIXEL_FORMAT_A_8_BRCM: return 1;
47 default: return 0; /* invalid */
48 }
49}
50
51/*
52 failure is indicated by (!id[0] && !id[1]). call eglGetError for the error code
53
54 possible failures:
55 - width/height <= 0 or > EGL_CONFIG_MAX_WIDTH/EGL_CONFIG_MAX_HEIGHT (EGL_BAD_PARAMETER)
56 - pixel_format invalid (EGL_BAD_PARAMETER)
57 - insufficient resources (EGL_BAD_ALLOC)
58
59 data may be NULL (in which case the image contents are undefined)
60*/
61
62EGLAPI void EGLAPIENTRY eglCreateGlobalImageBRCM(EGLint width, EGLint height, EGLint pixel_format, const void *data, EGLint data_stride, EGLint *id)
63{
64 EGLint bytes_per_pixel;
65
66 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
67
68 /*
69 check params
70 */
71
72 bytes_per_pixel = get_bytes_per_pixel(pixel_format);
73 if ((width <= 0) || (width > EGL_CONFIG_MAX_WIDTH) ||
74 (height <= 0) || (height > EGL_CONFIG_MAX_HEIGHT) ||
75 (bytes_per_pixel == 0)) {
76 thread->error = EGL_BAD_PARAMETER;
77 id[0] = 0; id[1] = 0;
78 return;
79 }
80
81 /*
82 create the image
83 */
84
85 RPC_CALL4_OUT_CTRL(eglCreateGlobalImageBRCM_impl,
86 thread,
87 EGLCREATEGLOBALIMAGEBRCM_ID,
88 RPC_INT(width),
89 RPC_INT(height),
90 RPC_INT(pixel_format),
91 id);
92 if (!id[0] && !id[1]) {
93 thread->error = EGL_BAD_ALLOC;
94 return;
95 }
96
97 /*
98 fill the image in if necessary (this can't fail)
99 */
100
101 if (data) {
102 #ifdef RPC_DIRECT
103 RPC_CALL7(eglFillGlobalImageBRCM_impl, thread, no_id, id[0], id[1], 0, height, data, data_stride, pixel_format);
104 #else
105 EGLint y = 0;
106
107 EGLint chunk_height_max = KHDISPATCH_WORKSPACE_SIZE / (width * bytes_per_pixel);
108 vcos_assert(chunk_height_max != 0);
109
110 while (height != 0) {
111 VGint chunk_height = _min(height, chunk_height_max);
112
113 uint32_t message[] = {
114 EGLFILLGLOBALIMAGEBRCM_ID,
115 RPC_INT(id[0]),
116 RPC_INT(id[1]),
117 RPC_INT(y),
118 RPC_INT(chunk_height),
119 RPC_INT(width * bytes_per_pixel),
120 RPC_INT(pixel_format) };
121
122 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
123
124 rpc_begin(thread);
125 rpc_send_ctrl_begin(thread, sizeof(message));
126 rpc_send_ctrl_write(thread, message, sizeof(message));
127 rpc_send_ctrl_end(thread);
128 rpc_send_bulk_gather(thread, data, width * bytes_per_pixel, data_stride, chunk_height);
129 data = (const uint8_t *)data + (chunk_height * data_stride);
130 rpc_end(thread);
131
132 height -= chunk_height;
133 y += chunk_height;
134 }
135 #endif
136 }
137}
138
139/*
140 failure is indicated by (!id[0] && !id[1]). call eglGetError for the error code
141
142 possible failures:
143 - src_id invalid (EGL_BAD_PARAMETER)
144 - insufficient resources (EGL_BAD_ALLOC)
145*/
146
147EGLAPI void EGLAPIENTRY eglCreateCopyGlobalImageBRCM(const EGLint *src_id, EGLint *id)
148{
149 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
150
151 /*
152 create the image
153 */
154
155 RPC_CALL3_OUT_CTRL(eglCreateCopyGlobalImageBRCM_impl,
156 thread,
157 EGLCREATECOPYGLOBALIMAGEBRCM_ID,
158 RPC_INT(src_id[0]),
159 RPC_INT(src_id[1]),
160 id);
161 if (!id[0] && !id[1]) { /* not enough memory */
162 thread->error = EGL_BAD_ALLOC;
163 }
164 if ((id[0] == -1) && (id[1] == -1)) { /* src_id was invalid */
165 thread->error = EGL_BAD_PARAMETER;
166 id[0] = 0; id[1] = 0;
167 }
168}
169
170/*
171 failure is indicated by returning EGL_FALSE. call eglGetError for the error code
172
173 possible failures:
174 - id invalid (EGL_BAD_PARAMETER)
175*/
176
177EGLAPI EGLBoolean EGLAPIENTRY eglDestroyGlobalImageBRCM(const EGLint *id)
178{
179 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
180
181 /*
182 destroy the image
183 */
184
185 if (!RPC_BOOLEAN_RES(RPC_CALL2_RES(eglDestroyGlobalImageBRCM_impl,
186 thread,
187 EGLDESTROYGLOBALIMAGEBRCM_ID,
188 RPC_INT(id[0]),
189 RPC_INT(id[1])))) {
190 thread->error = EGL_BAD_PARAMETER;
191 return EGL_FALSE;
192 }
193
194 return EGL_TRUE;
195}
196
197/*
198 failure is indicated by returning EGL_FALSE. call eglGetError for the error code
199
200 possible failures:
201 - id invalid (EGL_BAD_PARAMETER)
202*/
203
204EGLAPI EGLBoolean EGLAPIENTRY eglQueryGlobalImageBRCM(const EGLint *id, EGLint *width_height_pixel_format)
205{
206 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
207
208 if (!RPC_BOOLEAN_RES(RPC_CALL3_OUT_CTRL_RES(eglQueryGlobalImageBRCM_impl,
209 thread,
210 EGLQUERYGLOBALIMAGEBRCM_ID,
211 RPC_INT(id[0]),
212 RPC_INT(id[1]),
213 width_height_pixel_format))) {
214 thread->error = EGL_BAD_PARAMETER;
215 return EGL_FALSE;
216 }
217
218 return EGL_TRUE;
219}
220
221#endif
222