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 * --