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