jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=8771c78a90f51dd4c5ec4de942630d1b7ef3349b

commit 8771c78a90f51dd4c5ec4de942630d1b7ef3349b
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Wed Nov 26 22:42:08 2014 +0900

    Evas GL: Fix indirect rendering surfaces for GLES 1.1
    
    Carefully select the requested EGL config and match it with
    the available visual from X, including the following options:
    - Stencil
    - Depth
    - MSAA
    
    TODO: The same thing for GLX. And fix direct rendering as well.
---
 src/modules/evas/engines/gl_common/evas_gl_core.c  |   2 +-
 .../evas/engines/gl_common/evas_gl_core_private.h  |   2 +-
 src/modules/evas/engines/gl_x11/evas_engine.c      | 151 +++++++++++++++++++--
 3 files changed, 145 insertions(+), 10 deletions(-)

diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c 
b/src/modules/evas/engines/gl_common/evas_gl_core.c
index 09f521d..ee4b09f 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.c
@@ -1592,7 +1592,7 @@ evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, 
int w, int h)
           }
 
         INF("Creating special surface for GLES 1.x rendering");
-        evgl_engine->funcs->gles1_surface_create(eng_data, sfc, cfg, w, h);
+        evgl_engine->funcs->gles1_surface_create(evgl_engine, eng_data, sfc, 
cfg, w, h);
      }
 
    // Create internal buffers
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core_private.h 
b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
index 329f726..4c22dd5 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core_private.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_core_private.h
@@ -70,7 +70,7 @@ struct _EVGL_Interface
    int         (*pbuffer_surface_destroy)(void *data, void *surface);
 
    // Create a surface for 1.x rendering (could be pbuffer or xpixmap for 
instance)
-   void       *(*gles1_surface_create)(void *data, EVGL_Surface *evgl_sfc, 
Evas_GL_Config *cfg, int w, int h);
+   void       *(*gles1_surface_create)(EVGL_Engine *evgl, void *data, 
EVGL_Surface *evgl_sfc, Evas_GL_Config *cfg, int w, int h);
 
    // Destroy 1.x surface (could be pbuffer or xpixmap for instance)
    int        (*gles1_surface_destroy)(void *data, EVGL_Surface *evgl_sfc);
diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c 
b/src/modules/evas/engines/gl_x11/evas_engine.c
index 1447c53..5a36125 100644
--- a/src/modules/evas/engines/gl_x11/evas_engine.c
+++ b/src/modules/evas/engines/gl_x11/evas_engine.c
@@ -864,11 +864,15 @@ evgl_eng_pbuffer_surface_destroy(void *data, void 
*surface)
 // For now, this will create an X pixmap... Ideally it should be able to create
 // a bindable pbuffer surface or just an FBO if that is supported and it can
 // be shared with Evas.
+// FIXME: Avoid passing evgl_engine around like that.
 static void *
-evgl_eng_gles1_surface_create(void *data, EVGL_Surface *evgl_sfc,
+evgl_eng_gles1_surface_create(EVGL_Engine *evgl, void *data,
+                              EVGL_Surface *evgl_sfc,
                               Evas_GL_Config *cfg, int w, int h)
 {
-   Render_Engine *re = (Render_Engine *)data;
+   Render_Engine *re = data;
+   Eina_Bool alpha = EINA_FALSE;
+   int colordepth;
    Pixmap px;
 
    if (!re || !evgl_sfc || !cfg)
@@ -877,16 +881,25 @@ evgl_eng_gles1_surface_create(void *data, EVGL_Surface 
*evgl_sfc,
         return NULL;
      }
 
-   if (cfg->gles_version != EVAS_GL_GLES_1_X)
+   if ((cfg->gles_version != EVAS_GL_GLES_1_X) || (w < 1) || (h < 1))
      {
         ERR("Inconsistent parameters, not creating any surface!");
         glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_PARAMETER);
         return NULL;
      }
 
-   // FIXME: Check the depth of the buffer!
-   px =  XCreatePixmap(eng_get_ob(re)->disp, eng_get_ob(re)->win, w, h,
-                       XDefaultDepth(eng_get_ob(re)->disp, 
eng_get_ob(re)->screen));
+   /* Choose appropriate pixmap depth */
+   if (cfg->color_format == EVAS_GL_RGBA_8888)
+     {
+        alpha = EINA_TRUE;
+        colordepth = 32;
+     }
+   else if (cfg->color_format == EVAS_GL_RGB_888)
+     colordepth = 24;
+   else // this could also be XDefaultDepth but this case shouldn't happen
+     colordepth = 24;
+
+   px = XCreatePixmap(eng_get_ob(re)->disp, eng_get_ob(re)->win, w, h, 
colordepth);
    if (!px)
      {
         ERR("Failed to create XPixmap!");
@@ -896,8 +909,127 @@ evgl_eng_gles1_surface_create(void *data, EVGL_Surface 
*evgl_sfc,
 
 #ifdef GL_GLES
    EGLSurface egl_sfc;
+   EGLConfig egl_cfg;
+   int i, num = 0;
+   EGLConfig configs[200];
+   int config_attrs[40];
+   Eina_Bool found = EINA_FALSE;
+   int msaa = 0, depth = 0, stencil = 0;
+   Visual *visual = NULL;
+
+   /* Now we need to iterate over all EGL configurations to check the 
compatible
+    * ones and finally check their visual ID. */
+
+   i = 0;
+   config_attrs[i++] = EGL_SURFACE_TYPE;
+   config_attrs[i++] = EGL_PIXMAP_BIT;
+   config_attrs[i++] = EGL_RENDERABLE_TYPE;
+   config_attrs[i++] = EGL_OPENGL_ES_BIT;
+   if (cfg->color_format == EVAS_GL_RGBA_8888)
+     {
+        config_attrs[i++] = EGL_ALPHA_SIZE;
+        config_attrs[i++] = 1; // should it be 8?
+        DBG("Requesting RGBA pixmap");
+     }
+   else
+     {
+        config_attrs[i++] = EGL_ALPHA_SIZE;
+        config_attrs[i++] = 0;
+     }
+   if ((cfg->depth_bits > EVAS_GL_DEPTH_NONE) &&
+       (cfg->depth_bits <= EVAS_GL_DEPTH_BIT_32))
+     {
+        depth = 8 * ((int) cfg->depth_bits);
+        config_attrs[i++] = EGL_DEPTH_SIZE;
+        config_attrs[i++] = depth;
+        DBG("Requesting depth buffer size %d", depth);
+     }
+   if ((cfg->stencil_bits > EVAS_GL_STENCIL_NONE) &&
+       (cfg->stencil_bits <= EVAS_GL_STENCIL_BIT_16))
+     {
+        stencil = 1 << ((int) cfg->stencil_bits - 1);
+        config_attrs[i++] = EGL_STENCIL_SIZE;
+        config_attrs[i++] = stencil;
+        DBG("Requesting stencil buffer size %d", stencil);
+     }
+   if ((cfg->multisample_bits > EVAS_GL_MULTISAMPLE_NONE) &&
+       (cfg->multisample_bits <= EVAS_GL_MULTISAMPLE_HIGH))
+     {
+        msaa = evgl->caps.msaa_samples[(int) cfg->multisample_bits - 1];
+        config_attrs[i++] = EGL_SAMPLE_BUFFERS;
+        config_attrs[i++] = 1;
+        config_attrs[i++] = EGL_SAMPLES;
+        config_attrs[i++] = msaa;
+        DBG("Requesting MSAA buffer with %d samples", msaa);
+     }
+   config_attrs[i++] = EGL_NONE;
+   config_attrs[i++] = 0;
 
-   egl_sfc = eglCreatePixmapSurface(eng_get_ob(re)->egl_disp, 
eng_get_ob(re)->egl_config, px, NULL);
+   if (!eglChooseConfig(eng_get_ob(re)->egl_disp, config_attrs, configs, 200, 
&num))
+     {
+        int err = eglGetError();
+        ERR("eglChooseConfig() can't find any configs, error: %x", err);
+        glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
+        XFreePixmap(eng_get_ob(re)->disp, px);
+        return NULL;
+     }
+
+   for (i = 0; (i < num) && !found; i++)
+     {
+        EGLint val = 0;
+        VisualID visid = 0;
+        XVisualInfo *xvi, vi_in;
+        XRenderPictFormat *fmt;
+        int nvi = 0, j;
+
+        if (!eglGetConfigAttrib(eng_get_ob(re)->egl_disp, configs[i],
+                                EGL_NATIVE_VISUAL_ID, &val))
+          continue;
+
+        // Find matching visuals. Only alpha & depth are really valid here.
+        visid = val;
+        vi_in.screen = eng_get_ob(re)->screen;
+        vi_in.visualid = visid;
+        xvi = XGetVisualInfo(eng_get_ob(re)->disp,
+                             VisualScreenMask | VisualIDMask,
+                             &vi_in, &nvi);
+        if (xvi)
+          {
+             for (j = 0; (j < nvi) && !found; j++)
+               {
+                  if (xvi[j].depth >= colordepth)
+                    {
+                       if (alpha)
+                         {
+                            fmt = 
XRenderFindVisualFormat(eng_get_ob(re)->disp, xvi[j].visual);
+                            if (fmt && (fmt->direct.alphaMask))
+                              found = EINA_TRUE;
+                         }
+                       else found = EINA_TRUE;
+                    }
+               }
+             if (found)
+               {
+                  egl_cfg = configs[i];
+                  visual = xvi[j].visual;
+                  XFree(xvi);
+                  break;
+               }
+             XFree(xvi);
+          }
+     }
+
+   if (!found)
+     {
+        // This config will probably not work, but we try anyways.
+        ERR("XGetVisualInfo failed. Trying with the first EGL config.");
+        if (num)
+          egl_cfg = configs[0];
+        else
+          egl_cfg = eng_get_ob(re)->egl_config;
+     }
+
+   egl_sfc = eglCreatePixmapSurface(eng_get_ob(re)->egl_disp, egl_cfg, px, 
NULL);
    if (!egl_sfc)
      {
         int err = eglGetError();
@@ -911,10 +1043,13 @@ evgl_eng_gles1_surface_create(void *data, EVGL_Surface 
*evgl_sfc,
    evgl_sfc->xpixmap = EINA_TRUE;
    evgl_sfc->gles1_sfc = egl_sfc;
    evgl_sfc->gles1_sfc_native = (void *)(intptr_t) px;
-   evgl_sfc->gles1_sfc_visual = eng_get_ob(re)->info->info.visual; // FIXME: 
Check this!
+   evgl_sfc->gles1_sfc_visual = visual;
    return evgl_sfc;
 
 #else
+   // TODO/FIXME: do the same as with EGL above...
+   ERR("GLX support is not fully implemented for GLES 1.x");
+
    evgl_sfc->gles1_indirect = EINA_TRUE;
    evgl_sfc->xpixmap = EINA_TRUE;
    evgl_sfc->gles1_sfc_native = (void *)(intptr_t) px;

-- 


Reply via email to