mirror of
https://github.com/raspberrypi/userland.git
synced 2025-12-06 04:49:12 +00:00
826 lines
24 KiB
C
826 lines
24 KiB
C
/*
|
|
Copyright (c) 2012, Broadcom Europe Ltd
|
|
All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* Neither the name of the copyright holder nor the
|
|
names of its contributors may be used to endorse or promote products
|
|
derived from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
#define VCOS_LOG_CATEGORY (&khrn_client_log)
|
|
|
|
#include "interface/khronos/common/khrn_client_platform.h"
|
|
#include "interface/khronos/common/khrn_client.h"
|
|
#include "interface/khronos/common/khrn_client_rpc.h"
|
|
#include "interface/khronos/common/khrn_int_ids.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#ifdef WANT_X
|
|
#include "X11/Xlib.h"
|
|
#endif
|
|
|
|
extern VCOS_LOG_CAT_T khrn_client_log;
|
|
|
|
extern void vc_vchi_khronos_init();
|
|
|
|
static void send_bound_pixmaps(void);
|
|
#ifdef WANT_X
|
|
static void dump_hierarchy(Window w, Window thisw, Window look, int level);
|
|
static void dump_ancestors(Window w);
|
|
#endif
|
|
|
|
//see helpers\scalerlib\scalerlib_misc.c
|
|
//int32_t scalerlib_convert_vcimage_to_display_element()
|
|
//dark blue, 1<<3 in 888
|
|
#define CHROMA_KEY_565 0x0001
|
|
//
|
|
|
|
#ifdef WANT_X
|
|
static Display *hacky_display = 0;
|
|
|
|
static XErrorHandler old_handler = (XErrorHandler) 0 ;
|
|
static int application_error_handler(Display *display, XErrorEvent *theEvent)
|
|
{
|
|
vcos_log_trace(
|
|
"Ignoring Xlib error: error code %d request code %d\n",
|
|
theEvent->error_code,
|
|
theEvent->request_code) ;
|
|
return 0 ;
|
|
}
|
|
#endif
|
|
|
|
|
|
VCOS_STATUS_T khronos_platform_semaphore_create(PLATFORM_SEMAPHORE_T *sem, int name[3], int count)
|
|
{
|
|
char buf[64];
|
|
vcos_snprintf(buf,sizeof(buf),"KhanSemaphore%08x%08x%08x", name[0], name[1], name[2]);
|
|
return vcos_named_semaphore_create(sem, buf, count);
|
|
}
|
|
|
|
uint64_t khronos_platform_get_process_id()
|
|
{
|
|
return vcos_process_id_current();
|
|
}
|
|
|
|
static bool process_attached = false;
|
|
|
|
void *platform_tls_get(PLATFORM_TLS_T tls)
|
|
{
|
|
void *ret;
|
|
|
|
if (!process_attached)
|
|
/* TODO: this isn't thread safe */
|
|
{
|
|
vcos_log_trace("Attaching process");
|
|
client_process_attach();
|
|
process_attached = true;
|
|
tls = client_tls;
|
|
|
|
vc_vchi_khronos_init();
|
|
}
|
|
|
|
ret = vcos_tls_get(tls);
|
|
if (!ret)
|
|
{
|
|
/* The problem here is that on VCFW, the first notification we get that a thread
|
|
* exists at all is when it calls an arbitrary EGL function. We need to detect this
|
|
* case and initiliase the per-thread state.
|
|
*
|
|
* On Windows this gets done in DllMain.
|
|
*/
|
|
client_thread_attach();
|
|
vcos_thread_at_exit(client_thread_detach, NULL);
|
|
ret = vcos_tls_get(tls);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void *platform_tls_get_check(PLATFORM_TLS_T tls)
|
|
{
|
|
return vcos_tls_get(tls);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* workaround for broken platforms which don't detect threads exiting
|
|
* -------------------------------------------------------------------- */
|
|
void platform_hint_thread_finished()
|
|
{
|
|
/*
|
|
todo: should we do this:
|
|
|
|
vcos_thread_deregister_at_exit(client_thread_detach);
|
|
client_thread_detach();
|
|
|
|
here?
|
|
*/
|
|
}
|
|
|
|
#ifndef KHRN_PLATFORM_VCOS_NO_MALLOC
|
|
|
|
/**
|
|
Allocate memory
|
|
|
|
@param size Size in bytes of memory block to allocate
|
|
@return pointer to memory block
|
|
**/
|
|
void *khrn_platform_malloc(size_t size, const char * name)
|
|
{
|
|
return vcos_malloc(size, name);
|
|
}
|
|
|
|
/**
|
|
Free memory
|
|
|
|
@param v Pointer to memory area to free
|
|
**/
|
|
void khrn_platform_free(void *v)
|
|
{
|
|
if (v)
|
|
{
|
|
vcos_free(v);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#ifdef WANT_X
|
|
static XImage *current_ximage = NULL;
|
|
|
|
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)
|
|
{
|
|
if (bits_per_pixel == 16 /*&& red_mask == 0xf800 && green_mask == 0x07e0 && blue_mask == 0x001f*/)
|
|
return RGB_565_RSO;
|
|
//else if (bits_per_pixel == 24 && red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff)
|
|
// return RGB_888_RSO;
|
|
else if (bits_per_pixel == 24 && red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000)
|
|
return BGR_888_RSO;
|
|
else if (bits_per_pixel == 32 /*&& red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000*/)
|
|
return ABGR_8888_RSO; //meego uses alpha channel
|
|
else if (bits_per_pixel == 32 && red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff)
|
|
return ARGB_8888_RSO;
|
|
else
|
|
{
|
|
vcos_log_warn("platform_get_pixmap_info unknown image format\n");
|
|
return IMAGE_FORMAT_INVALID;
|
|
}
|
|
}
|
|
|
|
bool platform_get_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
|
|
{
|
|
Window r;
|
|
int x, y;
|
|
unsigned int w, h, b, d;
|
|
KHRN_IMAGE_FORMAT_T format;
|
|
XImage *xi;
|
|
XWindowAttributes attr;
|
|
Status rc;
|
|
|
|
vcos_log_trace("platform_get_pixmap_info !!!");
|
|
|
|
if (!XGetGeometry(hacky_display, (Drawable)pixmap, &r, &x, &y, &w, &h, &b, &d))
|
|
return false;
|
|
|
|
vcos_log_trace("platform_get_pixmap_info %d geometry = %d %d %d %d",(int)pixmap,
|
|
x, y, w, h);
|
|
|
|
xi = XGetImage(hacky_display, (Drawable)pixmap, 0, 0, w, h, 0xffffffff, ZPixmap);
|
|
if (xi == NULL)
|
|
return false;
|
|
|
|
vcos_log_trace("platform_get_pixmap_info ximage = %d %d %d 0x%08x %d %x %x %x",
|
|
xi->width, xi->height, xi->bytes_per_line, (uint32_t)xi->data,
|
|
xi->bits_per_pixel, (uint32_t)xi->red_mask,
|
|
(uint32_t)xi->green_mask, (uint32_t)xi->blue_mask);
|
|
|
|
format = ximage_to_image_format(xi->bits_per_pixel, xi->red_mask, xi->green_mask, xi->blue_mask);
|
|
if (format == IMAGE_FORMAT_INVALID)
|
|
{
|
|
XDestroyImage(xi);
|
|
return false;
|
|
}
|
|
|
|
image->format = format;
|
|
image->width = xi->width;
|
|
image->height = xi->height;
|
|
image->stride = xi->bytes_per_line;
|
|
image->aux = NULL;
|
|
image->storage = xi->data;
|
|
|
|
//hacking to see if this pixmap is actually the offscreen pixmap for the window that is our current surface
|
|
{
|
|
int xw, yw;
|
|
unsigned int ww, hw, bw, dw;
|
|
unsigned long pixel;
|
|
Window rw,win = (Window)CLIENT_GET_THREAD_STATE()->opengl.draw->win;
|
|
vcos_log_trace("current EGL surface win %d ", (int)win);
|
|
if(win!=0)
|
|
{
|
|
/* Install our error handler to override Xlib's termination behavior */
|
|
old_handler = XSetErrorHandler(application_error_handler) ;
|
|
|
|
XGetGeometry(hacky_display, (Drawable)win, &rw, &xw, &yw, &ww, &hw, &bw, &dw);
|
|
vcos_log_trace("%dx%d", ww, hw);
|
|
if(ww==w && hw==h)
|
|
{
|
|
//this pixmap is the same size as our current window
|
|
pixel = XGetPixel(xi,w/2,h/2);
|
|
vcos_log_trace("Pixmap centre pixel 0x%lx%s",pixel,pixel==CHROMA_KEY_565 ? "- chroma key!!" : "");
|
|
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.
|
|
image->aux = (void *)CLIENT_GET_THREAD_STATE()->opengl.draw->serverbuffer ;
|
|
}
|
|
|
|
(void) XSetErrorHandler(old_handler) ;
|
|
}
|
|
}
|
|
//
|
|
|
|
current_ximage = xi;
|
|
return true;
|
|
}
|
|
|
|
void khrn_platform_release_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
|
|
{
|
|
XDestroyImage(current_ximage);
|
|
current_ximage = NULL;
|
|
}
|
|
#else
|
|
static KHRN_IMAGE_FORMAT_T convert_format(uint32_t format)
|
|
{
|
|
switch (format & ~EGL_PIXEL_FORMAT_USAGE_MASK_BRCM) {
|
|
case EGL_PIXEL_FORMAT_ARGB_8888_PRE_BRCM: return (KHRN_IMAGE_FORMAT_T)(ABGR_8888 | IMAGE_FORMAT_PRE);
|
|
case EGL_PIXEL_FORMAT_ARGB_8888_BRCM: return ABGR_8888;
|
|
case EGL_PIXEL_FORMAT_XRGB_8888_BRCM: return XBGR_8888;
|
|
case EGL_PIXEL_FORMAT_RGB_565_BRCM: return RGB_565;
|
|
case EGL_PIXEL_FORMAT_A_8_BRCM: return A_8;
|
|
default: vcos_verify(0); return (KHRN_IMAGE_FORMAT_T)0;
|
|
}
|
|
}
|
|
|
|
bool platform_get_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
|
|
{
|
|
image->format = convert_format(((uint32_t *)pixmap)[4]);
|
|
image->width = ((uint32_t *)pixmap)[2];
|
|
image->height = ((uint32_t *)pixmap)[3];
|
|
|
|
/* can't actually access data */
|
|
image->stride = 0;
|
|
image->aux = 0;
|
|
image->storage = 0;
|
|
|
|
return image->format != 0;
|
|
}
|
|
void khrn_platform_release_pixmap_info(EGLNativePixmapType pixmap, KHRN_IMAGE_WRAP_T *image)
|
|
{
|
|
/* Nothing to do */
|
|
}
|
|
#endif
|
|
|
|
void platform_get_pixmap_server_handle(EGLNativePixmapType pixmap, uint32_t *handle)
|
|
{
|
|
handle[0] = ((uint32_t *)pixmap)[0];
|
|
handle[1] = ((uint32_t *)pixmap)[1];
|
|
}
|
|
|
|
bool platform_match_pixmap_api_support(EGLNativePixmapType pixmap, uint32_t api_support)
|
|
{
|
|
return
|
|
(!(api_support & EGL_OPENGL_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_GL_BRCM)) &&
|
|
(!(api_support & EGL_OPENGL_ES_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_GLES_BRCM)) &&
|
|
(!(api_support & EGL_OPENGL_ES2_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM)) &&
|
|
(!(api_support & EGL_OPENVG_BIT) || (((uint32_t *)pixmap)[4] & EGL_PIXEL_FORMAT_RENDER_VG_BRCM));
|
|
}
|
|
|
|
#if EGL_BRCM_global_image && EGL_KHR_image
|
|
|
|
bool platform_use_global_image_as_egl_image(uint32_t id_0, uint32_t id_1, EGLNativePixmapType pixmap, EGLint *error)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void platform_acquire_global_image(uint32_t id_0, uint32_t id_1)
|
|
{
|
|
}
|
|
|
|
void platform_release_global_image(uint32_t id_0, uint32_t id_1)
|
|
{
|
|
}
|
|
|
|
void platform_get_global_image_info(uint32_t id_0, uint32_t id_1,
|
|
uint32_t *pixel_format, uint32_t *width, uint32_t *height)
|
|
{
|
|
EGLint id[2] = {id_0, id_1};
|
|
EGLint width_height_pixel_format[3];
|
|
verify(eglQueryGlobalImageBRCM(id, width_height_pixel_format));
|
|
width_height_pixel_format[2] |=
|
|
/* this isn't right (the flags should be those passed in to
|
|
* eglCreateGlobalImageBRCM), but this stuff is just for basic testing, so
|
|
* it doesn't really matter */
|
|
EGL_PIXEL_FORMAT_RENDER_GLES_BRCM | EGL_PIXEL_FORMAT_RENDER_GLES2_BRCM |
|
|
EGL_PIXEL_FORMAT_RENDER_VG_BRCM | EGL_PIXEL_FORMAT_VG_IMAGE_BRCM |
|
|
EGL_PIXEL_FORMAT_GLES_TEXTURE_BRCM | EGL_PIXEL_FORMAT_GLES2_TEXTURE_BRCM;
|
|
if (pixel_format) { *pixel_format = width_height_pixel_format[2]; }
|
|
if (width) { *width = width_height_pixel_format[0]; }
|
|
if (height) { *height = width_height_pixel_format[1]; }
|
|
}
|
|
|
|
#endif
|
|
|
|
void platform_client_lock(void)
|
|
{
|
|
platform_mutex_acquire(&client_mutex);
|
|
}
|
|
|
|
void platform_client_release(void)
|
|
{
|
|
platform_mutex_release(&client_mutex);
|
|
}
|
|
|
|
void platform_init_rpc(struct CLIENT_THREAD_STATE *state)
|
|
{
|
|
assert(1);
|
|
}
|
|
|
|
void platform_term_rpc(struct CLIENT_THREAD_STATE *state)
|
|
{
|
|
assert(1);
|
|
}
|
|
|
|
void platform_maybe_free_process(void)
|
|
{
|
|
assert(1);
|
|
}
|
|
|
|
void platform_destroy_winhandle(void *a, uint32_t b)
|
|
{
|
|
assert(1);
|
|
}
|
|
|
|
void platform_surface_update(uint32_t handle)
|
|
{
|
|
/*
|
|
XXX This seems as good a place as any to do the client side pixmap hack.
|
|
(called from eglSwapBuffers)
|
|
*/
|
|
send_bound_pixmaps();
|
|
}
|
|
|
|
void egl_gce_win_change_image(void)
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
void platform_retrieve_pixmap_completed(EGLNativePixmapType pixmap)
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
void platform_send_pixmap_completed(EGLNativePixmapType pixmap)
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
uint32_t platform_memcmp(const void * aLeft, const void * aRight, size_t aLen)
|
|
{
|
|
return memcmp(aLeft, aRight, aLen);
|
|
}
|
|
|
|
void platform_memcpy(void * aTrg, const void * aSrc, size_t aLength)
|
|
{
|
|
memcpy(aTrg, aSrc, aLength);
|
|
}
|
|
|
|
|
|
#ifdef WANT_X
|
|
uint32_t platform_get_handle(EGLNativeWindowType win)
|
|
{
|
|
return (uint32_t)win;
|
|
}
|
|
|
|
void platform_get_dimensions(EGLDisplay dpy, EGLNativeWindowType win,
|
|
uint32_t *width, uint32_t *height, uint32_t *swapchain_count)
|
|
{
|
|
Window w = (Window) win;
|
|
XWindowAttributes attr;
|
|
GC gc;
|
|
Status rc = XGetWindowAttributes(hacky_display, w, &attr);
|
|
|
|
// check rc is OK and if it is (vcos_assert(rc == 0);?????)
|
|
*width = attr.width;
|
|
*height = attr.height;
|
|
*swapchain_count = 0;
|
|
|
|
/* Hackily assume if this function is called then they want to fill with GL stuff. So fill window with chromakey. */
|
|
vcos_log_trace("Calling XCreateGC %d",(int)w);
|
|
|
|
gc = XCreateGC(hacky_display, w, 0, NULL);
|
|
XSetForeground(hacky_display, gc, CHROMA_KEY_565);
|
|
|
|
vcos_log_trace("Calling XFillRectangle %d %dx%d",(int)w,attr.width, attr.height);
|
|
|
|
XFillRectangle(hacky_display, w, gc, 0, 0, attr.width, attr.height);
|
|
|
|
vcos_log_trace("Calling XFreeGC");
|
|
|
|
XFreeGC(hacky_display, gc);
|
|
|
|
vcos_log_trace("Done platform_get_dimensions");
|
|
//debugging
|
|
dump_hierarchy(attr.root, w, 0, 0);
|
|
}
|
|
#endif
|
|
|
|
#ifdef WANT_X
|
|
EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id)
|
|
{
|
|
if(hacky_display==0)
|
|
{
|
|
hacky_display = (Display *)display_id;
|
|
return (EGLDisplay)1;
|
|
}
|
|
else
|
|
return EGL_NO_DISPLAY;
|
|
}
|
|
#else
|
|
EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id)
|
|
{
|
|
if (display_id == EGL_DEFAULT_DISPLAY)
|
|
return (EGLDisplay)1;
|
|
else
|
|
return EGL_NO_DISPLAY;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WANT_X
|
|
static void dump_hierarchy(Window w, Window thisw, Window look, int level)
|
|
{
|
|
Window root_dummy, parent_dummy, *children;
|
|
unsigned int i, nchildren;
|
|
XWindowAttributes attr;
|
|
|
|
XGetWindowAttributes(hacky_display, w, &attr);
|
|
XQueryTree(hacky_display, w, &root_dummy, &parent_dummy, &children, &nchildren);
|
|
|
|
for (i = 0; i < level; i++)
|
|
{
|
|
vcos_log_trace(" ");
|
|
}
|
|
vcos_log_trace( "%d %d%s%s",
|
|
attr.map_state, (int)w,
|
|
(w==look)?" <-- LOOK FOR ME!":((w==thisw)?" <-- THIS WINDOW":""),
|
|
children?"":" no children");
|
|
|
|
if (children)
|
|
{
|
|
for (i = 0; i < nchildren; i++)
|
|
{
|
|
dump_hierarchy(children[i], thisw, look, level + 1);
|
|
}
|
|
XFree(children);
|
|
}
|
|
}
|
|
|
|
static void dump_ancestors(Window w)
|
|
{
|
|
Window root_dummy, *children;
|
|
unsigned int i, nchildren;
|
|
|
|
Window grandparent,parent = w, child = 0;
|
|
unsigned int rlayer = ~0;
|
|
bool bidirectional;
|
|
vcos_log_trace("walking back up heirarchy");
|
|
while(parent)
|
|
{
|
|
bidirectional = false;
|
|
if(!XQueryTree(hacky_display, parent, &root_dummy, &grandparent, &children, &nchildren))
|
|
break;
|
|
if (children)
|
|
{
|
|
for (i = 0; i < nchildren; i++)
|
|
{
|
|
if (children[i] == child)
|
|
{
|
|
bidirectional = true;
|
|
rlayer = i;
|
|
}
|
|
}
|
|
XFree(children);
|
|
}
|
|
vcos_log_trace("%s%s%d", bidirectional ? "<" : "", (child>0) ? "->" : "", (int)parent);
|
|
|
|
child = parent;
|
|
parent = grandparent;
|
|
|
|
}
|
|
vcos_log_trace("->end");
|
|
}
|
|
|
|
|
|
uint32_t khrn_platform_get_window_position(EGLNativeWindowType win)
|
|
{
|
|
Window w = (Window) win;
|
|
Window dummy;
|
|
XWindowAttributes attr;
|
|
Window look_for_me, root_dummy, root_dummy2, parent_dummy, *children;
|
|
int x, y;
|
|
unsigned int layer, i, nchildren;
|
|
|
|
//the assumption is that windows are at the 2nd level i.e. in the below
|
|
//root_dummy/attr.root -> look_for_me -> w
|
|
vcos_log_trace("Start khrn_platform_get_window_position");
|
|
|
|
XGetWindowAttributes(hacky_display, w, &attr);
|
|
|
|
vcos_log_trace("XGetWindowAttributes");
|
|
|
|
if (attr.map_state == IsViewable)
|
|
{
|
|
XTranslateCoordinates(hacky_display, w, attr.root, 0, 0, &x, &y, &dummy);
|
|
|
|
vcos_log_trace("XTranslateCoordinates");
|
|
|
|
XQueryTree(hacky_display, w, &root_dummy, &look_for_me, &children, &nchildren);
|
|
if (children) XFree(children);
|
|
XQueryTree(hacky_display, attr.root, &root_dummy2, &parent_dummy, &children, &nchildren);
|
|
|
|
vcos_log_trace("XQueryTree");
|
|
|
|
layer = ~0;
|
|
|
|
vcos_log_trace("Dumping hierarchy %d %d (%d)", (int)w, (int)look_for_me, (int)root_dummy);
|
|
dump_hierarchy(attr.root, w, look_for_me, 0);
|
|
|
|
if (children)
|
|
{
|
|
for (i = 0; i < nchildren; i++)
|
|
{
|
|
if (children[i] == look_for_me)
|
|
layer = i;
|
|
}
|
|
XFree(children);
|
|
}
|
|
|
|
vcos_log_trace("XFree");
|
|
|
|
if (layer == ~0)
|
|
{
|
|
vcos_log_error("EGL window isn't child of root", i);
|
|
|
|
//to try and find out where this window has gone, let us walk back up the heirarchy
|
|
dump_ancestors(w);
|
|
return ~0;
|
|
}
|
|
else
|
|
{
|
|
vcos_log_trace("End khrn_platform_get_window_position - visible");
|
|
return x | y << 12 | layer << 24;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vcos_log_trace("End khrn_platform_get_window_position - invisible");
|
|
|
|
return ~0; /* Window is invisible */
|
|
}
|
|
}
|
|
#else
|
|
static int xxx_position = 0;
|
|
uint32_t khrn_platform_get_window_position(EGLNativeWindowType win)
|
|
{
|
|
return xxx_position;
|
|
}
|
|
#endif
|
|
|
|
#define NUM_PIXMAP_BINDINGS 16
|
|
static struct
|
|
{
|
|
bool used;
|
|
bool send;
|
|
EGLNativePixmapType pixmap;
|
|
EGLImageKHR egl_image;
|
|
} pixmap_binding[NUM_PIXMAP_BINDINGS];
|
|
|
|
static void set_egl_image_color_data(EGLImageKHR egl_image, KHRN_IMAGE_WRAP_T *image)
|
|
{
|
|
int line_size = (image->stride < 0) ? -image->stride : image->stride;
|
|
int lines = KHDISPATCH_WORKSPACE_SIZE / line_size;
|
|
int offset = 0;
|
|
int height = image->height;
|
|
|
|
if (khrn_image_is_tformat(image->format))
|
|
lines &= ~63;
|
|
|
|
assert(lines > 0);
|
|
|
|
while (height > 0) {
|
|
int batch = _min(lines, height);
|
|
uint32_t len = batch * line_size;
|
|
|
|
CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
|
|
int adjusted_offset = (image->stride < 0) ? (offset + (batch - 1)) : offset;
|
|
|
|
RPC_CALL8_IN_BULK(eglIntImageSetColorData_impl,
|
|
thread,
|
|
EGLINTIMAGESETCOLORDATA_ID,
|
|
RPC_EGLID(egl_image),
|
|
RPC_UINT(image->format),
|
|
RPC_UINT(0),
|
|
RPC_INT(offset),
|
|
RPC_UINT(image->width),
|
|
RPC_INT(batch),
|
|
RPC_UINT(image->stride),
|
|
(const char *)image->storage + adjusted_offset * image->stride,
|
|
len);
|
|
|
|
offset += batch;
|
|
height -= batch;
|
|
}
|
|
}
|
|
|
|
static void send_bound_pixmap(int i)
|
|
{
|
|
KHRN_IMAGE_WRAP_T image;
|
|
|
|
vcos_log_trace("send_bound_pixmap %d %d", i, (int)pixmap_binding[i].egl_image);
|
|
|
|
vcos_assert(i >= 0 && i < NUM_PIXMAP_BINDINGS);
|
|
vcos_assert(pixmap_binding[i].used);
|
|
|
|
platform_get_pixmap_info(pixmap_binding[i].pixmap, &image);
|
|
set_egl_image_color_data(pixmap_binding[i].egl_image, &image);
|
|
khrn_platform_release_pixmap_info(pixmap_binding[i].pixmap, &image);
|
|
}
|
|
|
|
static void send_bound_pixmaps(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < NUM_PIXMAP_BINDINGS; i++)
|
|
{
|
|
if (pixmap_binding[i].used && pixmap_binding[i].send)
|
|
{
|
|
send_bound_pixmap(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void khrn_platform_bind_pixmap_to_egl_image(EGLNativePixmapType pixmap, EGLImageKHR egl_image, bool send)
|
|
{
|
|
int i;
|
|
for (i = 0; i < NUM_PIXMAP_BINDINGS; i++)
|
|
{
|
|
if (!pixmap_binding[i].used)
|
|
{
|
|
|
|
vcos_log_trace("khrn_platform_bind_pixmap_to_egl_image %d", i);
|
|
|
|
pixmap_binding[i].used = true;
|
|
pixmap_binding[i].pixmap = pixmap;
|
|
pixmap_binding[i].egl_image = egl_image;
|
|
pixmap_binding[i].send = send;
|
|
if(send)
|
|
send_bound_pixmap(i);
|
|
return;
|
|
}
|
|
}
|
|
vcos_assert(0); /* Not enough NUM_PIXMAP_BINDINGS? */
|
|
}
|
|
|
|
void khrn_platform_unbind_pixmap_from_egl_image(EGLImageKHR egl_image)
|
|
{
|
|
int i;
|
|
for (i = 0; i < NUM_PIXMAP_BINDINGS; i++)
|
|
{
|
|
if (pixmap_binding[i].used && pixmap_binding[i].egl_image == egl_image)
|
|
{
|
|
pixmap_binding[i].used = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef EGL_SERVER_DISPMANX
|
|
#define NUM_WIN 6
|
|
|
|
static bool have_default_dwin[NUM_WIN];
|
|
static EGL_DISPMANX_WINDOW_T default_dwin[NUM_WIN];
|
|
|
|
static EGL_DISPMANX_WINDOW_T *check_default(EGLNativeWindowType win)
|
|
{
|
|
int wid = (int)win;
|
|
if(wid>-NUM_WIN && wid <=0) {
|
|
/*
|
|
* Special identifiers indicating the default windows. Either use the
|
|
* one we've got or create a new one
|
|
* simple hack for VMCSX_VC4_1.0 release to demonstrate concurrent running of apps under linux
|
|
|
|
* win == 0 => full screen window on display 0
|
|
* win == -1 => 1/4 screen top left window on display 0
|
|
* win == -2 => 1/4 screen top right window on display 0
|
|
* win == -3 => 1/4 screen bottom left window on display 0
|
|
* win == -4 => 1/4 screen bottom right window on display 0
|
|
* win == -5 => full screen window on display 2
|
|
|
|
* it is expected that Open WFC will provide a proper mechanism in the near future
|
|
*/
|
|
wid = -wid;
|
|
|
|
if (!have_default_dwin[wid]) {
|
|
DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open( (wid == 5) ? 2 : 0 );
|
|
DISPMANX_MODEINFO_T info;
|
|
vc_dispmanx_display_get_info(display, &info);
|
|
int32_t dw = info.width, dh = info.height;
|
|
|
|
DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start( 0 );
|
|
VC_DISPMANX_ALPHA_T alpha = {DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0};
|
|
VC_RECT_T dst_rect;
|
|
VC_RECT_T src_rect;
|
|
|
|
int x, y, width, height, layer;
|
|
|
|
switch(wid)
|
|
{
|
|
case 0:
|
|
x = 0; y = 0; width = dw; height = dh; layer = 0; break;
|
|
case 1:
|
|
x = 0; y = 0; width = dw/2; height = dh/2; layer = 0; break;
|
|
case 2:
|
|
x = dw/2; y = 0; width = dw/2; height = dh/2; layer = 0; break;
|
|
case 3:
|
|
x = 0; y = dh/2; width = dw/2; height = dh/2; layer = 0; break;
|
|
case 4:
|
|
x = dw/2; y = dh/2; width = dw/2; height = dh/2; layer = 0; break;
|
|
case 5:
|
|
x = 0; y = 0; width = dw; height = dh; layer = 0; break;
|
|
}
|
|
|
|
src_rect.x = 0;
|
|
src_rect.y = 0;
|
|
src_rect.width = width << 16;
|
|
src_rect.height = height << 16;
|
|
|
|
dst_rect.x = x;
|
|
dst_rect.y = y;
|
|
dst_rect.width = width;
|
|
dst_rect.height = height;
|
|
|
|
default_dwin[wid].element = vc_dispmanx_element_add ( update, display,
|
|
layer, &dst_rect, 0/*src*/,
|
|
&src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0/*clamp*/, 0/*transform*/);
|
|
|
|
default_dwin[wid].width = width;
|
|
default_dwin[wid].height = height;
|
|
|
|
vc_dispmanx_update_submit_sync( update );
|
|
|
|
have_default_dwin[wid] = true;
|
|
}
|
|
return &default_dwin[wid];
|
|
} else
|
|
return (EGL_DISPMANX_WINDOW_T*)win;
|
|
}
|
|
|
|
|
|
void platform_get_dimensions(EGLDisplay dpy, EGLNativeWindowType win,
|
|
uint32_t *width, uint32_t *height, uint32_t *swapchain_count)
|
|
{
|
|
EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
|
|
vcos_assert(dwin);
|
|
vcos_assert(dwin->width < 1<<16); // sanity check
|
|
vcos_assert(dwin->height < 1<<16); // sanity check
|
|
*width = dwin->width;
|
|
*height = dwin->height;
|
|
*swapchain_count = 0;
|
|
}
|
|
|
|
uint32_t platform_get_handle(EGLDisplay dpy, EGLNativeWindowType win)
|
|
{
|
|
EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
|
|
vcos_assert(dwin);
|
|
vcos_assert(dwin->width < 1<<16); // sanity check
|
|
vcos_assert(dwin->height < 1<<16); // sanity check
|
|
return dwin->element;
|
|
}
|
|
|
|
#endif
|
|
|
|
uint32_t platform_get_color_format ( uint32_t format ) { return format; }
|
|
void platform_dequeue(EGLDisplay dpy, EGLNativeWindowType window) {}
|