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