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#define VCOS_LOG_CATEGORY (&egl_khr_image_client_log)
31#include "interface/khronos/common/khrn_client_mangle.h"
32
33#include "interface/khronos/common/khrn_int_common.h"
34
35#include "interface/khronos/common/khrn_client.h"
36#include "interface/khronos/common/khrn_client_rpc.h"
37
38#include "interface/khronos/include/EGL/egl.h"
39#include "interface/khronos/include/EGL/eglext.h"
40#include "interface/khronos/include/EGL/eglext_brcm.h"
41#include "interface/khronos/include/GLES/gl.h"
42
43#include "interface/vcos/vcos.h"
44
45#if EGL_ANDROID_image_native_buffer
46#include <gralloc_brcm.h>
47#endif
48
49#if defined(ANDROID) && defined(KHRN_BCG_ANDROID)
50#include "gralloc_priv.h"
51#include "middleware/khronos/common/2708/khrn_prod_4.h"
52#endif
53
54#ifdef KHRONOS_HAVE_VCSM
55#include "user-vcsm.h"
56#else
57#include <dlfcn.h>
58#include <dlfcn.h>
59typedef enum
60{
61 VCSM_CACHE_TYPE_NONE = 0, // No caching applies.
62 VCSM_CACHE_TYPE_HOST, // Allocation is cached on host (user space).
63 VCSM_CACHE_TYPE_VC, // Allocation is cached on videocore.
64 VCSM_CACHE_TYPE_HOST_AND_VC, // Allocation is cached on both host and videocore.
65
66} VCSM_CACHE_TYPE_T;
67static unsigned int (*vcsm_malloc_cache)(unsigned int size, VCSM_CACHE_TYPE_T cache, char *name);
68static unsigned int (*vcsm_vc_hdl_from_hdl)(unsigned int handle);
69static void (*vcsm_free) (unsigned int handle);
70#endif /* KHRONOS_HAVE_VCSM */
71
72static VCOS_LOG_CAT_T egl_khr_image_client_log = VCOS_LOG_INIT("egl_khr_image_client", VCOS_LOG_WARN);
73
74static bool egl_init_vcsm()
75{
76#ifdef KHRONOS_HAVE_VCSM
77 return true;
78#else
79 static bool warn_once;
80 bool success = false;
81
82 if (vcsm_malloc_cache)
83 return true;
84
85 if (! vcsm_malloc_cache) {
86 /* Try LD_LIBRARY_PATH first */
87 void *dl = dlopen("libvcsm.so", RTLD_LAZY);
88
89 if (!dl)
90 dl = dlopen("/opt/vc/lib/libvcsm.so", RTLD_LAZY);
91
92 if (dl)
93 {
94 vcsm_malloc_cache = dlsym(dl, "vcsm_malloc_cache");
95 vcsm_vc_hdl_from_hdl = dlsym(dl, "vcsm_vc_hdl_from_hdl");
96 vcsm_free = dlsym(dl, "vcsm_free");
97
98 if (vcsm_malloc_cache && vcsm_vc_hdl_from_hdl && vcsm_free)
99 {
100 success = true;
101 }
102 else
103 {
104 vcsm_malloc_cache = NULL;
105 vcsm_vc_hdl_from_hdl = NULL;
106 vcsm_free = NULL;
107 }
108 }
109 }
110 if (! success && ! warn_once)
111 {
112 vcos_log_error("Unable to load libvcsm.so for target EGL_IMAGE_BRCM_VCSM");
113 warn_once = false;
114 }
115 return success;
116#endif /* KHRONOS_HAVE_VCSM */
117}
118
119EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list)
120{
121 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
122 EGLImageKHR result = EGL_NO_IMAGE_KHR;
123
124 CLIENT_LOCK();
125
126 vcos_log_info("eglCreateImageKHR: dpy %p ctx %p target %x buf %p\n",
127 dpy, ctx, target, buffer);
128
129 {
130 CLIENT_PROCESS_STATE_T *process = client_egl_get_process_state(thread, dpy, EGL_TRUE);
131
132 if (process) {
133 EGL_CONTEXT_T *context;
134 bool ctx_error;
135 if (target == EGL_NATIVE_PIXMAP_KHR
136#ifdef EGL_BRCM_image_wrap
137 || target == EGL_IMAGE_WRAP_BRCM
138#endif
139#ifdef EGL_BRCM_image_wrap_bcg
140 || target == EGL_IMAGE_WRAP_BRCM_BCG
141#endif
142#if EGL_ANDROID_image_native_buffer
143 || target == EGL_NATIVE_BUFFER_ANDROID
144 || target == EGL_IMAGE_BRCM_RAW_PIXELS
145#endif
146 || target == EGL_IMAGE_BRCM_MULTIMEDIA
147 || target == EGL_IMAGE_BRCM_MULTIMEDIA_Y
148 || target == EGL_IMAGE_BRCM_MULTIMEDIA_U
149 || target == EGL_IMAGE_BRCM_MULTIMEDIA_V
150 || target == EGL_IMAGE_BRCM_DUPLICATE
151 || target == EGL_IMAGE_BRCM_VCSM
152 ) {
153 context = NULL;
154 ctx_error = ctx != EGL_NO_CONTEXT;
155 } else {
156 context = client_egl_get_context(thread, process, ctx);
157 ctx_error = !context;
158 }
159 if (ctx_error) {
160 thread->error = EGL_BAD_PARAMETER;
161 }
162 else {
163 uint32_t buf[2];
164 KHRN_IMAGE_FORMAT_T buffer_format = IMAGE_FORMAT_INVALID;
165 uint32_t buffer_width = 0;
166 uint32_t buffer_height = 0;
167 uint32_t buffer_stride = 0;
168 bool buf_error = false;
169 if (target == EGL_NATIVE_PIXMAP_KHR) {
170 buf[0] = 0; buf[1] = (uint32_t)(-1);
171 platform_get_pixmap_server_handle((EGLNativePixmapType)buffer, buf);
172#if EGL_BRCM_global_image
173 if ((buf[0] == 0) && (buf[1] == (uint32_t)(-1))) { /* allow either regular or global image server-side pixmaps */
174#else
175 if ((buf[0] == 0) || (buf[1] != (uint32_t)(-1))) { /* only allow regular server-side pixmaps */
176#endif
177 /* This is a client-side pixmap! TODO: implement these properly */
178 KHRN_IMAGE_WRAP_T image;
179 if (platform_get_pixmap_info((EGLNativePixmapType)buffer, &image))
180 {
181//meego hack
182 if(image.aux!=0)
183 {
184 //image.aux refers to a server side EGL surface
185 //that already contains the data we're interested in
186 buf[0] = (uint32_t)image.aux;
187 target = EGL_IMAGE_FROM_SURFACE_BRCM;
188 khrn_platform_release_pixmap_info((EGLNativePixmapType)buffer, &image);
189 }
190//
191 else
192 {
193 buf[0] = image.width | image.height << 16;
194 target = EGL_NATIVE_PIXMAP_CLIENT_SIDE_BRCM;
195 khrn_platform_release_pixmap_info((EGLNativePixmapType)buffer, &image);
196 }
197
198 }
199 else
200 {
201 buf_error = true;
202 }
203 }
204#if EGL_BRCM_image_wrap
205 } else if (target == EGL_IMAGE_WRAP_BRCM) {
206 KHRN_IMAGE_WRAP_T *wrap_buffer = (KHRN_IMAGE_WRAP_T *)buffer;
207
208 buf[0] = (uint32_t)wrap_buffer->storage;
209 buffer_format = wrap_buffer->format;
210 buffer_width = wrap_buffer->width;
211 buffer_height = wrap_buffer->height;
212 buffer_stride = wrap_buffer->stride;
213#endif
214#if EGL_BRCM_image_wrap_bcg
215 } else if (target == EGL_IMAGE_WRAP_BRCM_BCG) {
216 EGL_IMAGE_WRAP_BRCM_BCG_IMAGE_T *wrap_buffer = (EGL_IMAGE_WRAP_BRCM_BCG_IMAGE_T *)buffer;
217
218 buf[0] = (uint32_t)wrap_buffer->storage;
219 buffer_width = wrap_buffer->width;
220 buffer_height = wrap_buffer->height;
221 buffer_stride = wrap_buffer->stride;
222
223 switch(wrap_buffer->format)
224 {
225 case BEGL_BufferFormat_eR8G8B8A8_TFormat: buffer_format = ABGR_8888_TF; break;
226 case BEGL_BufferFormat_eX8G8B8A8_TFormat: buffer_format = XBGR_8888_TF; break;
227 case BEGL_BufferFormat_eR5G6B5_TFormat: buffer_format = RGB_565_TF; break;
228 case BEGL_BufferFormat_eR5G5B5A1_TFormat: buffer_format = RGBA_5551_TF; break;
229 case BEGL_BufferFormat_eR4G4B4A4_TFormat: buffer_format = RGBA_4444_TF; break;
230
231 case BEGL_BufferFormat_eR8G8B8A8_LTFormat: buffer_format = ABGR_8888_LT; break;
232 case BEGL_BufferFormat_eX8G8B8A8_LTFormat: buffer_format = XBGR_8888_LT; break;
233 case BEGL_BufferFormat_eR5G6B5_LTFormat: buffer_format = RGB_565_LT; break;
234 case BEGL_BufferFormat_eR5G5B5A1_LTFormat: buffer_format = RGBA_5551_LT; break;
235 case BEGL_BufferFormat_eR4G4B4A4_LTFormat: buffer_format = RGBA_4444_LT; break;
236
237 default:
238 buf_error = true;
239 }
240#endif
241#if EGL_ANDROID_image_native_buffer
242#ifdef KHRN_BCG_ANDROID
243 } else if (target == EGL_NATIVE_BUFFER_ANDROID) {
244 android_native_buffer_t *android_buffer = (android_native_buffer_t *)buffer;
245 vcos_assert(ANDROID_NATIVE_BUFFER_MAGIC == android_buffer->common.magic);
246 /* TODO check that handle is a valid gralloc handle */
247 /* These are shadow width/height and format, not to be confused with the
248 underlying formats configuration */
249
250 buf[0] = (uint32_t)khrn_hw_unaddr(((struct private_handle_t *)android_buffer->handle)->oglPhysicalAddress);
251
252 buffer_format = ((struct private_handle_t *)android_buffer->handle)->oglFormat;
253 buffer_width = android_buffer->width;
254 buffer_height = android_buffer->height;
255 buffer_stride = ((struct private_handle_t *)android_buffer->handle)->oglStride;
256
257 switch (((struct private_handle_t *)android_buffer->handle)->oglFormat)
258 {
259 case BEGL_BufferFormat_eR8G8B8A8_TFormat: buffer_format = ABGR_8888_TF; break;
260 case BEGL_BufferFormat_eX8G8B8A8_TFormat: buffer_format = XBGR_8888_TF; break;
261 case BEGL_BufferFormat_eR5G6B5_TFormat: buffer_format = RGB_565_TF; break;
262 case BEGL_BufferFormat_eR5G5B5A1_TFormat: buffer_format = RGBA_5551_TF; break;
263 case BEGL_BufferFormat_eR4G4B4A4_TFormat: buffer_format = RGBA_4444_TF; break;
264 case BEGL_BufferFormat_eR8G8B8A8_LTFormat: buffer_format = ABGR_8888_LT; break;
265 case BEGL_BufferFormat_eX8G8B8A8_LTFormat: buffer_format = XBGR_8888_LT; break;
266 case BEGL_BufferFormat_eR5G6B5_LTFormat: buffer_format = RGB_565_LT; break;
267 case BEGL_BufferFormat_eR5G5B5A1_LTFormat: buffer_format = RGBA_5551_LT; break;
268 case BEGL_BufferFormat_eR4G4B4A4_LTFormat: buffer_format = RGBA_4444_LT; break;
269 default : buf_error = true; break;
270 }
271#else
272 } else if (target == EGL_NATIVE_BUFFER_ANDROID) {
273 gralloc_private_handle_t *gpriv = gralloc_private_handle_from_client_buffer(buffer);
274 int res_type = gralloc_private_handle_get_res_type(gpriv);
275
276 if (res_type == GRALLOC_PRIV_TYPE_GL_RESOURCE) {
277 /* just return the a copy of the EGLImageKHR gralloc created earlier
278 see hardware/broadcom/videocore/components/graphics/gralloc/ */
279 target = EGL_IMAGE_BRCM_DUPLICATE;
280 buf[0] = (uint32_t)gralloc_private_handle_get_egl_image(gpriv);
281 vcos_log_trace("%s: converting buffer %p egl_image %d to EGL_IMAGE_BRCM_DUPLICATE",
282 __FUNCTION__, buffer, buf[0]);
283 }
284 else if (res_type == GRALLOC_PRIV_TYPE_MM_RESOURCE) {
285 /* MM image is potentially going to be used as a texture so
286 * VC EGL needs to acquire a reference to the underlying vc_image.
287 * So, we create the image in the normal way.
288 * EGL_NATIVE_BUFFER_ANDROID is passed as the target.
289 */
290 if (gpriv->gl_format == GRALLOC_MAGICS_HAL_PIXEL_FORMAT_OPAQUE)
291 target = EGL_IMAGE_BRCM_MULTIMEDIA;
292 else
293 target = EGL_IMAGE_BRCM_RAW_PIXELS;
294 buffer_width = gpriv->w;
295 buffer_height = gpriv->h;
296 buffer_stride = gpriv->stride;
297
298 buf[0] = gralloc_private_handle_get_vc_handle(gpriv);
299 vcos_log_trace("%s: converting buffer %p handle %u to EGL_IMAGE_BRCM_MULTIMEDIA",
300 __FUNCTION__, buffer, buf[0]);
301 }
302 else {
303 vcos_log_error("%s: unknown gralloc resource type %x", __FUNCTION__, res_type);
304 }
305#endif
306#else /* Not Android */
307 } else if (target == EGL_IMAGE_BRCM_VCSM && egl_init_vcsm()) {
308 struct egl_image_brcm_vcsm_info *info = (struct egl_image_brcm_vcsm_info *) buffer;
309 buf_error = true;
310 vcos_log_info("%s: EGL_IMAGE_BRCM_VCSM", __FUNCTION__); // FIXME
311
312#define IS_POT(X) ((X) && (((X) & (~(X) + 1)) == (X)))
313#define VALID_RSO_DIM(X) (IS_POT(X) && (X) >= 64 && (X) <= 2048)
314
315 // Allocate the VCSM buffer. This could be moved to VideoCore.
316 if (info && VALID_RSO_DIM(info->width) && VALID_RSO_DIM(info->height)) {
317 unsigned int vcsm_handle;
318 buffer_width = info->width;
319 buffer_height = info->height;
320 buffer_format = ABGR_8888_RSO; // Only format supported
321 buffer_stride = buffer_width << 2;
322
323 vcsm_handle = vcsm_malloc_cache(buffer_stride * buffer_height,
324 VCSM_CACHE_TYPE_HOST, "EGL_IMAGE_BRCM_VCSM");
325 if (vcsm_handle) {
326 buf[0] = vcsm_vc_hdl_from_hdl(vcsm_handle);
327 info->vcsm_handle = vcsm_handle;
328 if (buf[0])
329 buf_error = false;
330 else {
331 vcos_log_error("%s: bad VCSM handle %u", __FUNCTION__, vcsm_handle);
332 vcsm_free(vcsm_handle);
333 }
334
335 vcos_log_trace("%s: VCSM %u VC %u %ux%u %u", __FUNCTION__, vcsm_handle,
336 buf[0], buffer_width, buffer_height, buffer_stride);
337 }
338 } else {
339 vcos_log_error("VCSM buffer dimension but be POT between 64 and 2048\n");
340 }
341 } else if (target == EGL_IMAGE_BRCM_MULTIMEDIA) {
342 buf[0] = (uint32_t)buffer;
343 vcos_log_trace("%s: converting buffer handle %u to EGL_IMAGE_BRCM_MULTIMEDIA",
344 __FUNCTION__, buf[0]);
345 } else if (target == EGL_IMAGE_BRCM_MULTIMEDIA_Y) {
346 buf[0] = (uint32_t)buffer;
347 vcos_log_trace("%s: converting buffer handle %u to EGL_IMAGE_BRCM_MULTIMEDIA_Y",
348 __FUNCTION__, buf[0]);
349 } else if (target == EGL_IMAGE_BRCM_MULTIMEDIA_U) {
350 buf[0] = (uint32_t)buffer;
351 vcos_log_trace("%s: converting buffer handle %u to EGL_IMAGE_BRCM_MULTIMEDIA_U",
352 __FUNCTION__, buf[0]);
353 } else if (target == EGL_IMAGE_BRCM_MULTIMEDIA_V) {
354 buf[0] = (uint32_t)buffer;
355 vcos_log_trace("%s: converting buffer handle %u to EGL_IMAGE_BRCM_MULTIMEDIA_V",
356 __FUNCTION__, buf[0]);
357#endif
358 } else {
359 vcos_log_trace("%s:target type %x buffer %p handled on server", __FUNCTION__, target, buffer);
360 buf[0] = (uint32_t)buffer;
361 }
362 if (buf_error) {
363 thread->error = EGL_BAD_PARAMETER;
364 }
365 else {
366 EGLint texture_level = 0;
367 bool attr_error = false;
368 if (attr_list) {
369 while (!attr_error && *attr_list != EGL_NONE) {
370 switch (*attr_list++) {
371 case EGL_GL_TEXTURE_LEVEL_KHR:
372 texture_level = *attr_list++;
373 break;
374 case EGL_IMAGE_PRESERVED_KHR:
375 {
376 EGLint preserved = *attr_list++;
377 if ((preserved != EGL_FALSE) && (preserved != EGL_TRUE)) {
378 attr_error = true;
379 } /* else: ignore the actual value -- we always preserve */
380 break;
381 }
382 default:
383 attr_error = true;
384 }
385 }
386 }
387 if (attr_error) {
388 thread->error = EGL_BAD_PARAMETER;
389 }
390 else {
391#if EGL_BRCM_global_image
392 if ((target == EGL_NATIVE_PIXMAP_KHR) && (buf[1] != (uint32_t)-1)) {
393 if (platform_use_global_image_as_egl_image(buf[0], buf[1], (EGLNativePixmapType)buffer, &thread->error)) {
394 if (!khrn_global_image_map_insert(&process->global_image_egl_images,
395 process->next_global_image_egl_image,
396 buf[0] | ((uint64_t)buf[1] << 32))) {
397 thread->error = EGL_BAD_ALLOC;
398 } else {
399 result = (EGLImageKHR)(uintptr_t)process->next_global_image_egl_image;
400 thread->error = EGL_SUCCESS;
401 do {
402 process->next_global_image_egl_image = (1 << 31) |
403 (process->next_global_image_egl_image + 1);
404 } while (khrn_global_image_map_lookup(&process->global_image_egl_images,
405 process->next_global_image_egl_image));
406 }
407 }
408 } else
409#endif
410 {
411 EGLint results[2];
412
413 vcos_log_info("%s: width %d height %d target %x buffer %p", __FUNCTION__, buffer_width, buffer_height, target, buffer);
414 RPC_CALL10_OUT_CTRL(eglCreateImageKHR_impl,
415 thread,
416 EGLCREATEIMAGEKHR_ID,
417 RPC_UINT(context ? (context->type == OPENGL_ES_20 ? 2 : 1) : 0),
418 RPC_UINT(context ? context->servercontext : 0),
419 RPC_ENUM(target),
420 RPC_UINT(buf[0]),
421 RPC_UINT(buffer_format),
422 RPC_UINT(buffer_width),
423 RPC_UINT(buffer_height),
424 RPC_UINT(buffer_stride),
425 RPC_INT(texture_level),
426 results);
427
428 result = (EGLImageKHR)(intptr_t)results[0];
429 thread->error = results[1];
430
431 if (target == EGL_NATIVE_PIXMAP_CLIENT_SIDE_BRCM || target == EGL_IMAGE_FROM_SURFACE_BRCM)
432 {
433 khrn_platform_bind_pixmap_to_egl_image((EGLNativePixmapType)buffer, result, target == EGL_NATIVE_PIXMAP_CLIENT_SIDE_BRCM);
434 }
435 }
436 }
437 }
438 }
439 }
440 }
441
442 CLIENT_UNLOCK();
443 if (result == EGL_NO_IMAGE_KHR) {
444 vcos_log_error("%s: failed to create image for buffer %p target %d error 0x%x",
445 __FUNCTION__, buffer, target, thread->error);
446 } else {
447 vcos_log_trace("%s: returning EGLImageKHR %p for buffer %p target %d",
448 __FUNCTION__, result, buffer, target);
449 }
450 return result;
451}
452
453EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image)
454{
455 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
456 EGLBoolean result;
457
458 vcos_log_trace("eglDestroyImageKHR image=%d.\n", (int)image);
459
460 CLIENT_LOCK();
461
462 {
463 CLIENT_PROCESS_STATE_T *process = client_egl_get_process_state(thread, dpy, EGL_TRUE);
464 vcos_log_trace("%s: process %p image %p", __FUNCTION__, process, image);
465
466 if (!process)
467 result = EGL_FALSE;
468 else {
469 khrn_platform_unbind_pixmap_from_egl_image(image);
470#if EGL_BRCM_global_image
471 if ((uintptr_t)image & (1 << 31)) {
472 result = khrn_global_image_map_delete(&process->global_image_egl_images, (uint32_t)(uintptr_t)image) ?
473 EGL_TRUE : EGL_FALSE;
474 } else
475#endif
476 {
477 vcos_log_trace("%s: process %p image %p calling eglDestroyImageKHR_impl",
478 __FUNCTION__, process, image);
479 result = RPC_BOOLEAN_RES(RPC_CALL1_RES(eglDestroyImageKHR_impl,
480 thread,
481 EGLDESTROYIMAGEKHR_ID,
482 RPC_EGLID(image)));
483 }
484
485 if (!result) {
486 thread->error = EGL_BAD_PARAMETER;
487 }
488 }
489 }
490
491 CLIENT_UNLOCK();
492
493 return result;
494}
495
496void eglIntImageSetColorData(EGLDisplay dpy,
497 EGLImageKHR image, KHRN_IMAGE_FORMAT_T format,
498 uint32_t x_offset, uint32_t y_offset,
499 uint32_t width, uint32_t height,
500 int32_t stride, const void *data)
501{
502 CLIENT_THREAD_STATE_T *thread;
503 CLIENT_PROCESS_STATE_T *process;
504
505 if (CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process)) {
506
507 size_t chunk = KHDISPATCH_WORKSPACE_SIZE / stride;
508 const uint8_t *p = (uint8_t *)data + (y_offset*stride);
509 size_t remaining = height;
510 size_t y = y_offset;
511
512 vcos_log_trace("[%s] egl im %d (%d,%d,%d,%d)",__FUNCTION__, (uint32_t)image, x_offset, y_offset, width, height);
513
514 while (remaining) {
515 size_t n = _min(remaining, chunk);
516 size_t size = n * stride;
517
518 RPC_CALL8_IN_BULK(eglIntImageSetColorData_impl,
519 thread, EGLINTIMAGESETCOLORDATA_ID,
520 RPC_UINT(image), format, x_offset, y, width, n, stride,
521 p, size);
522
523 p += size;
524 y += n;
525 remaining -= n;
526 }
527
528 CLIENT_UNLOCK();
529 }
530}
531