[Title] pixmap, EGLImageKHR, glEGLImageTargetTexture2DOES extensions are add.
authorSangjin Kim <sangjin3.kim@samsung.com>
Tue, 21 Aug 2012 09:28:55 +0000 (18:28 +0900)
committerSangjin Kim <sangjin3.kim@samsung.com>
Tue, 21 Aug 2012 09:28:55 +0000 (18:28 +0900)
[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
tizen/src/hw/gloffscreen.h
tizen/src/hw/gloffscreen_glx.c
tizen/src/hw/gloffscreen_test.c
tizen/src/hw/gloffscreen_xcomposite.c
tizen/src/hw/opengl_exec.c
tizen/src/hw/opengl_func.h

index 7ee6278..1488343 100644 (file)
@@ -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),
index e860c07..fe543ac 100644 (file)
@@ -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);
 
index e807c6b..a09da30 100644 (file)
@@ -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) {
index cbeb02c..bfd66bb 100644 (file)
@@ -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");
index f111e98..6c3343e 100644 (file)
@@ -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);
index 001a202..24ea678 100644 (file)
@@ -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:
index b2c8a1c..3b30217 100644 (file)
@@ -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 };