jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=5bdcea59dbdb3534ec3621d1c6b84b9ab75a6f7f

commit 5bdcea59dbdb3534ec3621d1c6b84b9ab75a6f7f
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Mon Apr 6 21:57:32 2015 +0900

    Evas gl_x11: Fix runtime switching of GL window configurations
    
    Test case:
    - Elementary Test
    -- GLView
    --- Direct rendering
    
    Direct rendering would never happen in reality, because Evas GL
    had to fallback. The reason being that DR requires the window
    to have a depth buffer, but this depth buffer was no present
    in the default config.
    
    From elm, the solution is to set a special accel_preference,
    for instance "gl:depth". But setting this value right before
    calling elm_win_add() for the GLView test was already too late.
    Indeed, evas_x would keep the default configurations and reuse
    them no matter what was requested (ie. only RGB and RGBA would
    work).
    
    Solution:
    Implement a slightly more complex cache based on a hash map instead
    of just two static variables. Always request a new config if it's
    not found in the current hash. Store that config, and reuse it for
    the same config requests.
    
    Tons of line changes because of the name changes and the whitespace
    adjustments. Also some variables disappeared into the magic hash table.
---
 src/modules/evas/engines/gl_x11/evas_x_main.c | 861 ++++++++++++++------------
 1 file changed, 478 insertions(+), 383 deletions(-)

diff --git a/src/modules/evas/engines/gl_x11/evas_x_main.c 
b/src/modules/evas/engines/gl_x11/evas_x_main.c
index 38e450c..816d222 100644
--- a/src/modules/evas/engines/gl_x11/evas_x_main.c
+++ b/src/modules/evas/engines/gl_x11/evas_x_main.c
@@ -5,21 +5,26 @@ static Eina_TLS _context_key = 0;
 
 #ifdef GL_GLES
 typedef EGLContext GLContext;
-static EGLConfig fbconf = 0;
-static EGLConfig rgba_fbconf = 0;
-static Eina_Bool gles3_supported = EINA_FALSE;
+typedef EGLConfig GLConfig;
+static int gles3_supported = -1;
 #else
 // FIXME: this will only work for 1 display connection (glx land can have > 1)
 typedef GLXContext GLContext;
+typedef GLXFBConfig GLConfig;
 static Eina_TLS _rgba_context_key = 0;
-static GLXFBConfig fbconf = 0;
-static GLXFBConfig rgba_fbconf = 0;
 #endif
 
-static XVisualInfo *_evas_gl_x11_vi = NULL;
-static XVisualInfo *_evas_gl_x11_rgba_vi = NULL;
-static Colormap     _evas_gl_x11_cmap = 0;
-static Colormap     _evas_gl_x11_rgba_cmap = 0;
+typedef struct _Evas_GL_X11_Visual Evas_GL_X11_Visual;
+struct _Evas_GL_X11_Visual
+{
+   XVisualInfo info;
+   GLConfig config;
+   Colormap cmap;
+   Eina_Bool alpha;
+};
+
+/* index (_visuals_hash_index_get) -> Evas_GL_X11_Visual */
+static Eina_Hash *_evas_gl_visuals = NULL;
 
 static int win_count = 0;
 static Eina_Bool initted = EINA_FALSE;
@@ -104,6 +109,29 @@ __glXMakeContextCurrent(Display *disp, GLXDrawable glxwin, 
GLXContext context)
 }
 #endif
 
+static void
+_visuals_hash_del_cb(void *data)
+{
+   free(data);
+}
+
+static inline int
+_visuals_hash_index_get(int alpha, int zdepth, int stencil, int msaa)
+{
+   if (!_evas_gl_visuals)
+     _evas_gl_visuals = eina_hash_int32_new(_visuals_hash_del_cb);
+   return alpha | (zdepth << 8) | (stencil << 16) | (msaa << 24);
+}
+
+static inline int
+_visuals_hash_index_get_from_info(Evas_Engine_Info_GL_X11 *info)
+{
+   if (!info) return -1;
+   return _visuals_hash_index_get(info->info.destination_alpha,
+                                  info->depth_bits, info->stencil_bits,
+                                  info->msaa_bits);
+}
+
 Outbuf *
 eng_window_new(Evas_Engine_Info_GL_X11 *info,
                Evas *e,
@@ -130,13 +158,25 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
    int major_version, minor_version;
 #else
    GLXContext rgbactx;
+   Evas_GL_X11_Visual *evis2 = NULL;
+   int tmp;
 #endif
    const GLubyte *vendor, *renderer, *version, *glslversion;
    int blacklist = 0;
-   int val = 0;
+   int val = 0, idx;
+   Evas_GL_X11_Visual *evis;
+
+   idx = _visuals_hash_index_get_from_info(info);
+   evis = eina_hash_find(_evas_gl_visuals, &idx);
+   if (!evis)
+     {
+        eng_best_visual_get(info);
+        evis = eina_hash_find(_evas_gl_visuals, &idx);
+        if (!evis) return NULL;
+     }
 
-   if (!fbconf) eng_best_visual_get(info);
-   if (!_evas_gl_x11_vi) return NULL;
+   vis = evis->info.visual;
+   if (!vis) return NULL;
 
    gw = calloc(1, sizeof(Outbuf));
    if (!gw) return NULL;
@@ -158,11 +198,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
    gw->depth_bits = depth_bits;
    gw->stencil_bits = stencil_bits;
    gw->msaa_bits = msaa_bits;
-
-   if (gw->alpha && _evas_gl_x11_rgba_vi)
-     gw->visualinfo = _evas_gl_x11_rgba_vi;
-   else
-     gw->visualinfo = _evas_gl_x11_vi;
+   gw->visualinfo = &evis->info;
 
 // EGL / GLES
 #ifdef GL_GLES
@@ -187,8 +223,7 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info,
         return NULL;
      }
 
-   if (gw->alpha) gw->egl_config = rgba_fbconf;
-   else gw->egl_config = fbconf;
+   gw->egl_config = evis->config;
 
    gw->egl_surface[0] = eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
                                                (EGLNativeWindowType)gw->win,
@@ -287,12 +322,26 @@ try_gles2:
    context = _tls_context_get();
    if (!context)
      {
+        if (!evis->alpha)
+          evis2 = evis;
+        else
+          {
+             tmp = info->info.destination_alpha;
+             info->info.destination_alpha = 0;
+             evis2 = eng_best_visual_get(info);
+             info->info.destination_alpha = tmp;
+             if (!evis2)
+               {
+                  ERR("Could not find visual! (rgb only)");
+                  evis2 = evis;
+               }
+          }
         if (indirect)
-          context = glXCreateNewContext(gw->disp, fbconf,
+          context = glXCreateNewContext(gw->disp, evis2->config,
                                         GLX_RGBA_TYPE, NULL,
                                         GL_FALSE);
         else
-          context = glXCreateNewContext(gw->disp, fbconf,
+          context = glXCreateNewContext(gw->disp, evis2->config,
                                         GLX_RGBA_TYPE, NULL,
                                         GL_TRUE);
         _tls_context_set(context);
@@ -300,20 +349,47 @@ try_gles2:
    rgbactx = _tls_rgba_context_get();
    if ((gw->alpha) && (!rgbactx))
      {
+        if (evis->alpha)
+          evis2 = evis;
+        else
+          {
+             tmp = info->info.destination_alpha;
+             info->info.destination_alpha = 1;
+             evis2 = eng_best_visual_get(info);
+             info->info.destination_alpha = tmp;
+             if (!evis2)
+               {
+                  ERR("Could not find visual! (rgba)");
+                  evis2 = evis;
+               }
+          }
         if (indirect)
-          rgbactx = glXCreateNewContext(gw->disp, rgba_fbconf,
+          rgbactx = glXCreateNewContext(gw->disp, evis2->config,
                                         GLX_RGBA_TYPE, context,
                                         GL_FALSE);
         else
-          rgbactx = glXCreateNewContext(gw->disp, rgba_fbconf,
+          rgbactx = glXCreateNewContext(gw->disp, evis2->config,
                                         GLX_RGBA_TYPE, context,
                                         GL_TRUE);
         _tls_rgba_context_set(rgbactx);
      }
-   if (gw->alpha)
-     gw->glxwin = glXCreateWindow(gw->disp, rgba_fbconf, gw->win, NULL);
+
+   if (gw->alpha != info->info.destination_alpha)
+     {
+        tmp = info->info.destination_alpha;
+        info->info.destination_alpha = gw->alpha;
+        evis2 = eng_best_visual_get(info);
+        info->info.destination_alpha = tmp;
+        if (!evis2)
+          {
+             ERR("Could not find visual! (alpha: %d)", gw->alpha);
+             evis2 = evis;
+          }
+     }
    else
-     gw->glxwin = glXCreateWindow(gw->disp, fbconf, gw->win, NULL);
+     evis2 = evis;
+   gw->glxwin = glXCreateWindow(gw->disp, evis2->config, gw->win, NULL);
+
    if (!gw->glxwin)
      {
         ERR("glXCreateWindow failed.");
@@ -512,13 +588,9 @@ eng_window_free(Outbuf *gw)
         if (context) eglDestroyContext(gw->egl_disp, context);
         eglTerminate(gw->egl_disp);
         eglReleaseThread();
+        eina_hash_free(_evas_gl_visuals);
+        _evas_gl_visuals = NULL;
         _tls_context_set(EGL_NO_CONTEXT);
-        free(_evas_gl_x11_vi);
-        free(_evas_gl_x11_rgba_vi);
-        fbconf = 0;
-        rgba_fbconf = 0;
-        _evas_gl_x11_vi = NULL;
-        _evas_gl_x11_rgba_vi = NULL;
      }
 #else
    glXDestroyWindow(gw->disp, gw->glxwin);
@@ -527,14 +599,10 @@ eng_window_free(Outbuf *gw)
         GLXContext rgbactx = _tls_rgba_context_get();
         if (context) glXDestroyContext(gw->disp, context);
         if (rgbactx) glXDestroyContext(gw->disp, rgbactx);
-        free(_evas_gl_x11_vi);
-        free(_evas_gl_x11_rgba_vi);
+        eina_hash_free(_evas_gl_visuals);
+        _evas_gl_visuals = NULL;
         _tls_context_set(0);
         _tls_rgba_context_set(0);
-        fbconf = 0;
-        rgba_fbconf = 0;
-        _evas_gl_x11_vi = NULL;
-        _evas_gl_x11_rgba_vi = NULL;
      }
 #endif
    free(gw);
@@ -698,10 +766,20 @@ eng_window_resurf(Outbuf *gw)
         ERR("eglMakeCurrent() failed!");
      }
 #else
-   if (gw->alpha)
-     gw->glxwin = glXCreateWindow(gw->disp, rgba_fbconf, gw->win, NULL);
-   else
-     gw->glxwin = glXCreateWindow(gw->disp, fbconf, gw->win, NULL);
+   Evas_GL_X11_Visual *evis;
+   int idx = _visuals_hash_index_get(gw->alpha, gw->depth_bits, 
gw->stencil_bits, gw->msaa_bits);
+   evis = eina_hash_find(_evas_gl_visuals, &idx);
+   if (!evis)
+     {
+        eng_best_visual_get(gw->info);
+        evis = eina_hash_find(_evas_gl_visuals, &idx);
+        if (!evis)
+          {
+             ERR("Could not find matching visual! Resurf failed.");
+             return;
+          }
+     }
+   gw->glxwin = glXCreateWindow(gw->disp, evis->config, gw->win, NULL);
    if (!__glXMakeContextCurrent(gw->disp, gw->glxwin, gw->context))
      {
         ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void 
*)gw->glxwin, (void *)gw->win, (void *)gw->context);
@@ -713,22 +791,50 @@ eng_window_resurf(Outbuf *gw)
 void *
 eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo)
 {
+   Evas_GL_X11_Visual *evis;
+   int alpha = einfo->info.destination_alpha;
+   int depth_bits = einfo->depth_bits;
+   int stencil_bits = einfo->stencil_bits;
+   int msaa_samples = einfo->msaa_bits;
+   int config_attrs[40], i, num, idx;
+   Eina_Bool found;
+
    if (!einfo) return NULL;
    if (!einfo->info.display) return NULL;
-   if (!_evas_gl_x11_vi)
-     {
-        int alpha;
-// EGL / GLES
+
+   idx = _visuals_hash_index_get_from_info(einfo);
+   evis = eina_hash_find(_evas_gl_visuals, &idx);
+   if (evis)
+     return evis->info.visual;
+
+   evis = calloc(1, sizeof(Evas_GL_X11_Visual));
+   if (!evis) return NULL;
+
+   evis->alpha = alpha;
+
+   // EGL / GLES
 #ifdef GL_GLES
-        EGLDisplay *egl_disp;
-        EGLConfig configs[200];
-        int major_version, minor_version;
-        const char *eglexts, *s;
+   EGLDisplay *egl_disp;
+   EGLConfig configs[200];
+   int major_version, minor_version;
+   const char *eglexts, *s;
+   int depth = DefaultDepth(einfo->info.display, einfo->info.screen);
 
-        egl_disp = eglGetDisplay((EGLNativeDisplayType)(einfo->info.display));
-        if (!egl_disp) return NULL;
-        if (!eglInitialize(egl_disp, &major_version, &minor_version)) return 
NULL;
+   egl_disp = eglGetDisplay((EGLNativeDisplayType)(einfo->info.display));
+   if (!egl_disp)
+     {
+        free(evis);
+        return NULL;
+     }
+   if (!eglInitialize(egl_disp, &major_version, &minor_version))
+     {
+        free(evis);
+        return NULL;
+     }
 
+   /* detect GLES 3.x support */
+   if (gles3_supported == -1)
+     {
         eglexts = eglQueryString(egl_disp, EGL_EXTENSIONS);
         if (eglexts && strstr(eglexts, "EGL_KHR_create_context"))
           {
@@ -762,388 +868,377 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo)
              INF("Disabling OpenGL ES 3.x support.");
              gles3_supported = EINA_FALSE;
           }
+     }
 
-        for (alpha = 0; alpha < 2; alpha++)
-          {
-             Eina_Bool found;
-             int config_attrs[40], i, n, num;
-             int depth = DefaultDepth(einfo->info.display,
-                                      einfo->info.screen);
-             int depth_bits = einfo->depth_bits;
-             int stencil_bits = einfo->stencil_bits;
-             int msaa_samples = einfo->msaa_bits;
-
+   /* Find matching config & visual */
 try_again:
-             n = 0;
-             config_attrs[n++] = EGL_SURFACE_TYPE;
-             config_attrs[n++] = EGL_WINDOW_BIT;
-             config_attrs[n++] = EGL_RENDERABLE_TYPE;
-             if (gles3_supported)
-               config_attrs[n++] = EGL_OPENGL_ES3_BIT_KHR;
-             else
-               config_attrs[n++] = EGL_OPENGL_ES2_BIT;
+   i = 0;
+   config_attrs[i++] = EGL_SURFACE_TYPE;
+   config_attrs[i++] = EGL_WINDOW_BIT;
+   config_attrs[i++] = EGL_RENDERABLE_TYPE;
+   if (gles3_supported)
+     config_attrs[i++] = EGL_OPENGL_ES3_BIT_KHR;
+   else
+     config_attrs[i++] = EGL_OPENGL_ES2_BIT;
 # if 0
-             // FIXME: n900 - omap3 sgx libs break here
-             config_attrs[n++] = EGL_RED_SIZE;
-             config_attrs[n++] = 1;
-             config_attrs[n++] = EGL_GREEN_SIZE;
-             config_attrs[n++] = 1;
-             config_attrs[n++] = EGL_BLUE_SIZE;
-             config_attrs[n++] = 1;
-             // FIXME: end n900 breakage
+   // FIXME: n900 - omap3 sgx libs break here
+   config_attrs[n++] = EGL_RED_SIZE;
+   config_attrs[n++] = 1;
+   config_attrs[n++] = EGL_GREEN_SIZE;
+   config_attrs[n++] = 1;
+   config_attrs[n++] = EGL_BLUE_SIZE;
+   config_attrs[n++] = 1;
+   // FIXME: end n900 breakage
 # endif
-             if (alpha)
-               {
-                  config_attrs[n++] = EGL_ALPHA_SIZE;
-                  config_attrs[n++] = 1;
-               }
-             else
-               {
-                  config_attrs[n++] = EGL_ALPHA_SIZE;
-                  config_attrs[n++] = 0;
-               }
+   if (alpha)
+     {
+        config_attrs[i++] = EGL_ALPHA_SIZE;
+        config_attrs[i++] = 1;
+     }
+   else
+     {
+        config_attrs[i++] = EGL_ALPHA_SIZE;
+        config_attrs[i++] = 0;
+     }
 
-             if (depth_bits)
-               {
-                  config_attrs[n++] = EGL_DEPTH_SIZE;
-                  config_attrs[n++] = depth_bits;
-               }
+   if (depth_bits)
+     {
+        config_attrs[i++] = EGL_DEPTH_SIZE;
+        config_attrs[i++] = depth_bits;
+     }
 
-             if (stencil_bits)
-               {
-                  config_attrs[n++] = EGL_STENCIL_SIZE;
-                  config_attrs[n++] = stencil_bits;
-               }
+   if (stencil_bits)
+     {
+        config_attrs[i++] = EGL_STENCIL_SIZE;
+        config_attrs[i++] = stencil_bits;
+     }
 
-             if (msaa_samples)
-               {
-                  config_attrs[n++] = EGL_SAMPLE_BUFFERS;
-                  config_attrs[n++] = 1;
-                  config_attrs[n++] = EGL_SAMPLES;
-                  config_attrs[n++] = msaa_samples;
-               }
-             config_attrs[n++] = EGL_NONE;
-             num = 0;
-             if ((!eglChooseConfig(egl_disp, config_attrs, configs, 200, &num))
-                 || (num < 1))
+   if (msaa_samples)
+     {
+        config_attrs[i++] = EGL_SAMPLE_BUFFERS;
+        config_attrs[i++] = 1;
+        config_attrs[i++] = EGL_SAMPLES;
+        config_attrs[i++] = msaa_samples;
+     }
+   config_attrs[i++] = EGL_NONE;
+   num = 0;
+   if ((!eglChooseConfig(egl_disp, config_attrs, configs, 200, &num))
+       || (num < 1))
+     {
+        ERR("eglChooseConfig() can't find any configs (gles%d, alpha: %d, 
depth: %d, stencil: %d, msaa: %d)",
+            gles3_supported ? 3 : 2, alpha, depth_bits, stencil_bits, 
msaa_samples);
+        if ((depth_bits > 24) || (stencil_bits > 8))
+          {
+             WRN("Please note that your driver might not support 32-bit depth 
or "
+                 "16-bit stencil buffers, so depth24, stencil8 are the maximum 
"
+                 "recommended values.");
+             if (depth_bits > 24) depth_bits = 24;
+             if (stencil_bits > 8) stencil_bits = 8;
+             DBG("Trying again with depth:%d, stencil:%d", depth_bits, 
stencil_bits);
+             goto try_again;
+          }
+        else if (msaa_samples)
+          {
+             msaa_samples /= 2;
+             DBG("Trying again with msaa_samples: %d", msaa_samples);
+             goto try_again;
+          }
+        else if (depth_bits || stencil_bits)
+          {
+             depth_bits = 0;
+             stencil_bits = 0;
+             DBG("Trying again without any depth or stencil buffer");
+             goto try_again;
+          }
+        free(evis);
+        return NULL;
+     }
+   found = EINA_FALSE;
+   for (i = 0; (i < num) && (!found); i++)
+     {
+        EGLint val = 0;
+        VisualID visid = 0;
+        XVisualInfo *xvi, vi_in;
+        int nvi, j;
+
+        if (!eglGetConfigAttrib(egl_disp, configs[i],
+                                EGL_NATIVE_VISUAL_ID, &val))
+          continue;
+        visid = val;
+        vi_in.screen = einfo->info.screen;
+        vi_in.visualid = visid;
+        xvi = XGetVisualInfo(einfo->info.display,
+                             VisualScreenMask |
+                             VisualIDMask,
+                             &vi_in, &nvi);
+        for (j = 0; j < nvi; j++)
+          {
+             if (!alpha)
                {
-                  ERR("eglChooseConfig() can't find any configs (gles%d, 
alpha: %d, depth: %d, stencil: %d, msaa: %d)",
-                      gles3_supported ? 3 : 2, alpha, depth_bits, 
stencil_bits, msaa_samples);
-                  if ((depth_bits > 24) || (stencil_bits > 8))
-                    {
-                       WRN("Please note that your driver might not support 
32-bit depth or "
-                           "16-bit stencil buffers, so depth24, stencil8 are 
the maximum "
-                           "recommended values.");
-                       if (depth_bits > 24) depth_bits = 24;
-                       if (stencil_bits > 8) stencil_bits = 8;
-                       DBG("Trying again with depth:%d, stencil:%d", 
depth_bits, stencil_bits);
-                       goto try_again;
-                    }
-                  else if (msaa_samples)
-                    {
-                       msaa_samples /= 2;
-                       DBG("Trying again with msaa_samples: %d", msaa_samples);
-                       goto try_again;
-                    }
-                  else if (depth_bits || stencil_bits)
+                  if (xvi[j].depth == depth)
                     {
-                       depth_bits = 0;
-                       stencil_bits = 0;
-                       DBG("Trying again without any depth or stencil buffer");
-                       goto try_again;
+                       memcpy(&evis->info, &(xvi[j]), sizeof(XVisualInfo));
+                       evis->config = configs[i];
+                       found = EINA_TRUE;
+                       break;
                     }
-                  return NULL;
                }
-             found = EINA_FALSE;
-             for (i = 0; (i < num) && (!found); i++)
+             else
                {
-                  EGLint val = 0;
-                  VisualID visid = 0;
-                  XVisualInfo *xvi, vi_in;
-                  int nvi, j;
-
-                  if (!eglGetConfigAttrib(egl_disp, configs[i],
-                                          EGL_NATIVE_VISUAL_ID, &val))
-                    continue;
-                  visid = val;
-                  vi_in.screen = einfo->info.screen;
-                  vi_in.visualid = visid;
-                  xvi = XGetVisualInfo(einfo->info.display,
-                                       VisualScreenMask |
-                                       VisualIDMask,
-                                       &vi_in, &nvi);
-                  for (j = 0; j < nvi; j++)
+                  XRenderPictFormat *fmt;
+
+                  fmt = XRenderFindVisualFormat
+                        (einfo->info.display, xvi[j].visual);
+                  if ((fmt->direct.alphaMask > 0) &&
+                      (fmt->type == PictTypeDirect))
                     {
-                       if (!alpha)
-                         {
-                            if (xvi[j].depth == depth)
-                              {
-                                 _evas_gl_x11_vi = malloc(sizeof(XVisualInfo));
-                                 if (_evas_gl_x11_vi)
-                                   memcpy(_evas_gl_x11_vi, &(xvi[j]), 
sizeof(XVisualInfo));
-                                 fbconf = configs[i];
-                                 found = EINA_TRUE;
-                                 break;
-                              }
-                         }
-                       else
-                         {
-                            XRenderPictFormat *fmt;
-
-                            fmt = XRenderFindVisualFormat
-                              (einfo->info.display, xvi[j].visual);
-                            if ((fmt->direct.alphaMask > 0) &&
-                                (fmt->type == PictTypeDirect))
-                              {
-                                 _evas_gl_x11_rgba_vi = 
malloc(sizeof(XVisualInfo));
-                                 if (_evas_gl_x11_rgba_vi)
-                                   memcpy(_evas_gl_x11_rgba_vi, &(xvi[j]), 
sizeof(XVisualInfo));
-                                 rgba_fbconf = configs[i];
-                                 found = EINA_TRUE;
-                                 break;
-                              }
-                         }
+                       memcpy(&evis->info, &(xvi[j]), sizeof(XVisualInfo));
+                       evis->config = configs[i];
+                       found = EINA_TRUE;
+                       break;
                     }
-                  if (xvi) XFree(xvi);
                }
-             if (!found)
+          }
+        if (xvi) XFree(xvi);
+     }
+   if (!found)
+     {
+        // this is a less correct fallback if the above fails to
+        // find the right visuals/configs
+        if (!alpha)
+          {
+             evis->config = configs[0];
+             XMatchVisualInfo(einfo->info.display,
+                              einfo->info.screen, depth, TrueColor,
+                              &evis->info);
+          }
+        else
+          {
+             XVisualInfo *xvi, vi_in;
+             int nvi, j;
+             XRenderPictFormat *fmt;
+
+             evis->config = configs[0];
+             vi_in.screen = einfo->info.screen;
+             vi_in.depth = 32;
+             vi_in.class = TrueColor;
+             xvi = XGetVisualInfo(einfo->info.display,
+                                  VisualScreenMask | VisualDepthMask |
+                                  VisualClassMask,
+                                  &vi_in, &nvi);
+             if (xvi)
                {
-                  // this is a less correct fallback if the above fails to
-                  // find the right visuals/configs
-                  if (!alpha)
-                    {
-                       fbconf = configs[0];
-                       _evas_gl_x11_vi = calloc(1, sizeof(XVisualInfo));
-                       if (_evas_gl_x11_vi)
-                         XMatchVisualInfo(einfo->info.display,
-                                          einfo->info.screen, depth, TrueColor,
-                                          _evas_gl_x11_vi);
-                    }
-                  else
+                  for (j = 0; j < nvi; j++)
                     {
-                       XVisualInfo *xvi, vi_in;
-                       int nvi, j;
-                       XRenderPictFormat *fmt;
-
-                       rgba_fbconf = configs[0];
-                       vi_in.screen = einfo->info.screen;
-                       vi_in.depth = 32;
-                       vi_in.class = TrueColor;
-                       xvi = XGetVisualInfo(einfo->info.display,
-                                            VisualScreenMask | VisualDepthMask 
|
-                                            VisualClassMask,
-                                            &vi_in, &nvi);
-                       if (xvi)
+                       fmt = XRenderFindVisualFormat(einfo->info.display,
+                                                     xvi[j].visual);
+                       if ((fmt->type == PictTypeDirect) &&
+                           (fmt->direct.alphaMask))
                          {
-                            for (j = 0; j < nvi; j++)
-                              {
-                                 fmt = 
XRenderFindVisualFormat(einfo->info.display,
-                                                               xvi[j].visual);
-                                 if ((fmt->type == PictTypeDirect) &&
-                                     (fmt->direct.alphaMask))
-                                   {
-                                      _evas_gl_x11_rgba_vi =
-                                        malloc(sizeof(XVisualInfo));
-                                      if (_evas_gl_x11_rgba_vi)
-                                        memcpy(_evas_gl_x11_rgba_vi,
-                                               &(xvi[j]), sizeof(XVisualInfo));
-                                      break;
-                                   }
-                              }
-                            XFree(xvi);
+                            memcpy(&evis->info, &(xvi[j]), 
sizeof(XVisualInfo));
+                            break;
                          }
                     }
+                  XFree(xvi);
                }
           }
-// GLX
+     }
+
+   // GLX
 #else
-        for (alpha = 0; alpha < 2; alpha++)
-          {
-             int config_attrs[40];
-             GLXFBConfig *configs = NULL, config = 0;
-             int i, num;
-             int depth_bits = einfo->depth_bits;
-             int stencil_bits = einfo->stencil_bits;
-             int msaa_samples = einfo->msaa_bits;
+   GLXFBConfig *configs = NULL, config = 0;
 
 try_again:
-             i = 0;
-             config_attrs[i++] = GLX_DRAWABLE_TYPE;
-             config_attrs[i++] = GLX_WINDOW_BIT;
-             config_attrs[i++] = GLX_DOUBLEBUFFER;
-             config_attrs[i++] = 1;
-             config_attrs[i++] = GLX_RED_SIZE;
-             config_attrs[i++] = 1;
-             config_attrs[i++] = GLX_GREEN_SIZE;
-             config_attrs[i++] = 1;
-             config_attrs[i++] = GLX_BLUE_SIZE;
-             config_attrs[i++] = 1;
-             if (alpha)
-               {
-                  config_attrs[i++] = GLX_RENDER_TYPE;
-                  config_attrs[i++] = GLX_RGBA_BIT;
-                  config_attrs[i++] = GLX_ALPHA_SIZE;
-                  config_attrs[i++] = 1;
-               }
-             else
-               {
-                  config_attrs[i++] = GLX_ALPHA_SIZE;
-                  config_attrs[i++] = 0;
-               }
-             config_attrs[i++] = GLX_DEPTH_SIZE;
-             config_attrs[i++] = depth_bits;
-             config_attrs[i++] = GLX_STENCIL_SIZE;
-             config_attrs[i++] = stencil_bits;
-             if (msaa_samples)
+   i = 0;
+   config_attrs[i++] = GLX_DRAWABLE_TYPE;
+   config_attrs[i++] = GLX_WINDOW_BIT;
+   config_attrs[i++] = GLX_DOUBLEBUFFER;
+   config_attrs[i++] = 1;
+   config_attrs[i++] = GLX_RED_SIZE;
+   config_attrs[i++] = 1;
+   config_attrs[i++] = GLX_GREEN_SIZE;
+   config_attrs[i++] = 1;
+   config_attrs[i++] = GLX_BLUE_SIZE;
+   config_attrs[i++] = 1;
+   if (alpha)
+     {
+        config_attrs[i++] = GLX_RENDER_TYPE;
+        config_attrs[i++] = GLX_RGBA_BIT;
+        config_attrs[i++] = GLX_ALPHA_SIZE;
+        config_attrs[i++] = 1;
+     }
+   else
+     {
+        config_attrs[i++] = GLX_ALPHA_SIZE;
+        config_attrs[i++] = 0;
+     }
+   if (depth_bits)
+     {
+        config_attrs[i++] = GLX_DEPTH_SIZE;
+        config_attrs[i++] = depth_bits;
+     }
+   if (stencil_bits)
+     {
+        config_attrs[i++] = GLX_STENCIL_SIZE;
+        config_attrs[i++] = stencil_bits;
+     }
+   if (msaa_samples)
+     {
+        config_attrs[i++] = GLX_SAMPLE_BUFFERS;
+        config_attrs[i++] = 1;
+        config_attrs[i++] = GLX_SAMPLES;
+        config_attrs[i++] = msaa_samples;
+     }
+   config_attrs[i++] = GLX_AUX_BUFFERS;
+   config_attrs[i++] = 0;
+   config_attrs[i++] = GLX_STEREO;
+   config_attrs[i++] = 0;
+   config_attrs[i++] = GLX_TRANSPARENT_TYPE;
+   config_attrs[i++] = GLX_NONE;//GLX_TRANSPARENT_INDEX,GLX_TRANSPARENT_RGB
+   config_attrs[i++] = 0;
+
+   configs = glXChooseFBConfig(einfo->info.display,
+                               einfo->info.screen,
+                               config_attrs, &num);
+   if ((!configs) || (num < 1))
+     {
+        ERR("glXChooseFBConfig() can't find any configs (alpha: %d, depth: %d, 
stencil: %d, msaa: %d)",
+            alpha, depth_bits, stencil_bits, msaa_samples);
+        if ((depth_bits > 24) || (stencil_bits > 8))
+          {
+             WRN("Please note that your driver might not support 32-bit depth 
or "
+                 "16-bit stencil buffers, so depth24, stencil8 are the maximum 
"
+                 "recommended values.");
+             if (depth_bits > 24) depth_bits = 24;
+             if (stencil_bits > 8) stencil_bits = 8;
+             DBG("Trying again with depth:%d, stencil:%d", depth_bits, 
stencil_bits);
+             goto try_again;
+          }
+        else if (msaa_samples)
+          {
+             msaa_samples /= 2;
+             DBG("Trying again with msaa_samples: %d", msaa_samples);
+             goto try_again;
+          }
+        else if (depth_bits || stencil_bits)
+          {
+             depth_bits = 0;
+             stencil_bits = 0;
+             DBG("Trying again without any depth or stencil buffer");
+             goto try_again;
+          }
+        free(evis);
+        return NULL;
+     }
+
+   found = EINA_FALSE;
+   for (i = 0; (i < num) && !found; i++)
+     {
+        XVisualInfo *visinfo;
+        XRenderPictFormat *format = NULL;
+
+        visinfo = glXGetVisualFromFBConfig(einfo->info.display,
+                                           configs[i]);
+        if (!visinfo) continue;
+        if (visinfo->visual->class != TrueColor)
+          {
+             XFree(visinfo);
+             continue;
+          }
+        if (!alpha)
+          {
+             config = configs[i];
+             // ensure depth matches default depth!
+             if (DefaultDepth(einfo->info.display, 0) ==
+                 visinfo->depth)
                {
-                  config_attrs[i++] = GLX_SAMPLE_BUFFERS;
-                  config_attrs[i++] = 1;
-                  config_attrs[i++] = GLX_SAMPLES;
-                  config_attrs[i++] = msaa_samples;
+                  memcpy(&evis->info, visinfo, sizeof(XVisualInfo));
+                  evis->config = config;
+                  found = EINA_TRUE;
+                  XFree(visinfo);
+                  break;
                }
-             config_attrs[i++] = GLX_AUX_BUFFERS;
-             config_attrs[i++] = 0;
-             config_attrs[i++] = GLX_STEREO;
-             config_attrs[i++] = 0;
-             config_attrs[i++] = GLX_TRANSPARENT_TYPE;
-             config_attrs[i++] = 
GLX_NONE;//GLX_NONE;//GLX_TRANSPARENT_INDEX//GLX_TRANSPARENT_RGB;
-             config_attrs[i++] = 0;
-
-             configs = glXChooseFBConfig(einfo->info.display,
-                                         einfo->info.screen,
-                                         config_attrs, &num);
-             if ((!configs) || (num < 1))
+          }
+        else
+          {
+             format = XRenderFindVisualFormat
+                   (einfo->info.display, visinfo->visual);
+             if (!format)
                {
-                  ERR("glXChooseFBConfig() can't find any configs (alpha: %d, 
depth: %d, stencil: %d, msaa: %d)",
-                      alpha, depth_bits, stencil_bits, msaa_samples);
-                  if ((depth_bits > 24) || (stencil_bits > 8))
-                    {
-                       WRN("Please note that your driver might not support 
32-bit depth or "
-                           "16-bit stencil buffers, so depth24, stencil8 are 
the maximum "
-                           "recommended values.");
-                       if (depth_bits > 24) depth_bits = 24;
-                       if (stencil_bits > 8) stencil_bits = 8;
-                       DBG("Trying again with depth:%d, stencil:%d", 
depth_bits, stencil_bits);
-                       goto try_again;
-                    }
-                  else if (msaa_samples)
-                    {
-                       msaa_samples /= 2;
-                       DBG("Trying again with msaa_samples: %d", msaa_samples);
-                       goto try_again;
-                    }
-                  else if (depth_bits || stencil_bits)
-                    {
-                       depth_bits = 0;
-                       stencil_bits = 0;
-                       DBG("Trying again without any depth or stencil buffer");
-                       goto try_again;
-                    }
-                  return NULL;
+                  XFree(visinfo);
+                  continue;
                }
-             for (i = 0; i < num; i++)
+             if ((format->direct.alphaMask > 0) &&
+                 (format->type == PictTypeDirect))
                {
-                  XVisualInfo *visinfo;
-                  XRenderPictFormat *format = NULL;
-
-                  visinfo = glXGetVisualFromFBConfig(einfo->info.display,
-                                                     configs[i]);
-                  if (!visinfo) continue;
-                  if (visinfo->visual->class != TrueColor)
-                    {
-                       XFree(visinfo);
-                       continue;
-                    }
-                  if (!alpha)
-                    {
-                       config = configs[i];
-                       // ensure depth matches default depth!
-                       if (DefaultDepth(einfo->info.display, 0) ==
-                           visinfo->depth)
-                         {
-                            _evas_gl_x11_vi = malloc(sizeof(XVisualInfo));
-                            if (_evas_gl_x11_vi)
-                              memcpy(_evas_gl_x11_vi, visinfo, 
sizeof(XVisualInfo));
-                            fbconf = config;
-                            XFree(visinfo);
-                            break;
-                         }
-                    }
-                  else
-                    {
-                       format = XRenderFindVisualFormat
-                         (einfo->info.display, visinfo->visual);
-                       if (!format)
-                         {
-                            XFree(visinfo);
-                            continue;
-                         }
-                       if ((format->direct.alphaMask > 0) &&
-                           (format->type == PictTypeDirect))
-                         {
-                            config = configs[i];
-                            _evas_gl_x11_rgba_vi = malloc(sizeof(XVisualInfo));
-                            if (_evas_gl_x11_rgba_vi)
-                              memcpy(_evas_gl_x11_rgba_vi, visinfo, 
sizeof(XVisualInfo));
-                            rgba_fbconf = config;
-                            _evas_gl_x11_rgba_cmap = format->colormap;
-                            XFree(visinfo);
-                            break;
-                         }
-                    }
+                  memcpy(&evis->info, visinfo, sizeof(XVisualInfo));
+                  evis->config = configs[i];
+                  evis->cmap = format->colormap;
+                  found = EINA_TRUE;
                   XFree(visinfo);
+                  break;
                }
           }
-#endif
+        XFree(visinfo);
      }
-   if (!_evas_gl_x11_vi) return NULL;
-   if (einfo->info.destination_alpha)
+
+   if (!found)
+     {
+        ERR("Could not find a matching config. Now what?");
+        free(evis);
+        return NULL;
+     }
+#endif
+
+   if (!evis->cmap)
      {
-        if (_evas_gl_x11_rgba_vi) return _evas_gl_x11_rgba_vi->visual;
+        /* save colormap now */
+        evis->cmap = XCreateColormap(einfo->info.display,
+                                    RootWindow(einfo->info.display,
+                                               einfo->info.screen),
+                                    evis->info.visual, 0);
      }
-   return _evas_gl_x11_vi->visual;
+
+   eina_hash_add(_evas_gl_visuals, &idx, evis);
+   return evis->info.visual;
 }
 
 Colormap
 eng_best_colormap_get(Evas_Engine_Info_GL_X11 *einfo)
 {
+   Evas_GL_X11_Visual *evis;
+   int idx;
+
    if (!einfo) return 0;
    if (!einfo->info.display) return 0;
-   if (!_evas_gl_x11_vi) eng_best_visual_get(einfo);
-   if (!_evas_gl_x11_vi) return 0;
-   if ((einfo->info.destination_alpha) && (_evas_gl_x11_rgba_vi))
-     {
-        if (!_evas_gl_x11_rgba_cmap)
-          _evas_gl_x11_rgba_cmap =
-          XCreateColormap(einfo->info.display,
-                          RootWindow(einfo->info.display,
-                                     einfo->info.screen),
-                          _evas_gl_x11_rgba_vi->visual,
-                          0);
-        return _evas_gl_x11_rgba_cmap;
-     }
-   if (!_evas_gl_x11_cmap)
-     _evas_gl_x11_cmap =
-     XCreateColormap(einfo->info.display,
-                     RootWindow(einfo->info.display,
-                                einfo->info.screen),
-                     _evas_gl_x11_vi->visual,
-                     0);
-   return _evas_gl_x11_cmap;
+   idx = _visuals_hash_index_get_from_info(einfo);
+   evis = eina_hash_find(_evas_gl_visuals, &idx);
+   if (!evis)
+     {
+        eng_best_visual_get(einfo);
+        evis = eina_hash_find(_evas_gl_visuals, &idx);
+        if (!evis) return 0;
+     }
+   return evis->cmap;
 }
 
 int
 eng_best_depth_get(Evas_Engine_Info_GL_X11 *einfo)
 {
+   Evas_GL_X11_Visual *evis;
+   int idx;
+
    if (!einfo) return 0;
    if (!einfo->info.display) return 0;
-   if (!_evas_gl_x11_vi) eng_best_visual_get(einfo);
-   if (!_evas_gl_x11_vi) return 0;
-   if (einfo->info.destination_alpha)
+   idx = _visuals_hash_index_get_from_info(einfo);
+   evis = eina_hash_find(_evas_gl_visuals, &idx);
+   if (!evis)
      {
-        if (_evas_gl_x11_rgba_vi) return _evas_gl_x11_rgba_vi->depth;
+        eng_best_visual_get(einfo);
+        evis = eina_hash_find(_evas_gl_visuals, &idx);
+        if (!evis) return 0;
      }
-   return _evas_gl_x11_vi->depth;
+   return evis->info.depth;
 }
 
 Context_3D *

-- 


Reply via email to