1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, 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
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON 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
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 #define VCOS_LOG_CATEGORY (&khrn_client_log)
28
29 #include "interface/khronos/common/khrn_client_platform.h"
30 #include "interface/khronos/common/khrn_client.h"
31 #include "interface/khronos/common/khrn_client_rpc.h"
32 #include "interface/khronos/common/khrn_int_ids.h"
33 #include <stdio.h>
34 #include <string.h>
35 #include <assert.h>
36 #ifdef WANT_X
37 #include "X11/Xlib.h"
38 #endif
39
40 extern VCOS_LOG_CAT_T khrn_client_log;
41
42 extern void vc_vchi_khronos_init();
43
44 static void send_bound_pixmaps(void);
45 #ifdef WANT_X
46 static void dump_hierarchy(Window w, Window thisw, Window look, int level);
47 static void dump_ancestors(Window w);
48 #endif
49
50 //see helpers\scalerlib\scalerlib_misc.c
51 //int32_t scalerlib_convert_vcimage_to_display_element()
52 //dark blue, 1<<3 in 888
53 #define CHROMA_KEY_565 0x0001
54 //
55
56 #ifdef WANT_X
57 static Display *hacky_display = 0;
58
59 static XErrorHandler old_handler = (XErrorHandler) 0 ;
application_error_handler(Display * display,XErrorEvent * theEvent)60 static int application_error_handler(Display *display, XErrorEvent *theEvent)
61 {
62 vcos_log_trace(
63 "Ignoring Xlib error: error code %d request code %d\n",
64 theEvent->error_code,
65 theEvent->request_code) ;
66 return 0 ;
67 }
68 #endif
69
khronos_platform_semaphore_create(PLATFORM_SEMAPHORE_T * sem,int name[3],int count)70 VCOS_STATUS_T khronos_platform_semaphore_create(PLATFORM_SEMAPHORE_T *sem, int name[3], int count)
71 {
72 char buf[64];
73 vcos_snprintf(buf,sizeof(buf),"KhanSemaphore%08x%08x%08x", name[0], name[1], name[2]);
74 return vcos_named_semaphore_create(sem, buf, count);
75 }
76
khronos_platform_get_process_id()77 uint64_t khronos_platform_get_process_id()
78 {
79 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
80
81 return rpc_get_client_id(thread);
82 }
83
84 static bool process_attached = false;
85
platform_tls_get(PLATFORM_TLS_T tls)86 void *platform_tls_get(PLATFORM_TLS_T tls)
87 {
88 void *ret;
89
90 if (!process_attached)
91 /* TODO: this isn't thread safe */
92 {
93 vcos_log_trace("Attaching process");
94 client_process_attach();
95 process_attached = true;
96 tls = client_tls;
97
98 vc_vchi_khronos_init();
99 }
100
101 ret = vcos_tls_get(tls);
102 if (!ret)
103 {
104 /* The problem here is that on VCFW, the first notification we get that a thread
105 * exists at all is when it calls an arbitrary EGL function. We need to detect this
106 * case and initiliase the per-thread state.
107 *
108 * On Windows this gets done in DllMain.
109 */
110 client_thread_attach();
111 vcos_thread_at_exit(client_thread_detach, NULL);
112 ret = vcos_tls_get(tls);
113 }
114 return ret;
115 }
116
platform_tls_get_check(PLATFORM_TLS_T tls)117 void *platform_tls_get_check(PLATFORM_TLS_T tls)
118 {
119 return platform_tls_get(tls);
120 }
121
122 /* ----------------------------------------------------------------------
123 * workaround for broken platforms which don't detect threads exiting
124 * -------------------------------------------------------------------- */
platform_hint_thread_finished()125 void platform_hint_thread_finished()
126 {
127 /*
128 todo: should we do this:
129
130 vcos_thread_deregister_at_exit(client_thread_detach);
131 client_thread_detach();
132
133 here?
134 */
135 }
136
137 #ifndef KHRN_PLATFORM_VCOS_NO_MALLOC
138
139 /**
140 Allocate memory
141
142 @param size Size in bytes of memory block to allocate
143 @return pointer to memory block
144 **/
khrn_platform_malloc(size_t size,const char * name)145 void *khrn_platform_malloc(size_t size, const char * name)
146 {
147 return vcos_malloc(size, name);
148 }
149
150 /**
151 Free memory
152
153 @param v Pointer to memory area to free
154 **/
khrn_platform_free(void * v)155 void khrn_platform_free(void *v)
156 {
157 if (v)
158 {
159 vcos_free(v);
160 }
161 }
162
163 #endif
164
165 #ifdef WANT_X
166 static XImage *current_ximage = NULL;
167
ximage_to_image_format(int bits_per_pixel,unsigned long red_mask,unsigned long green_mask,unsigned long blue_mask)168 static KHRN_IMAGE_FORMAT_T ximage_to_image_format(int bits_per_pixel, unsigned long red_mask, unsigned long green_mask, unsigned long blue_mask)
169 {
170 if (bits_per_pixel == 16 /*&& red_mask == 0xf800 && green_mask == 0x07e0 && blue_mask == 0x001f*/)
171 return RGB_565_RSO;
172 //else if (bits_per_pixel == 24 && red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff)
173 // return RGB_888_RSO;
174 else if (bits_per_pixel == 24 && red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000)
175 return BGR_888_RSO;
176 else if (bits_per_pixel == 32 /*&& red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000*/)
177 return ABGR_8888_RSO; //meego uses alpha channel
178 else if (bits_per_pixel == 32 && red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff)
179 return ARGB_8888_RSO;
180 else
181 {
182 vcos_log_warn("platform_get_pixmap_info unknown image format\n");
183 return IMAGE_FORMAT_INVALID;
184 }
185 }
186
platform_get_pixmap_info(EGLNativePixmapType pixmap,KHRN_IMAGE_WRAP_T * image)187 bool platform_get_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
188 {
189 Window r;
190 int x, y;
191 unsigned int w, h, b, d;
192 KHRN_IMAGE_FORMAT_T format;
193 XImage *xi;
194 XWindowAttributes attr;
195 Status rc;
196
197 vcos_log_trace("platform_get_pixmap_info !!!");
198
199 if (!XGetGeometry(hacky_display, (Drawable)pixmap, &r, &x, &y, &w, &h, &b, &d))
200 return false;
201
202 vcos_log_trace("platform_get_pixmap_info %d geometry = %d %d %d %d",(int)pixmap,
203 x, y, w, h);
204
205 xi = XGetImage(hacky_display, (Drawable)pixmap, 0, 0, w, h, 0xffffffff, ZPixmap);
206 if (xi == NULL)
207 return false;
208
209 vcos_log_trace("platform_get_pixmap_info ximage = %d %d %d 0x%08x %d %x %x %x",
210 xi->width, xi->height, xi->bytes_per_line, (uint32_t)xi->data,
211 xi->bits_per_pixel, (uint32_t)xi->red_mask,
212 (uint32_t)xi->green_mask, (uint32_t)xi->blue_mask);
213
214 format = ximage_to_image_format(xi->bits_per_pixel, xi->red_mask, xi->green_mask, xi->blue_mask);
215 if (format == IMAGE_FORMAT_INVALID)
216 {
217 XDestroyImage(xi);
218 return false;
219 }
220
221 image->format = format;
222 image->width = xi->width;
223 image->height = xi->height;
224 image->stride = xi->bytes_per_line;
225 image->aux = NULL;
226 image->storage = xi->data;
227
228 //hacking to see if this pixmap is actually the offscreen pixmap for the window that is our current surface
229 {
230 int xw, yw;
231 unsigned int ww, hw, bw, dw;
232 unsigned long pixel;
233 Window rw,win = (Window)CLIENT_GET_THREAD_STATE()->opengl.draw->win;
234 vcos_log_trace("current EGL surface win %d ", (int)win);
235 if(win!=0)
236 {
237 /* Install our error handler to override Xlib's termination behavior */
238 old_handler = XSetErrorHandler(application_error_handler) ;
239
240 XGetGeometry(hacky_display, (Drawable)win, &rw, &xw, &yw, &ww, &hw, &bw, &dw);
241 vcos_log_trace("%dx%d", ww, hw);
242 if(ww==w && hw==h)
243 {
244 //this pixmap is the same size as our current window
245 pixel = XGetPixel(xi,w/2,h/2);
246 vcos_log_trace("Pixmap centre pixel 0x%lx%s",pixel,pixel==CHROMA_KEY_565 ? "- chroma key!!" : "");
247 if(pixel == CHROMA_KEY_565)//the pixmap is also full of our magic chroma key colour, we want to copy the server side EGL surface.
248 image->aux = (void *)CLIENT_GET_THREAD_STATE()->opengl.draw->serverbuffer ;
249 }
250
251 (void) XSetErrorHandler(old_handler) ;
252 }
253 }
254 //
255
256 current_ximage = xi;
257 return true;
258 }
259
khrn_platform_release_pixmap_info(EGLNativePixmapType pixmap,KHRN_IMAGE_WRAP_T * image)260 void khrn_platform_release_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
261 {
262 XDestroyImage(current_ximage);
263 current_ximage = NULL;
264 }
265 #else
convert_format(uint32_t format)266 static KHRN_IMAGE_FORMAT_T convert_format(uint32_t format)
267 {
268 switch (format & ~EGL_PIXEL_FORMAT_USAGE_MASK_BRCM) {
269 case EGL_PIXEL_FORMAT_ARGB_8888_PRE_BRCM: return (KHRN_IMAGE_FORMAT_T)(ABGR_8888 | IMAGE_FORMAT_PRE);
270 case EGL_PIXEL_FORMAT_ARGB_8888_BRCM: return ABGR_8888;
271 case EGL_PIXEL_FORMAT_XRGB_8888_BRCM: return XBGR_8888;
272 case EGL_PIXEL_FORMAT_RGB_565_BRCM: return RGB_565;
273 case EGL_PIXEL_FORMAT_A_8_BRCM: return A_8;
274 default:
275 vcos_assert(0);
276 return (KHRN_IMAGE_FORMAT_T)0;
277 }
278 }
279
platform_get_pixmap_info(EGLNativePixmapType pixmap,KHRN_IMAGE_WRAP_T * image)280 bool platform_get_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
281 {
282 image->format = convert_format(((uint32_t *)pixmap)[4]);
283 image->width = ((uint32_t *)pixmap)[2];
284 image->height = ((uint32_t *)pixmap)[3];
285
286 /* can't actually access data */
287 image->stride = 0;
288 image->aux = 0;
289 image->storage = 0;
290
291 return image->format != 0;
292 }
khrn_platform_release_pixmap_info(EGLNativePixmapType pixmap,KHRN_IMAGE_WRAP_T * image)293 void khrn_platform_release_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
294 {
295 /* Nothing to do */
296 }
297 #endif
298
platform_get_pixmap_server_handle(EGLNativePixmapType pixmap,uint32_t * handle)299 void platform_get_pixmap_server_handle(EGLNativePixmapType pixmap, uint32_t *handle)
300 {
301 handle[0] = ((uint32_t *)pixmap)[0];
302 handle[1] = ((uint32_t *)pixmap)[1];
303 }
304
platform_match_pixmap_api_support(EGLNativePixmapType pixmap,uint32_t api_support)305 bool platform_match_pixmap_api_support(EGLNativePixmapType pixmap, uint32_t api_support)
306 {
307 return
308 (!(api_support & EGL_OPENGL_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_GL_BRCM)) &&
309 (!(api_support & EGL_OPENGL_ES_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_GLES_BRCM)) &&
310 (!(api_support & EGL_OPENGL_ES2_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM)) &&
311 (!(api_support & EGL_OPENVG_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_VG_BRCM));
312 }
313
314 #if EGL_BRCM_global_image && EGL_KHR_image
315
platform_use_global_image_as_egl_image(uint32_t id_0,uint32_t id_1,EGLNativePixmapType pixmap,EGLint * error)316 bool platform_use_global_image_as_egl_image(uint32_t id_0, uint32_t id_1, EGLNativePixmapType pixmap, EGLint *error)
317 {
318 return true;
319 }
320
platform_acquire_global_image(uint32_t id_0,uint32_t id_1)321 void platform_acquire_global_image(uint32_t id_0, uint32_t id_1)
322 {
323 }
324
platform_release_global_image(uint32_t id_0,uint32_t id_1)325 void platform_release_global_image(uint32_t id_0, uint32_t id_1)
326 {
327 }
328
platform_get_global_image_info(uint32_t id_0,uint32_t id_1,uint32_t * pixel_format,uint32_t * width,uint32_t * height)329 void platform_get_global_image_info(uint32_t id_0, uint32_t id_1,
330 uint32_t *pixel_format, uint32_t *width, uint32_t *height)
331 {
332 EGLint id[2] = {id_0, id_1};
333 EGLint width_height_pixel_format[3];
334 verify(eglQueryGlobalImageBRCM(id, width_height_pixel_format));
335 width_height_pixel_format[2] |=
336 /* this isn't right (the flags should be those passed in to
337 * eglCreateGlobalImageBRCM), but this stuff is just for basic testing, so
338 * it doesn't really matter */
339 EGL_PIXEL_FORMAT_RENDER_GLES_BRCM | EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM |
340 EGL_PIXEL_FORMAT_RENDER_VG_BRCM | EGL_PIXEL_FORMAT_VG_IMAGE_BRCM |
341 EGL_PIXEL_FORMAT_GLES_TEXTURE_BRCM | EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM;
342 if (pixel_format) { *pixel_format = width_height_pixel_format[2]; }
343 if (width) { *width = width_height_pixel_format[0]; }
344 if (height) { *height = width_height_pixel_format[1]; }
345 }
346
347 #endif
348
platform_client_lock(void)349 void platform_client_lock(void)
350 {
351 platform_mutex_acquire(&client_mutex);
352 }
353
platform_client_release(void)354 void platform_client_release(void)
355 {
356 platform_mutex_release(&client_mutex);
357 }
358
platform_init_rpc(struct CLIENT_THREAD_STATE * state)359 void platform_init_rpc(struct CLIENT_THREAD_STATE *state)
360 {
361 assert(1);
362 }
363
platform_term_rpc(struct CLIENT_THREAD_STATE * state)364 void platform_term_rpc(struct CLIENT_THREAD_STATE *state)
365 {
366 assert(1);
367 }
368
platform_maybe_free_process(void)369 void platform_maybe_free_process(void)
370 {
371 assert(1);
372 }
373
platform_destroy_winhandle(void * a,uint32_t b)374 void platform_destroy_winhandle(void *a, uint32_t b)
375 {
376 assert(1);
377 }
378
platform_surface_update(uint32_t handle)379 void platform_surface_update(uint32_t handle)
380 {
381 /*
382 XXX This seems as good a place as any to do the client side pixmap hack.
383 (called from eglSwapBuffers)
384 */
385 send_bound_pixmaps();
386 }
387
egl_gce_win_change_image(void)388 void egl_gce_win_change_image(void)
389 {
390 assert(0);
391 }
392
platform_retrieve_pixmap_completed(EGLNativePixmapType pixmap)393 void platform_retrieve_pixmap_completed(EGLNativePixmapType pixmap)
394 {
395 assert(0);
396 }
397
platform_send_pixmap_completed(EGLNativePixmapType pixmap)398 void platform_send_pixmap_completed(EGLNativePixmapType pixmap)
399 {
400 assert(0);
401 }
402
platform_memcmp(const void * aLeft,const void * aRight,size_t aLen)403 uint32_t platform_memcmp(const void * aLeft, const void * aRight, size_t aLen)
404 {
405 return memcmp(aLeft, aRight, aLen);
406 }
407
platform_memcpy(void * aTrg,const void * aSrc,size_t aLength)408 void platform_memcpy(void * aTrg, const void * aSrc, size_t aLength)
409 {
410 memcpy(aTrg, aSrc, aLength);
411 }
412
413 #ifdef WANT_X
platform_get_handle(EGLNativeWindowType win)414 uint32_t platform_get_handle(EGLNativeWindowType win)
415 {
416 return (uint32_t)win;
417 }
418
platform_get_dimensions(EGLDisplay dpy,EGLNativeWindowType win,uint32_t * width,uint32_t * height,uint32_t * swapchain_count)419 void platform_get_dimensions(EGLDisplay dpy, EGLNativeWindowType win,
420 uint32_t *width, uint32_t *height, uint32_t *swapchain_count)
421 {
422 Window w = (Window) win;
423 XWindowAttributes attr;
424 GC gc;
425 Status rc = XGetWindowAttributes(hacky_display, w, &attr);
426
427 // check rc is OK and if it is (vcos_assert(rc == 0);?????)
428 *width = attr.width;
429 *height = attr.height;
430 *swapchain_count = 0;
431
432 /* Hackily assume if this function is called then they want to fill with GL stuff. So fill window with chromakey. */
433 vcos_log_trace("Calling XCreateGC %d",(int)w);
434
435 gc = XCreateGC(hacky_display, w, 0, NULL);
436 XSetForeground(hacky_display, gc, CHROMA_KEY_565);
437
438 vcos_log_trace("Calling XFillRectangle %d %dx%d",(int)w,attr.width, attr.height);
439
440 XFillRectangle(hacky_display, w, gc, 0, 0, attr.width, attr.height);
441
442 vcos_log_trace("Calling XFreeGC");
443
444 XFreeGC(hacky_display, gc);
445
446 vcos_log_trace("Done platform_get_dimensions");
447 //debugging
448 dump_hierarchy(attr.root, w, 0, 0);
449 }
450 #endif
451
452 #ifdef WANT_X
khrn_platform_set_display_id(EGLNativeDisplayType display_id)453 EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id)
454 {
455 if(hacky_display==0)
456 {
457 hacky_display = (Display *)display_id;
458 return (EGLDisplay)1;
459 }
460 else
461 return EGL_NO_DISPLAY;
462 }
463 #else
khrn_platform_set_display_id(EGLNativeDisplayType display_id)464 EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id)
465 {
466 if (display_id == EGL_DEFAULT_DISPLAY)
467 return (EGLDisplay)1;
468 else
469 return EGL_NO_DISPLAY;
470 }
471 #endif
472
473 #ifdef WANT_X
dump_hierarchy(Window w,Window thisw,Window look,int level)474 static void dump_hierarchy(Window w, Window thisw, Window look, int level)
475 {
476 Window root_dummy, parent_dummy, *children;
477 unsigned int i, nchildren;
478 XWindowAttributes attr;
479
480 XGetWindowAttributes(hacky_display, w, &attr);
481 XQueryTree(hacky_display, w, &root_dummy, &parent_dummy, &children, &nchildren);
482
483 for (i = 0; i < level; i++)
484 {
485 vcos_log_trace(" ");
486 }
487 vcos_log_trace( "%d %d%s%s",
488 attr.map_state, (int)w,
489 (w==look)?" <-- LOOK FOR ME!":((w==thisw)?" <-- THIS WINDOW":""),
490 children?"":" no children");
491
492 if (children)
493 {
494 for (i = 0; i < nchildren; i++)
495 {
496 dump_hierarchy(children[i], thisw, look, level + 1);
497 }
498 XFree(children);
499 }
500 }
501
dump_ancestors(Window w)502 static void dump_ancestors(Window w)
503 {
504 Window root_dummy, *children;
505 unsigned int i, nchildren;
506
507 Window grandparent,parent = w, child = 0;
508 unsigned int rlayer = ~0;
509 bool bidirectional;
510 vcos_log_trace("walking back up hierarchy");
511 while(parent)
512 {
513 bidirectional = false;
514 if(!XQueryTree(hacky_display, parent, &root_dummy, &grandparent, &children, &nchildren))
515 break;
516 if (children)
517 {
518 for (i = 0; i < nchildren; i++)
519 {
520 if (children[i] == child)
521 {
522 bidirectional = true;
523 rlayer = i;
524 }
525 }
526 XFree(children);
527 }
528 vcos_log_trace("%s%s%d", bidirectional ? "<" : "", (child>0) ? "->" : "", (int)parent);
529
530 child = parent;
531 parent = grandparent;
532
533 }
534 vcos_log_trace("->end");
535 }
536
khrn_platform_get_window_position(EGLNativeWindowType win)537 uint32_t khrn_platform_get_window_position(EGLNativeWindowType win)
538 {
539 Window w = (Window) win;
540 Window dummy;
541 XWindowAttributes attr;
542 Window look_for_me, root_dummy, root_dummy2, parent_dummy, *children;
543 int x, y;
544 unsigned int layer, i, nchildren;
545
546 //the assumption is that windows are at the 2nd level i.e. in the below
547 //root_dummy/attr.root -> look_for_me -> w
548 vcos_log_trace("Start khrn_platform_get_window_position");
549
550 XGetWindowAttributes(hacky_display, w, &attr);
551
552 vcos_log_trace("XGetWindowAttributes");
553
554 if (attr.map_state == IsViewable)
555 {
556 XTranslateCoordinates(hacky_display, w, attr.root, 0, 0, &x, &y, &dummy);
557
558 vcos_log_trace("XTranslateCoordinates");
559
560 XQueryTree(hacky_display, w, &root_dummy, &look_for_me, &children, &nchildren);
561 if (children) XFree(children);
562 XQueryTree(hacky_display, attr.root, &root_dummy2, &parent_dummy, &children, &nchildren);
563
564 vcos_log_trace("XQueryTree");
565
566 layer = ~0;
567
568 vcos_log_trace("Dumping hierarchy %d %d (%d)", (int)w, (int)look_for_me, (int)root_dummy);
569 dump_hierarchy(attr.root, w, look_for_me, 0);
570
571 if (children)
572 {
573 for (i = 0; i < nchildren; i++)
574 {
575 if (children[i] == look_for_me)
576 layer = i;
577 }
578 XFree(children);
579 }
580
581 vcos_log_trace("XFree");
582
583 if (layer == ~0)
584 {
585 vcos_log_error("EGL window isn't child of root", i);
586
587 //to try and find out where this window has gone, let us walk back up the hierarchy
588 dump_ancestors(w);
589 return ~0;
590 }
591 else
592 {
593 vcos_log_trace("End khrn_platform_get_window_position - visible");
594 return x | y << 12 | layer << 24;
595 }
596 }
597 else
598 {
599 vcos_log_trace("End khrn_platform_get_window_position - invisible");
600
601 return ~0; /* Window is invisible */
602 }
603 }
604 #else
605 static int xxx_position = 0;
khrn_platform_get_window_position(EGLNativeWindowType win)606 uint32_t khrn_platform_get_window_position(EGLNativeWindowType win)
607 {
608 return xxx_position;
609 }
610 #endif
611
612 #define NUM_PIXMAP_BINDINGS 16
613 static struct
614 {
615 bool used;
616 bool send;
617 EGLNativePixmapType pixmap;
618 EGLImageKHR egl_image;
619 } pixmap_binding[NUM_PIXMAP_BINDINGS];
620
set_egl_image_color_data(EGLImageKHR egl_image,KHRN_IMAGE_WRAP_T * image)621 static void set_egl_image_color_data(EGLImageKHR egl_image, KHRN_IMAGE_WRAP_T *image)
622 {
623 int line_size = (image->stride < 0) ? -image->stride : image->stride;
624 int lines = KHDISPATCH_WORKSPACE_SIZE / line_size;
625 int offset = 0;
626 int height = image->height;
627
628 if (khrn_image_is_brcm1(image->format))
629 lines &= ~63;
630
631 assert(lines > 0);
632
633 while (height > 0) {
634 int batch = _min(lines, height);
635 uint32_t len = batch * line_size;
636
637 CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
638 int adjusted_offset = (image->stride < 0) ? (offset + (batch - 1)) : offset;
639
640 RPC_CALL8_IN_BULK(eglIntImageSetColorData_impl,
641 thread,
642 EGLINTIMAGESETCOLORDATA_ID,
643 RPC_EGLID(egl_image),
644 RPC_UINT(image->format),
645 RPC_UINT(0),
646 RPC_INT(offset),
647 RPC_UINT(image->width),
648 RPC_INT(batch),
649 RPC_UINT(image->stride),
650 (const char *)image->storage + adjusted_offset * image->stride,
651 len);
652
653 offset += batch;
654 height -= batch;
655 }
656 }
657
send_bound_pixmap(int i)658 static void send_bound_pixmap(int i)
659 {
660 KHRN_IMAGE_WRAP_T image;
661
662 vcos_log_trace("send_bound_pixmap %d %d", i, (int)pixmap_binding[i].egl_image);
663
664 vcos_assert(i >= 0 && i < NUM_PIXMAP_BINDINGS);
665 vcos_assert(pixmap_binding[i].used);
666
667 platform_get_pixmap_info(pixmap_binding[i].pixmap, &image);
668 set_egl_image_color_data(pixmap_binding[i].egl_image, &image);
669 khrn_platform_release_pixmap_info(pixmap_binding[i].pixmap, &image);
670 }
671
send_bound_pixmaps(void)672 static void send_bound_pixmaps(void)
673 {
674 int i;
675 for (i = 0; i < NUM_PIXMAP_BINDINGS; i++)
676 {
677 if (pixmap_binding[i].used && pixmap_binding[i].send)
678 {
679 send_bound_pixmap(i);
680 }
681 }
682 }
683
khrn_platform_bind_pixmap_to_egl_image(EGLNativePixmapType pixmap,EGLImageKHR egl_image,bool send)684 void khrn_platform_bind_pixmap_to_egl_image(EGLNativePixmapType pixmap, EGLImageKHR egl_image, bool send)
685 {
686 int i;
687 for (i = 0; i < NUM_PIXMAP_BINDINGS; i++)
688 {
689 if (!pixmap_binding[i].used)
690 {
691
692 vcos_log_trace("khrn_platform_bind_pixmap_to_egl_image %d", i);
693
694 pixmap_binding[i].used = true;
695 pixmap_binding[i].pixmap = pixmap;
696 pixmap_binding[i].egl_image = egl_image;
697 pixmap_binding[i].send = send;
698 if(send)
699 send_bound_pixmap(i);
700 return;
701 }
702 }
703 vcos_assert(0); /* Not enough NUM_PIXMAP_BINDINGS? */
704 }
705
khrn_platform_unbind_pixmap_from_egl_image(EGLImageKHR egl_image)706 void khrn_platform_unbind_pixmap_from_egl_image(EGLImageKHR egl_image)
707 {
708 int i;
709 for (i = 0; i < NUM_PIXMAP_BINDINGS; i++)
710 {
711 if (pixmap_binding[i].used && pixmap_binding[i].egl_image == egl_image)
712 {
713 pixmap_binding[i].used = false;
714 }
715 }
716 }
717
718 #ifdef EGL_SERVER_DISPMANX
719 #define NUM_WIN 6
720
721 static bool have_default_dwin[NUM_WIN];
722 static EGL_DISPMANX_WINDOW_T default_dwin[NUM_WIN];
723
check_default(EGLNativeWindowType win)724 static EGL_DISPMANX_WINDOW_T *check_default(EGLNativeWindowType win)
725 {
726 int wid = (int)win;
727 if(wid>-NUM_WIN && wid <=0) {
728 /*
729 * Special identifiers indicating the default windows. Either use the
730 * one we've got or create a new one
731 * simple hack for VMCSX_VC4_1.0 release to demonstrate concurrent running of apps under linux
732
733 * win == 0 => full screen window on display 0
734 * win == -1 => 1/4 screen top left window on display 0
735 * win == -2 => 1/4 screen top right window on display 0
736 * win == -3 => 1/4 screen bottom left window on display 0
737 * win == -4 => 1/4 screen bottom right window on display 0
738 * win == -5 => full screen window on display 2
739
740 * it is expected that Open WFC will provide a proper mechanism in the near future
741 */
742 wid = -wid;
743
744 if (!have_default_dwin[wid]) {
745 DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open( (wid == 5) ? 2 : 0 );
746 DISPMANX_MODEINFO_T info;
747 vc_dispmanx_display_get_info(display, &info);
748 int32_t dw = info.width, dh = info.height;
749
750 DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start( 0 );
751 VC_DISPMANX_ALPHA_T alpha = {DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0};
752 VC_RECT_T dst_rect;
753 VC_RECT_T src_rect;
754
755 int x = 0, y = 0, width = 0, height = 0, layer = 0;
756
757 switch(wid)
758 {
759 case 0:
760 x = 0; y = 0; width = dw; height = dh; layer = 0; break;
761 case 1:
762 x = 0; y = 0; width = dw/2; height = dh/2; layer = 0; break;
763 case 2:
764 x = dw/2; y = 0; width = dw/2; height = dh/2; layer = 0; break;
765 case 3:
766 x = 0; y = dh/2; width = dw/2; height = dh/2; layer = 0; break;
767 case 4:
768 x = dw/2; y = dh/2; width = dw/2; height = dh/2; layer = 0; break;
769 case 5:
770 x = 0; y = 0; width = dw; height = dh; layer = 0; break;
771 }
772
773 src_rect.x = 0;
774 src_rect.y = 0;
775 src_rect.width = width << 16;
776 src_rect.height = height << 16;
777
778 dst_rect.x = x;
779 dst_rect.y = y;
780 dst_rect.width = width;
781 dst_rect.height = height;
782
783 default_dwin[wid].element = vc_dispmanx_element_add ( update, display,
784 layer, &dst_rect, 0/*src*/,
785 &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, 0/*transform*/);
786
787 default_dwin[wid].width = width;
788 default_dwin[wid].height = height;
789
790 vc_dispmanx_update_submit_sync( update );
791
792 have_default_dwin[wid] = true;
793 }
794 return &default_dwin[wid];
795 } else
796 return (EGL_DISPMANX_WINDOW_T*)win;
797 }
798
platform_get_dimensions(EGLDisplay dpy,EGLNativeWindowType win,uint32_t * width,uint32_t * height,uint32_t * swapchain_count)799 void platform_get_dimensions(EGLDisplay dpy, EGLNativeWindowType win,
800 uint32_t *width, uint32_t *height, uint32_t *swapchain_count)
801 {
802 EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
803 vcos_assert(dwin);
804 vcos_assert(dwin->width < 1<<16); // sanity check
805 vcos_assert(dwin->height < 1<<16); // sanity check
806 *width = dwin->width;
807 *height = dwin->height;
808 *swapchain_count = 0;
809 }
810
platform_get_handle(EGLDisplay dpy,EGLNativeWindowType win)811 uint32_t platform_get_handle(EGLDisplay dpy, EGLNativeWindowType win)
812 {
813 EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
814 vcos_assert(dwin);
815 vcos_assert(dwin->width < 1<<16); // sanity check
816 vcos_assert(dwin->height < 1<<16); // sanity check
817 return dwin->element;
818 }
819
820 #endif
821
platform_get_color_format(uint32_t format)822 uint32_t platform_get_color_format ( uint32_t format ) { return format; }
platform_dequeue(EGLDisplay dpy,EGLNativeWindowType window)823 void platform_dequeue(EGLDisplay dpy, EGLNativeWindowType window) {}
824