From f581efc36b342bc65d714161e403d7263d43bf9e Mon Sep 17 00:00:00 2001 From: Sangjin Kim Date: Tue, 21 Aug 2012 18:28:55 +0900 Subject: [PATCH] [Title] pixmap, EGLImageKHR, glEGLImageTargetTexture2DOES extensions are add. [Type] feature [Module] opengl [Priority] high [CQ#] N/A [Redmine#] N/A [Problem] Some features are not supported cause of pixmap. [Cause] N/A [Solution] Pixmap is implemented. [TestCase] N/A --- tizen/src/hw/gl_func_perso.h | 3 + tizen/src/hw/gloffscreen.h | 9 ++ tizen/src/hw/gloffscreen_glx.c | 22 +++- tizen/src/hw/gloffscreen_test.c | 1 + tizen/src/hw/gloffscreen_xcomposite.c | 53 +++++++- tizen/src/hw/opengl_exec.c | 166 +++++++++++++++++++++++++- tizen/src/hw/opengl_func.h | 9 ++ 7 files changed, 252 insertions(+), 11 deletions(-) diff --git a/tizen/src/hw/gl_func_perso.h b/tizen/src/hw/gl_func_perso.h index 7ee6278bf0..1488343e9c 100644 --- a/tizen/src/hw/gl_func_perso.h +++ b/tizen/src/hw/gl_func_perso.h @@ -58,6 +58,8 @@ MAGIC_MACRO(glXQueryExtension), MAGIC_MACRO(glXGetScreenDriver), MAGIC_MACRO(glXGetDriverConfig), MAGIC_MACRO(glXSwapIntervalSGI), +MAGIC_MACRO(glXCreatePixmap), +MAGIC_MACRO(glXDestroyPixmap), MAGIC_MACRO(glGetString), @@ -94,6 +96,7 @@ MAGIC_MACRO(glVertexNormalColorTexCoord012PointerInterlaced_fake), MAGIC_MACRO(glGenTextures_fake), MAGIC_MACRO(glGenBuffersARB_fake), MAGIC_MACRO(glGenLists_fake), +MAGIC_MACRO(glEGLImageTargetTexture2DOES_fake), MAGIC_MACRO(_glDrawElements_buffer), MAGIC_MACRO(_glDrawRangeElements_buffer), MAGIC_MACRO(_glMultiDrawElements_buffer), diff --git a/tizen/src/hw/gloffscreen.h b/tizen/src/hw/gloffscreen.h index e860c07a5c..fe543ac2b2 100644 --- a/tizen/src/hw/gloffscreen.h +++ b/tizen/src/hw/gloffscreen.h @@ -71,12 +71,21 @@ extern void *glo_getprocaddress(const char *procName); /* OS-independent glXQueryExtensionsString */ extern const char *glo_glXQueryExtensionsString(void); +/* Create a light-weight context just for creating surface */ +extern GloContext *__glo_context_create(int formatFlags); + /* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */ extern GloContext *glo_context_create(int formatFlags, GloContext *shareLists); /* Destroy a previouslu created OpenGL context */ extern void glo_context_destroy(GloContext *context); +/* Update the context in surface and free previous light-weight context */ +extern void glo_surface_update_context(GloSurface *surface, GloContext *context); + +/* Link the pixmap associated with surface as texture */ +extern void glo_surface_as_texture(GloSurface *surface); + /* Create a surface with given width and height, */ extern GloSurface *glo_surface_create(int width, int height, GloContext *context); diff --git a/tizen/src/hw/gloffscreen_glx.c b/tizen/src/hw/gloffscreen_glx.c index e807c6ba9a..a09da300d7 100644 --- a/tizen/src/hw/gloffscreen_glx.c +++ b/tizen/src/hw/gloffscreen_glx.c @@ -112,10 +112,8 @@ void *glo_getprocaddress(const char *procName) { /* ------------------------------------------------------------------------ */ -/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */ -GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { - if (!glo_inited) - glo_init(); +/* Create a light-weight context just for creating surface */ +GloContext *__glo_context_create(int formatFlags) { GLXFBConfig *fbConfigs; int numReturned; @@ -159,6 +157,14 @@ GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { context->formatFlags = formatFlags; context->fbConfig = fbConfigs[0]; + return context; +} + +/* Create an OpenGL context for a certain pixel format. formatflags are from the GLO_ constants */ +GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { + + GloContext *context = __glo_context_create(formatFlags); + /* Create a GLX context for OpenGL rendering */ context->context = glXCreateNewContext(glo.dpy, context->fbConfig, GLX_RGBA_TYPE, @@ -210,6 +216,14 @@ static void glo_surface_try_alloc_xshm_image(GloSurface *surface) { /* ------------------------------------------------------------------------ */ +/* Update the context in surface and free previous light-weight context */ +void glo_surface_update_context(GloSurface *surface, GloContext *context) +{ + if ( surface->context ) + qemu_free(surface->context); + surface->context = context; +} + /* Create a surface with given width and height, formatflags are from the * GLO_ constants */ GloSurface *glo_surface_create(int width, int height, GloContext *context) { diff --git a/tizen/src/hw/gloffscreen_test.c b/tizen/src/hw/gloffscreen_test.c index cbeb02c55e..bfd66bbf11 100644 --- a/tizen/src/hw/gloffscreen_test.c +++ b/tizen/src/hw/gloffscreen_test.c @@ -133,6 +133,7 @@ int gl_acceleration_capability_check (void) { printf("GL VENDOR %s\n", glGetString(GL_VENDOR)); printf("GL RENDERER %s\n", glGetString(GL_RENDERER)); printf("GL VERSION %s\n", glGetString(GL_VERSION)); + printf("GLSL VERSION %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); if (strstr (glGetString(GL_RENDERER), "Software")) { printf ("Host does not have GL hardware acceleration!\n"); diff --git a/tizen/src/hw/gloffscreen_xcomposite.c b/tizen/src/hw/gloffscreen_xcomposite.c index f111e9873c..6c3343ea6f 100644 --- a/tizen/src/hw/gloffscreen_xcomposite.c +++ b/tizen/src/hw/gloffscreen_xcomposite.c @@ -69,6 +69,7 @@ struct _GloSurface { Pixmap pixmap; XImage *image; XShmSegmentInfo shminfo; + GLXPixmap glxPixmap; }; extern void glo_surface_getcontents_readpixels(int formatFlags, int stride, @@ -143,12 +144,8 @@ void *glo_getprocaddress(const char *procName) { /* ------------------------------------------------------------------------ */ -/* Create an OpenGL context for a certain pixel format. - formatflags are from the GLO_ constants */ - -GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { - if (!glo_inited) - glo_init(); +/* Create a light-weight context just for creating surface */ +GloContext *__glo_context_create(int formatFlags) { GLXFBConfig *fbConfigs; int numReturned; @@ -190,6 +187,16 @@ GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { context->formatFlags = formatFlags; context->fbConfig = fbConfigs[0]; + return context; +} + +/* Create an OpenGL context for a certain pixel format. + formatflags are from the GLO_ constants */ + +GloContext *glo_context_create(int formatFlags, GloContext *shareLists) { + + GloContext *context = __glo_context_create(formatFlags); + /* Create a GLX context for OpenGL rendering */ context->context = glXCreateNewContext(glo.dpy, context->fbConfig, GLX_RGBA_TYPE, @@ -244,6 +251,14 @@ static void glo_surface_try_alloc_xshm_image(GloSurface *surface) { /* ------------------------------------------------------------------------ */ +/* Update the context in surface and free previous light-weight context */ +void glo_surface_update_context(GloSurface *surface, GloContext *context) +{ + if ( surface->context ) + g_free(surface->context); + surface->context = context; +} + /* Create a surface with given width and height, formatflags are from the * GLO_ constants */ GloSurface *glo_surface_create(int width, int height, GloContext *context) { @@ -299,6 +314,16 @@ GloSurface *glo_surface_create(int width, int height, GloContext *context) { return NULL; } + /* Create a GLX pixmap to associate the frame buffer configuration with the + * created X window */ + /*XXX: need attribute_list? */ + surface->glxPixmap = glXCreatePixmap( glo.dpy, context->fbConfig, surface->pixmap, NULL ); + if (!surface->glxPixmap) { + printf( "glXCreatePixmap failed\n" ); + //exit( EXIT_FAILURE ); + return NULL; + } + XSync(glo.dpy, 0); /* set hints and properties */ @@ -421,6 +446,22 @@ void glo_surface_get_size(GloSurface *surface, int *width, int *height) { *height = surface->height; } +/* Bind the surface as texture */ +void glo_surface_as_texture(GloSurface *surface) +{ + void (*ptr_func_glXBindTexImageEXT) (Display *dpy, GLXDrawable draw, int buffer, int *attrib_list); + ptr_func_glXBindTexImageEXT = + (void(*)(Display*, GLXDrawable, int, int*))glo_getprocaddress((const char*)"glXBindTexImageEXT"); + + /*XXX: When to call the glXReleaseTexImageEXT?*/ + if (!ptr_func_glXBindTexImageEXT) + { + fprintf (stderr, "glXBindTexImageEXT not supported! Can't emulate glEGLImageTargetTexture2DOES!\n"); + } + + ptr_func_glXBindTexImageEXT(glo.dpy, surface->glxPixmap, GLX_FRONT_LEFT_EXT, NULL); +} + /* Abstract glXQueryExtensionString() */ const char *glo_glXQueryExtensionsString(void) { return glXQueryExtensionsString(glo.dpy, 0); diff --git a/tizen/src/hw/opengl_exec.c b/tizen/src/hw/opengl_exec.c index 001a202908..24ea6788ba 100644 --- a/tizen/src/hw/opengl_exec.c +++ b/tizen/src/hw/opengl_exec.c @@ -186,6 +186,9 @@ typedef struct { #define MAX_FBCONFIG 10 +#define MAX_PENDING_QSURFACE 8 +#define MAX_PENDING_DRAWABLE 8 + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define DIM(X) (sizeof(X) / sizeof(X[0])) @@ -287,6 +290,12 @@ typedef struct { GLState **glstates; GLState *current_state; + /* Pending drawables that will be used as texture */ + ClientGLXDrawable pending_drawables[MAX_PENDING_DRAWABLE]; + + /* Created Pixmap surfaces, will link to context in MakeCurrent */ + QGloSurface *pending_qsurfaces[MAX_PENDING_QSURFACE]; + int nfbconfig; const GLXFBConfig *fbconfigs[MAX_FBCONFIG]; int fbconfigs_max[MAX_FBCONFIG]; @@ -582,6 +591,27 @@ static void bind_qsurface(GLState *state, state->current_qsurface = qsurface; } +/* Find the qsurface with required drawable in active & pending qsurfaces */ +QGloSurface* find_qsurface_from_client_drawable(ProcessState *process, ClientGLXDrawable client_drawable) +{ + /* search for surfaces in current conetxt */ + int i; + QGloSurface *qsurface = get_qsurface_from_client_drawable(process->current_state, client_drawable); + + if (qsurface) + return qsurface; + + /* search the pending surfaces */ + for ( i = 0; i < MAX_PENDING_QSURFACE; i++ ) + { + qsurface = process->pending_qsurfaces[i]; + if ( qsurface && qsurface->client_drawable == client_drawable ) + return qsurface; + } + + return NULL; +} + /* Make the appropriate qsurface current for a given client_drawable */ static int set_current_qsurface(GLState *state, ClientGLXDrawable client_drawable) @@ -603,6 +633,77 @@ static int set_current_qsurface(GLState *state, return 0; } +/* */ +static int keep_drawable(ProcessState *process, ClientGLXDrawable drawable) +{ + int i; + for ( i = 0; i < MAX_PENDING_DRAWABLE; i++) + { + if ( process->pending_drawables[i] == 0 ) + { + process->pending_drawables[i] = drawable; + return 1; + } + } + return 0; +} + +static int link_drawable(ProcessState *process, ClientGLXDrawable drawable) +{ + int i; + for ( i = 0; i < MAX_PENDING_DRAWABLE; i++ ) + { + if ( process->pending_drawables[i] == drawable ) + { + process->pending_drawables[i] = 0; + return 1; + } + } + return 0; +} + +/* Need to create pixmap surface when guest do so, as guest may use it before + * MakeCurrent. As no context available at this point, we do the follwoing: + * 1. Create one light-weight context just for surface creation. + * 2. Store this qsurface, and link it with right context when MakeCurrent + */ +static int keep_qsurface(ProcessState *process, QGloSurface *qsurface) +{ + int i; + for ( i = 0; i < MAX_PENDING_QSURFACE; i++) + { + if ( process->pending_qsurfaces[i] == NULL ) + { + process->pending_qsurfaces[i] = qsurface; + return 1; + } + } + return 0; +} + +static int link_qsurface(ProcessState *process, GLState *glstate, ClientGLXDrawable client_drawable) +{ + int i; + QGloSurface *qsurface; + for ( i = 0; i < MAX_PENDING_QSURFACE; i++ ) + { + qsurface = process->pending_qsurfaces[i]; + if ( qsurface && qsurface->client_drawable == client_drawable ) + { + process->pending_qsurfaces[i] = NULL; + qsurface->ref = 1; +/* qsurface->surface->context = glstate->context;*/ + glo_surface_update_context(qsurface->surface, glstate->context); + bind_qsurface(glstate, qsurface); + return 1; + } + } + + return 0; +} + + + static int get_server_texture(ProcessState *process, unsigned int client_texture) { @@ -1457,7 +1558,8 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args if (!glstate) { DEBUGF( " --invalid fake_ctxt (%d)!\n", fake_ctxt); } else { - if(!set_current_qsurface(glstate, client_drawable)) { + if(!set_current_qsurface(glstate, client_drawable) && + !link_qsurface(process, glstate, client_drawable) ) { // If there is no surface, create one. QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); qsurface->surface = glo_surface_create(4, 4, @@ -1714,6 +1816,68 @@ int do_function_call(ProcessState *process, int func_number, unsigned long *args } break; } + case glXCreatePixmap_func: + { + int client_fbconfig = args[1]; + + ret.i = 0; + const GLXFBConfig *fbconfig = get_fbconfig(process, client_fbconfig); + + if (fbconfig) { + + /* Create a light-weight context just for creating surface */ + GloContext *context = __glo_context_create(fbconfig->formatFlags); + + /* glXPixmap same as input Pixmap */ + ClientGLXDrawable client_drawable = to_drawable(args[2]); + + QGloSurface *qsurface = calloc(1, sizeof(QGloSurface)); + /*FIXME: need pass w,h from simulator-opengl */ + qsurface->surface = glo_surface_create(512, 512, context); + qsurface->client_drawable = client_drawable; + /* qsurface->ref = 1;*/ + + /* Keep this surface, will link it with context in MakeCurrent */ + if (!keep_qsurface(process, qsurface)) + { + DEBUGF( "No space to store create pixmap surface. Need call MakeCurrent to free them.\n"); + ret.i = 0; + break; + } + + /* If this pixmap is linked as texture previously */ + if (link_drawable(process, client_drawable)) + glo_surface_as_texture(qsurface->surface); + + ret.i = client_drawable; + + } + break; + } + case glXDestroyPixmap_func: + { + break; + } + case glEGLImageTargetTexture2DOES_fake_func: + { + int target = args[0]; + ClientGLXDrawable client_drawable = to_drawable(args[1]); + QGloSurface *qsurface = find_qsurface_from_client_drawable(process, client_drawable); + + if ( !qsurface ) + { + if ( !keep_drawable(process, client_drawable) ) + { + DEBUGF( "No space to store drawable for ImageTargetTexture. Need call CreatePixmapSurface to free them.\n"); + break; + } + } + else + glo_surface_as_texture(qsurface->surface); + + break; + } + /* Begin of texture stuff */ case glBindTexture_func: case glBindTextureEXT_func: diff --git a/tizen/src/hw/opengl_func.h b/tizen/src/hw/opengl_func.h index b2c8a1c343..3b302175ab 100644 --- a/tizen/src/hw/opengl_func.h +++ b/tizen/src/hw/opengl_func.h @@ -418,6 +418,12 @@ static const int glXGetVideoSyncSGI_signature[] = static const int glXSwapIntervalSGI_signature[] = { TYPE_INT, 0, 1, TYPE_INT }; +static const int glXCreatePixmap_signature[] = + { TYPE_INT, 0, 4, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT, TYPE_ARRAY_INT }; + +static const int glXDestroyPixmap_signature[] = + { TYPE_NONE, 0, 2, TYPE_IN_IGNORED_POINTER, TYPE_INT }; + static const int glXBindTexImageATI_signature[] = { TYPE_NONE, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT }; static const int glXReleaseTexImageATI_signature[] = @@ -427,6 +433,9 @@ static const int glXBindTexImageARB_signature[] = static const int glXReleaseTexImageARB_signature[] = { TYPE_INT, 0, 3, TYPE_IN_IGNORED_POINTER, TYPE_INT, TYPE_INT }; +static const int glEGLImageTargetTexture2DOES_fake_signature[] = + { TYPE_NONE, 0, 2, TYPE_UNSIGNED_INT, TYPE_INT }; + /* const GLubyte * glGetString( GLenum name ) */ static const int glGetString_signature[] = { TYPE_CONST_CHAR, 0, 1, TYPE_INT }; -- 2.34.1