From 696346c4673f2d88b562c02750277a5fb3e41f9e Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Sat, 25 Oct 2014 20:04:52 +0900 Subject: [PATCH] evas gl rgba visual/rendering fix try ... again so this is a re-try at the evas gl destination alpha fix. this is what cedric tried, but done RIGHT. it required adding an ecore_x call to create a window with correct visual/colormap. it requires doing visuals totally correctly all the way from ecore_evas to the evas gl_x11 core. nvidia drivers are very picky about visuals. i also had to vid the egl/gles code too to do the same thing. nvidia gles/egl drivers are also picky, mesa is not. this all requires a lot of code changes. it's far from trivial this isn't backported for a few reasons: 1. verify this fix doesn't break for anyone. i tested: nvidia glx + egl/gles intel glx + egl/gles radeon glx it needs wider testing. nouveau, fglrx for starters and maybe some other gles/egl drivers. 2. have some review time 3. time to settle before blasting to stable branches @fix --- src/lib/ecore_x/Ecore_X.h | 11 + src/lib/ecore_x/xcb/ecore_xcb_window.c | 62 +++ src/lib/ecore_x/xlib/ecore_x_window.c | 63 +++ src/modules/ecore_evas/engines/x/ecore_evas_x.c | 21 +- src/modules/evas/engines/gl_x11/evas_engine.c | 26 +- src/modules/evas/engines/gl_x11/evas_engine.h | 11 +- src/modules/evas/engines/gl_x11/evas_x_main.c | 604 ++++++++++++------------ 7 files changed, 464 insertions(+), 334 deletions(-) diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h index c3f0726..7272b6a 100644 --- a/src/lib/ecore_x/Ecore_X.h +++ b/src/lib/ecore_x/Ecore_X.h @@ -1469,6 +1469,17 @@ EAPI Ecore_X_Atom ecore_x_dnd_source_action_get(void); EAPI void ecore_x_dnd_callback_pos_update_set(void (*cb)(void *, Ecore_X_Xdnd_Position *data), const void *data); EAPI Eina_Bool ecore_x_dnd_abort(Ecore_X_Window xwin_source); /**< @since 1.9 */ +EAPI Ecore_X_Window + ecore_x_window_full_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h, + Ecore_X_Visual *visual, + Ecore_X_Colormap colormap, + int depth, + Eina_Bool override); /**< @since 1.12 */ + EAPI Ecore_X_Window ecore_x_window_new(Ecore_X_Window parent, int x, int y, int w, int h); EAPI Ecore_X_Window ecore_x_window_override_new(Ecore_X_Window parent, int x, int y, int w, int h); EAPI int ecore_x_window_argb_get(Ecore_X_Window win); diff --git a/src/lib/ecore_x/xcb/ecore_xcb_window.c b/src/lib/ecore_x/xcb/ecore_xcb_window.c index e89c74b..243eb69 100644 --- a/src/lib/ecore_x/xcb/ecore_xcb_window.c +++ b/src/lib/ecore_x/xcb/ecore_xcb_window.c @@ -51,6 +51,68 @@ void *_ecore_xcb_window_grab_replay_data; * Functions that can be used to create an X window. */ +EAPI Ecore_X_Window +ecore_x_window_full_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h, + Ecore_X_Visual *visual, + Ecore_X_Colormap colormap, + int depth, + Eina_Bool override) +{ + Ecore_X_Window win; + uint32_t mask, mask_list[10]; + xcb_visualtype_t *vis; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + CHECK_XCB_CONN; + + if (parent == 0) + parent = ((xcb_screen_t *)_ecore_xcb_screen)->root; + + vis = (xcb_visualtype_t *)visual; + + /* NB: Order here is very important due to xcb_cw_t enum */ + mask = (XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL | XCB_CW_BIT_GRAVITY | + XCB_CW_WIN_GRAVITY | XCB_CW_BACKING_STORE | + XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK | + XCB_CW_DONT_PROPAGATE | XCB_CW_COLORMAP); + + mask_list[0] = XCB_BACK_PIXMAP_NONE; + mask_list[1] = 0; + mask_list[2] = XCB_GRAVITY_NORTH_WEST; + mask_list[3] = XCB_GRAVITY_NORTH_WEST; + mask_list[4] = XCB_BACKING_STORE_NOT_USEFUL; + mask_list[5] = override; + mask_list[6] = 0; + mask_list[7] = (XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | + XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW | + XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE | + XCB_EVENT_MASK_VISIBILITY_CHANGE | + XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_PROPERTY_CHANGE | + XCB_EVENT_MASK_COLOR_MAP_CHANGE); + mask_list[8] = XCB_EVENT_MASK_NO_EVENT; + value_list[9] = colormap; + + win = xcb_generate_id(_ecore_xcb_conn); + xcb_create_window(_ecore_xcb_conn, XCB_COPY_FROM_PARENT, + win, parent, x, y, w, h, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + vis ? vis->visual_id : XCB_COPY_FROM_PARENT, + mask, mask_list); + + if (parent == ((xcb_screen_t *)_ecore_xcb_screen)->root) + ecore_x_window_defaults_set(win); + + return win; +} + /** * Creates a new window. * @param parent The parent window to use. If @p parent is @c 0, the root diff --git a/src/lib/ecore_x/xlib/ecore_x_window.c b/src/lib/ecore_x/xlib/ecore_x_window.c index 2fac34a..1a7667c 100644 --- a/src/lib/ecore_x/xlib/ecore_x_window.c +++ b/src/lib/ecore_x/xlib/ecore_x_window.c @@ -21,6 +21,69 @@ static Ecore_X_Window *ignore_list = NULL; * Functions that can be used to create an X window. */ +EAPI Ecore_X_Window +ecore_x_window_full_new(Ecore_X_Window parent, + int x, + int y, + int w, + int h, + Ecore_X_Visual *visual, + Ecore_X_Colormap colormap, + int depth, + Eina_Bool override) +{ + Window win; + XSetWindowAttributes attr; + + LOGFN(__FILE__, __LINE__, __FUNCTION__); + if (parent == 0) + parent = DefaultRootWindow(_ecore_x_disp); + + attr.backing_store = NotUseful; + attr.override_redirect = override; + attr.border_pixel = 0; + attr.background_pixmap = None; + attr.bit_gravity = NorthWestGravity; + attr.win_gravity = NorthWestGravity; + attr.save_under = False; + attr.do_not_propagate_mask = NoEventMask; + attr.colormap = (Colormap)colormap; + attr.event_mask = KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + EnterWindowMask | + LeaveWindowMask | + PointerMotionMask | + ExposureMask | + VisibilityChangeMask | + StructureNotifyMask | + FocusChangeMask | + PropertyChangeMask | + ColormapChangeMask; + win = XCreateWindow(_ecore_x_disp, parent, + x, y, w, h, 0, + depth, + InputOutput, + (Visual *)visual, + CWBackingStore | + CWOverrideRedirect | + (colormap ? CWColormap : 0) | + CWBorderPixel | + CWBackPixmap | + CWSaveUnder | + CWDontPropagate | + CWEventMask | + CWBitGravity | + CWWinGravity, + &attr); + if (_ecore_xlib_sync) ecore_x_sync(); + if (parent == DefaultRootWindow(_ecore_x_disp)) + ecore_x_window_defaults_set(win); + + return win; +} + /** * Creates a new window. * @param parent The parent window to use. If @p parent is @c 0, the root diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c b/src/modules/ecore_evas/engines/x/ecore_evas_x.c index 5bd821c..26593bf 100644 --- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c +++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c @@ -480,22 +480,11 @@ _ecore_evas_x_gl_window_new(Ecore_Evas *ee, Ecore_X_Window parent, int x, int y, return 0; } } - - if (argb) - { - if (override) - win = ecore_x_window_override_argb_new(parent, x, y, w, h); - else - win = ecore_x_window_argb_new(parent, x, y, w, h); - } - else - { - if (override) - win = ecore_x_window_override_new(parent, x, y, w, h); - else - win = ecore_x_window_new(parent, x, y, w, h); - } - + win = ecore_x_window_full_new(parent, x, y, w, h, + einfo->info.visual, + einfo->info.colormap, + einfo->info.depth, + override); ecore_x_window_pixel_gravity_set(win, ECORE_X_GRAVITY_FORGET); ecore_x_vsync_animator_tick_source_set(win); diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c b/src/modules/evas/engines/gl_x11/evas_engine.c index 477e2fc..1fe13be 100644 --- a/src/modules/evas/engines/gl_x11/evas_engine.c +++ b/src/modules/evas/engines/gl_x11/evas_engine.c @@ -271,7 +271,7 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush) if ((!context) && (!surface)) { - ret = glXMakeCurrent(eng_get_ob(re)->info->info.display, None, NULL); + ret = __glXMakeContextCurrent(eng_get_ob(re)->info->info.display, 0, NULL); if (!ret) { ERR("glXMakeCurrent() failed!"); @@ -289,8 +289,13 @@ evgl_eng_make_current(void *data, void *surface, void *context, int flush) if (flush) eng_window_use(NULL); // Do a make current - ret = glXMakeCurrent(eng_get_ob(re)->info->info.display, sfc, ctx); - + if ((sfc == eng_get_ob(re)->win) || + (sfc == eng_get_ob(re)->glxwin)) + ret = __glXMakeContextCurrent(eng_get_ob(re)->info->info.display, + eng_get_ob(re)->glxwin, ctx); + else + ret = __glXMakeContextCurrent(eng_get_ob(re)->info->info.display, + sfc, ctx); if (!ret) { ERR("glXMakeCurrent() failed. Ret: %d! Context: %p Surface: %p", ret, (void*)ctx, (void*)sfc); @@ -331,8 +336,8 @@ evgl_eng_native_window_create(void *data) attr.event_mask = 0; win = XCreateWindow(eng_get_ob(re)->info->info.display, - DefaultRootWindow(eng_get_ob(re)->info->info.display), - 0, 0, 2, 2, 0, + eng_get_ob(re)->win, + -20, -20, 2, 2, 0, CopyFromParent, InputOutput, CopyFromParent, CWBackingStore | CWOverrideRedirect | CWBorderPixel | CWBackPixmap | @@ -403,6 +408,7 @@ evgl_eng_window_surface_create(void *data, void *native_window EINA_UNUSED) if (!surface) { ERR("Creating window surface failed. Error: %#x.", eglGetError()); + abort(); return NULL; } @@ -1445,7 +1451,11 @@ eng_setup(Evas *eo_e, void *in) info->info.destination_alpha, info->info.rotation, swap_mode); - + if (!ob) + { + free(re); + return 0; + } eng_window_use(ob); if (ob) { @@ -1561,7 +1571,7 @@ eng_preload_make_current(void *data, void *doit) if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0], ob->egl_surface[0], ob->egl_context[0])) return EINA_FALSE; #else - if (!glXMakeCurrent(ob->info->info.display, ob->win, ob->context)) + if (!__glXMakeContextCurrent(ob->info->info.display, ob->glxwin, ob->context)) { ERR("glXMakeCurrent(%p, 0x%x, %p) failed", ob->info->info.display, (unsigned int)ob->win, (void *)ob->context); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); @@ -1575,7 +1585,7 @@ eng_preload_make_current(void *data, void *doit) if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) return EINA_FALSE; #else - if (!glXMakeCurrent(ob->info->info.display, None, NULL)) + if (!__glXMakeContextCurrent(ob->info->info.display, 0, NULL)) { ERR("glXMakeCurrent(%p, None, NULL) failed", ob->info->info.display); GLERR(__FUNCTION__, __FILE__, __LINE__, ""); diff --git a/src/modules/evas/engines/gl_x11/evas_engine.h b/src/modules/evas/engines/gl_x11/evas_engine.h index 37ffb93..347c41f 100644 --- a/src/modules/evas/engines/gl_x11/evas_engine.h +++ b/src/modules/evas/engines/gl_x11/evas_engine.h @@ -61,16 +61,15 @@ extern int _evas_engine_GL_X11_log_dom ; struct _Outbuf { #ifdef GL_GLES - EGLContext egl_context[1]; - EGLSurface egl_surface[1]; + EGLContext egl_context[2]; + EGLSurface egl_surface[2]; EGLConfig egl_config; EGLDisplay egl_disp; #else GLXContext context; GLXWindow glxwin; - struct { - unsigned int loose_binding : 1; + Eina_Bool loose_binding : 1; } detected; #endif @@ -202,4 +201,8 @@ _re_wincheck(Outbuf *ob) return 0; } +#ifndef GL_GLES +Eina_Bool __glXMakeContextCurrent(Display *disp, GLXDrawable glxwin, + GLXContext context); +#endif #endif 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 208e42c..dc8c36f 100644 --- a/src/modules/evas/engines/gl_x11/evas_x_main.c +++ b/src/modules/evas/engines/gl_x11/evas_x_main.c @@ -5,6 +5,8 @@ static Eina_TLS _context_key = 0; #ifdef GL_GLES typedef EGLContext GLContext; +static EGLConfig fbconf = 0; +static EGLConfig rgba_fbconf = 0; #else // FIXME: this will only work for 1 display connection (glx land can have > 1) typedef GLXContext GLContext; @@ -13,9 +15,6 @@ static GLXFBConfig fbconf = 0; static GLXFBConfig rgba_fbconf = 0; #endif -// fixme: something is up/wrong here - dont know what tho... -//#define NEWGL 1 - static XVisualInfo *_evas_gl_x11_vi = NULL; static XVisualInfo *_evas_gl_x11_rgba_vi = NULL; static Colormap _evas_gl_x11_cmap = 0; @@ -95,6 +94,13 @@ _tls_rgba_context_set(GLXContext ctx) if (!initted) eng_init(); return eina_tls_set(_rgba_context_key, ctx); } + +Eina_Bool +__glXMakeContextCurrent(Display *disp, GLXDrawable glxwin, GLXContext context) +{ + if (!glXMakeContextCurrent(disp, glxwin, glxwin, context)) return EINA_FALSE; + return EINA_TRUE; +} #endif Outbuf * @@ -117,17 +123,14 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, GLContext context; #ifdef GL_GLES int context_attrs[3]; - int config_attrs[40]; int major_version, minor_version; - int num_config, n = 0; #else -# ifdef NEWGL GLXContext rgbactx; -# endif #endif const GLubyte *vendor, *renderer, *version; int blacklist = 0; + if (!fbconf) eng_best_visual_get(info); if (!_evas_gl_x11_vi) return NULL; gw = calloc(1, sizeof(Outbuf)); @@ -159,36 +162,6 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, context_attrs[1] = 2; context_attrs[2] = EGL_NONE; - config_attrs[n++] = EGL_SURFACE_TYPE; - config_attrs[n++] = EGL_WINDOW_BIT; - config_attrs[n++] = EGL_RENDERABLE_TYPE; - config_attrs[n++] = 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 -# endif - if (gw->alpha) - { - config_attrs[n++] = EGL_ALPHA_SIZE; - config_attrs[n++] = 1; - } - else - { - config_attrs[n++] = EGL_ALPHA_SIZE; - config_attrs[n++] = 0; - } - config_attrs[n++] = EGL_DEPTH_SIZE; - config_attrs[n++] = 0; - config_attrs[n++] = EGL_STENCIL_SIZE; - config_attrs[n++] = 0; - config_attrs[n++] = EGL_NONE; - gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)(gw->disp)); if (!gw->egl_disp) { @@ -210,19 +183,15 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, return NULL; } - num_config = 0; - if (!eglChooseConfig(gw->egl_disp, config_attrs, &gw->egl_config, - 1, &num_config) || (num_config != 1)) - { - ERR("eglChooseConfig() fail. code=%#x", eglGetError()); - eng_window_free(gw); - return NULL; - } + if (gw->alpha) gw->egl_config = rgba_fbconf; + else gw->egl_config = fbconf; + gw->egl_surface[0] = eglCreateWindowSurface(gw->egl_disp, gw->egl_config, (EGLNativeWindowType)gw->win, NULL); if (gw->egl_surface[0] == EGL_NO_SURFACE) { + printf("surf creat fail! %x\n", eglGetError()); ERR("eglCreateWindowSurface() fail for %#x. code=%#x", (unsigned int)gw->win, eglGetError()); eng_window_free(gw); @@ -287,7 +256,6 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, context = _tls_context_get(); if (!context) { -#ifdef NEWGL if (indirect) context = glXCreateNewContext(gw->disp, fbconf, GLX_RGBA_TYPE, NULL, @@ -296,15 +264,8 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, context = glXCreateNewContext(gw->disp, fbconf, GLX_RGBA_TYPE, NULL, GL_TRUE); -#else - if (indirect) - context = glXCreateContext(gw->disp, gw->visualinfo, NULL, GL_FALSE); - else - context = glXCreateContext(gw->disp, gw->visualinfo, NULL, GL_TRUE); -#endif _tls_context_set(context); } -#ifdef NEWGL rgbactx = _tls_rgba_context_get(); if ((gw->alpha) && (!rgbactx)) { @@ -331,9 +292,6 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, if (gw->alpha) gw->context = rgbactx; else gw->context = context; -#else - gw->context = context; -#endif if (!gw->context) { @@ -341,142 +299,122 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, eng_window_free(gw); return NULL; } - if (gw->context) + if (!__glXMakeContextCurrent(gw->disp, gw->glxwin, gw->context)) { - if (gw->glxwin) - { - if (!glXMakeContextCurrent(gw->disp, gw->glxwin, gw->glxwin, - gw->context)) - { - ERR("glXMakeContextCurrent(%p, %p, %p, %p) failed", - (void *)gw->disp, (void *)gw->glxwin, (void *)gw->glxwin, - (void *)gw->context); - eng_window_free(gw); - return NULL; - } - } - else - { - if (!glXMakeCurrent(gw->disp, gw->win, gw->context)) - { - ERR("glXMakeCurrent(%p, 0x%x, %p) failed", (void *)gw->disp, - (unsigned int)gw->win, (void *)gw->context); - eng_window_free(gw); - return NULL; - } - } - - // FIXME: move this up to context creation + ERR("glXMakeContextCurrent(%p, %p, %p, %p)\n", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->win, (void *)gw->context); + eng_window_free(gw); + return NULL; + } + // FIXME: move this up to context creation - vendor = glGetString(GL_VENDOR); - renderer = glGetString(GL_RENDERER); - version = glGetString(GL_VERSION); - if (getenv("EVAS_GL_INFO")) - { - fprintf(stderr, "vendor: %s\n", vendor); - fprintf(stderr, "renderer: %s\n", renderer); - fprintf(stderr, "version: %s\n", version); - } - // examples: - // vendor: NVIDIA Corporation - // renderer: NVIDIA Tegra - // version: OpenGL ES 2.0 - // or - // vendor: Imagination Technologies - // renderer: PowerVR SGX 540 - // version: OpenGL ES 2.0 - // or - // vendor: NVIDIA Corporation - // renderer: GeForce GT 330M/PCI/SSE2 - // version: 3.3.0 NVIDIA 256.53 - // or - // vendor: NVIDIA Corporation - // renderer: GeForce GT 220/PCI/SSE2 - // version: 3.2.0 NVIDIA 195.36.24 - // or - // vendor: NVIDIA Corporation - // renderer: GeForce 8600 GTS/PCI/SSE2 - // version: 3.3.0 NVIDIA 260.19.36 - // or - // vendor: ATI Technologies Inc. - // renderer: ATI Mobility Radeon HD 4650 - // version: 3.2.9756 Compatibility Profile Context - // or - // vendor: Tungsten Graphics, Inc - // renderer: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100330 DEVELOPMENT x86/MMX/SSE2 - // version: 2.1 Mesa 7.9-devel - // or - // vendor: Advanced Micro Devices, Inc. - // renderer: Mesa DRI R600 (RS780 9610) 20090101 TCL DRI2 - // version: 2.1 Mesa 7.9-devel - // or - // vendor: NVIDIA Corporation - // renderer: GeForce 9600 GT/PCI/SSE2 - // version: 3.3.0 NVIDIA 260.19.29 - // or - // vendor: ATI Technologies Inc. - // renderer: ATI Radeon HD 4800 Series - // version: 3.3.10237 Compatibility Profile Context - // or - // vendor: Advanced Micro Devices, Inc. - // renderer: Mesa DRI R600 (RV770 9442) 20090101 TCL DRI2 - // version: 2.0 Mesa 7.8.2 - // or - // vendor: Tungsten Graphics, Inc - // renderer: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100330 DEVELOPMENT - // version: 2.1 Mesa 7.9-devel - // or (bad - software renderer) - // vendor: Mesa Project - // renderer: Software Rasterizer - // version: 2.1 Mesa 7.9-devel - // or (bad - software renderer) - // vendor: VMware, Inc. - // renderer: Gallium 0.4 on softpipe - // version: 2.1 Mesa 7.9-devel - - if (strstr((const char *)vendor, "Mesa Project")) - { - if (strstr((const char *)renderer, "Software Rasterizer")) - blacklist = 1; - } - if (strstr((const char *)renderer, "softpipe")) - blacklist = 1; - if (strstr((const char *)renderer, "llvmpipe")) + vendor = glGetString(GL_VENDOR); + renderer = glGetString(GL_RENDERER); + version = glGetString(GL_VERSION); + if (getenv("EVAS_GL_INFO")) + { + fprintf(stderr, "vendor: %s\n", vendor); + fprintf(stderr, "renderer: %s\n", renderer); + fprintf(stderr, "version: %s\n", version); + } + // examples: + // vendor: NVIDIA Corporation + // renderer: NVIDIA Tegra + // version: OpenGL ES 2.0 + // or + // vendor: Imagination Technologies + // renderer: PowerVR SGX 540 + // version: OpenGL ES 2.0 + // or + // vendor: NVIDIA Corporation + // renderer: GeForce GT 330M/PCI/SSE2 + // version: 3.3.0 NVIDIA 256.53 + // or + // vendor: NVIDIA Corporation + // renderer: GeForce GT 220/PCI/SSE2 + // version: 3.2.0 NVIDIA 195.36.24 + // or + // vendor: NVIDIA Corporation + // renderer: GeForce 8600 GTS/PCI/SSE2 + // version: 3.3.0 NVIDIA 260.19.36 + // or + // vendor: ATI Technologies Inc. + // renderer: ATI Mobility Radeon HD 4650 + // version: 3.2.9756 Compatibility Profile Context + // or + // vendor: Tungsten Graphics, Inc + // renderer: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100330 DEVELOPMENT x86/MMX/SSE2 + // version: 2.1 Mesa 7.9-devel + // or + // vendor: Advanced Micro Devices, Inc. + // renderer: Mesa DRI R600 (RS780 9610) 20090101 TCL DRI2 + // version: 2.1 Mesa 7.9-devel + // or + // vendor: NVIDIA Corporation + // renderer: GeForce 9600 GT/PCI/SSE2 + // version: 3.3.0 NVIDIA 260.19.29 + // or + // vendor: ATI Technologies Inc. + // renderer: ATI Radeon HD 4800 Series + // version: 3.3.10237 Compatibility Profile Context + // or + // vendor: Advanced Micro Devices, Inc. + // renderer: Mesa DRI R600 (RV770 9442) 20090101 TCL DRI2 + // version: 2.0 Mesa 7.8.2 + // or + // vendor: Tungsten Graphics, Inc + // renderer: Mesa DRI Mobile Intel® GM45 Express Chipset GEM 20100330 DEVELOPMENT + // version: 2.1 Mesa 7.9-devel + // or (bad - software renderer) + // vendor: Mesa Project + // renderer: Software Rasterizer + // version: 2.1 Mesa 7.9-devel + // or (bad - software renderer) + // vendor: VMware, Inc. + // renderer: Gallium 0.4 on softpipe + // version: 2.1 Mesa 7.9-devel + // + if (strstr((const char *)vendor, "Mesa Project")) + { + if (strstr((const char *)renderer, "Software Rasterizer")) blacklist = 1; - if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST"))) - { - WRN("OpenGL Driver blacklisted:"); - WRN("Vendor: %s", (const char *)vendor); - WRN("Renderer: %s", (const char *)renderer); - WRN("Version: %s", (const char *)version); - eng_window_free(gw); - return NULL; - } - if (strstr((const char *)vendor, "NVIDIA")) + } + if (strstr((const char *)renderer, "softpipe")) + blacklist = 1; + if (strstr((const char *)renderer, "llvmpipe")) + blacklist = 1; + if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST"))) + { + WRN("OpenGL Driver blacklisted:"); + WRN("Vendor: %s", (const char *)vendor); + WRN("Renderer: %s", (const char *)renderer); + WRN("Version: %s", (const char *)version); + eng_window_free(gw); + return NULL; + } + if (strstr((const char *)vendor, "NVIDIA")) + { + if (!strstr((const char *)renderer, "NVIDIA Tegra")) { - if (!strstr((const char *)renderer, "NVIDIA Tegra")) - { - int v1 = 0, v2 = 0, v3 = 0; + int v1 = 0, v2 = 0, v3 = 0; + if (sscanf((const char *)version, + "%*s %*s %i.%i.%i", + &v1, &v2, &v3) != 3) + { + v1 = v2 = v3 = 0; if (sscanf((const char *)version, - "%*s %*s %i.%i.%i", - &v1, &v2, &v3) != 3) - { - v1 = v2 = v3 = 0; - if (sscanf((const char *)version, - "%*s %*s %i.%i", - &v1, &v2) != 2) - v1 = 0; - } - // ALSO as of some nvidia driver version loose binding is - // probably not needed - if (v1 < 195) gw->detected.loose_binding = 1; + "%*s %*s %i.%i", + &v1, &v2) != 2) + v1 = 0; } + // ALSO as of some nvidia driver version loose binding is + // probably not needed + if (v1 < 195) gw->detected.loose_binding = 1; } - else - { - // noothing yet. add more cases and options over time - } + } + else + { + // noothing yet. add more cases and options over time } #endif @@ -495,8 +433,6 @@ eng_window_new(Evas_Engine_Info_GL_X11 *info, glsym_evas_gl_common_context_resize(gw->gl_context, w, h, rot); gw->surf = 1; return gw; -// unused warnign handled in mcro above -// (void) (indirect = 0); } void @@ -531,13 +467,16 @@ eng_window_free(Outbuf *gw) eglTerminate(gw->egl_disp); eglReleaseThread(); _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 - if (gw->glxwin) - { - glXMakeContextCurrent(gw->disp, 0, 0, gw->context); - glXDestroyWindow(gw->disp, gw->glxwin); - } + __glXMakeContextCurrent(gw->disp, 0, gw->context); + glXDestroyWindow(gw->disp, gw->glxwin); if (ref == 0) { GLXContext rgbactx = _tls_rgba_context_get(); @@ -548,10 +487,14 @@ eng_window_free(Outbuf *gw) } if (context) glXDestroyContext(gw->disp, context); if (rgbactx) glXDestroyContext(gw->disp, rgbactx); + free(_evas_gl_x11_vi); + free(_evas_gl_x11_rgba_vi); _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; } else if (!gw->glxwin) { @@ -581,26 +524,15 @@ eng_window_make_current(void *data, void *doit) #else if (doit) { - if (gw->glxwin) + if (!__glXMakeContextCurrent(gw->disp, gw->glxwin, gw->context)) { - if (!glXMakeContextCurrent(gw->disp, gw->glxwin, gw->glxwin, gw->context)) - { - ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->glxwin, (void *)gw->context); - return EINA_FALSE; - } - } - else - { - if (!glXMakeCurrent(gw->disp, gw->win, gw->context)) - { - ERR("glXMakeCurrent(%p, 0x%x, %p) failed", gw->disp, (unsigned int)gw->win, (void *)gw->context); - return EINA_FALSE; - } + ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->win, (void *)gw->context); + return EINA_FALSE; } } else { - if (!glXMakeCurrent(gw->disp, None, NULL)) + if (!__glXMakeContextCurrent(gw->disp, 0, NULL)) return EINA_FALSE; } #endif @@ -664,20 +596,9 @@ eng_window_use(Outbuf *gw) } // GLX #else - if (gw->glxwin) + if (!__glXMakeContextCurrent(gw->disp, gw->glxwin, gw->context)) { - if (!glXMakeContextCurrent(gw->disp, gw->glxwin, gw->glxwin, - gw->context)) - { - ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->glxwin, (void *)gw->context); - } - } - else - { - if (!glXMakeCurrent(gw->disp, gw->win, gw->context)) - { - ERR("glXMakeCurrent(%p, 0x%x, %p) failed", gw->disp, (unsigned int)gw->win, (void *)gw->context); - } + ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->win, (void *)gw->context); } #endif } @@ -690,8 +611,7 @@ eng_window_unsurf(Outbuf *gw) { if (!gw->surf) return; if (!getenv("EVAS_GL_WIN_RESURF")) return; - if (getenv("EVAS_GL_INFO")) - printf("unsurf %p\n", gw); + if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", gw); #ifdef GL_GLES Outbuf *xwin; @@ -712,12 +632,9 @@ eng_window_unsurf(Outbuf *gw) } #else if (gw->glxwin) - { - glXDestroyWindow(gw->disp, gw->glxwin); - gw->glxwin = 0; - } - else { + glXDestroyWindow(gw->disp, gw->glxwin); + gw->glxwin = 0; } #endif gw->surf = 0; @@ -727,8 +644,7 @@ void eng_window_resurf(Outbuf *gw) { if (gw->surf) return; - if (getenv("EVAS_GL_INFO")) - printf("resurf %p\n", gw); + if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", gw); #ifdef GL_GLES gw->egl_surface[0] = eglCreateWindowSurface(gw->egl_disp, gw->egl_config, (EGLNativeWindowType)gw->win, @@ -747,23 +663,15 @@ eng_window_resurf(Outbuf *gw) ERR("eglMakeCurrent() failed!"); } #else -#ifdef NEWGL if (gw->alpha) gw->glxwin = glXCreateWindow(gw->disp, rgba_fbconf, gw->win, NULL); else gw->glxwin = glXCreateWindow(gw->disp, fbconf, gw->win, NULL); - if (!glXMakeContextCurrent(gw->disp, gw->glxwin, gw->glxwin, - gw->context)) - { - ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->glxwin, (void *)gw->context); - } -#else - if (!glXMakeCurrent(gw->disp, gw->win, gw->context)) + if (!__glXMakeContextCurrent(gw->disp, gw->glxwin, gw->context)) { - ERR("glXMakeCurrent(%p, 0x%x, %p) failed", (void *)gw->disp, (unsigned int)gw->win, (void *)gw->context); + ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->win, (void *)gw->context); } #endif -#endif gw->surf = 1; } @@ -775,52 +683,159 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo) if (!_evas_gl_x11_vi) { int alpha; - // EGL / GLES #ifdef GL_GLES + EGLDisplay *egl_disp; + EGLConfig configs[200]; + int major_version, minor_version; + + egl_disp = eglGetDisplay((EGLNativeDisplayType)(einfo->info.display)); + if (!egl_disp) return NULL; + if (!eglInitialize(egl_disp, &major_version, &minor_version)) return NULL; + 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); + + n = 0; + config_attrs[n++] = EGL_SURFACE_TYPE; + config_attrs[n++] = EGL_WINDOW_BIT; + config_attrs[n++] = EGL_RENDERABLE_TYPE; + config_attrs[n++] = 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 +# endif if (alpha) { + config_attrs[n++] = EGL_ALPHA_SIZE; + config_attrs[n++] = 1; + } + else + { + config_attrs[n++] = EGL_ALPHA_SIZE; + config_attrs[n++] = 0; + } + config_attrs[n++] = EGL_DEPTH_SIZE; + config_attrs[n++] = 0; + config_attrs[n++] = EGL_STENCIL_SIZE; + config_attrs[n++] = 0; + config_attrs[n++] = EGL_NONE; + num = 0; + if ((!eglChooseConfig(egl_disp, config_attrs, configs, 200, &num)) + || (num < 1)) + { + ERR("eglChooseConfig() can't find any configs"); + return NULL; + } + found = EINA_FALSE; + for (i = 0; (i < num) && (!found); i++) + { + EGLint val = 0; + VisualID visid = 0; XVisualInfo *xvi, vi_in; - int nvi, i; - XRenderPictFormat *fmt; + 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.depth = 32; - vi_in.class = TrueColor; + vi_in.visualid = visid; xvi = XGetVisualInfo(einfo->info.display, - VisualScreenMask | VisualDepthMask | - VisualClassMask, + VisualScreenMask | + VisualIDMask, &vi_in, &nvi); - if (xvi) + for (j = 0; j < nvi; j++) { - for (i = 0; i < nvi; i++) + 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 { - fmt = XRenderFindVisualFormat(einfo->info.display, - xvi[i].visual); - if ((fmt->type == PictTypeDirect) && - (fmt->direct.alphaMask)) + XRenderPictFormat *fmt; + + fmt = XRenderFindVisualFormat + (einfo->info.display, xvi[j].visual); + if ((fmt->direct.alphaMask > 0) && + (fmt->type == PictTypeDirect)) { - _evas_gl_x11_rgba_vi = - calloc(1, sizeof(XVisualInfo)); + _evas_gl_x11_rgba_vi = malloc(sizeof(XVisualInfo)); if (_evas_gl_x11_rgba_vi) - memcpy(_evas_gl_x11_rgba_vi, - &(xvi[i]), sizeof(XVisualInfo)); + memcpy(_evas_gl_x11_rgba_vi, &(xvi[j]), sizeof(XVisualInfo)); + rgba_fbconf = configs[i]; + found = EINA_TRUE; break; } } - XFree (xvi); } + if (xvi) XFree(xvi); } - else + if (!found) { - _evas_gl_x11_vi = calloc(1, sizeof(XVisualInfo)); - XMatchVisualInfo(einfo->info.display, - einfo->info.screen, depth, TrueColor, - _evas_gl_x11_vi); + // 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 + { + XVisualInfo *xvi, vi_in; + int nvi, i; + 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) + { + for (i = 0; i < nvi; i++) + { + fmt = XRenderFindVisualFormat(einfo->info.display, + xvi[i].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[i]), sizeof(XVisualInfo)); + break; + } + } + XFree(xvi); + } + } } } // GLX @@ -882,6 +897,11 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo) visinfo = glXGetVisualFromFBConfig(einfo->info.display, configs[i]); if (!visinfo) continue; + if (visinfo->visual->class != TrueColor) + { + XFree(visinfo); + continue; + } if (!alpha) { config = configs[i]; @@ -890,8 +910,8 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo) visinfo->depth) { _evas_gl_x11_vi = malloc(sizeof(XVisualInfo)); - memcpy(_evas_gl_x11_vi, visinfo, - sizeof(XVisualInfo)); + if (_evas_gl_x11_vi) + memcpy(_evas_gl_x11_vi, visinfo, sizeof(XVisualInfo)); fbconf = config; XFree(visinfo); break; @@ -906,12 +926,15 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo) XFree(visinfo); continue; } - if (format->direct.alphaMask > 0) + if ((format->direct.alphaMask > 0) && + (format->type == PictTypeDirect)) { config = configs[i]; _evas_gl_x11_rgba_vi = malloc(sizeof(XVisualInfo)); - memcpy(_evas_gl_x11_rgba_vi, visinfo, 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; } @@ -924,14 +947,7 @@ eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo) if (!_evas_gl_x11_vi) return NULL; if (einfo->info.destination_alpha) { -// EGL / GLES -#ifdef GL_GLES - if (_evas_gl_x11_rgba_vi) return _evas_gl_x11_rgba_vi->visual; -#else -//# ifdef NEWGL if (_evas_gl_x11_rgba_vi) return _evas_gl_x11_rgba_vi->visual; -//# endif -#endif } return _evas_gl_x11_vi->visual; } @@ -943,7 +959,7 @@ eng_best_colormap_get(Evas_Engine_Info_GL_X11 *einfo) 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) + if ((einfo->info.destination_alpha) && (_evas_gl_x11_rgba_vi)) { if (!_evas_gl_x11_rgba_cmap) _evas_gl_x11_rgba_cmap = @@ -1046,24 +1062,11 @@ eng_gl_context_use(Context_3D *ctx) ERR("eglMakeCurrent() failed."); } #else - if (ctx->glxwin) + if (!__glXMakeContextCurrent(ctx->display, ctx->glxwin, ctx->context)) { - if (!glXMakeContextCurrent(ctx->display, ctx->glxwin, - ctx->glxwin, ctx->context)) - { - ERR("glXMakeContextCurrent(%p, %p, %p, %p) faild.", - (void *)ctx->display, (void *)ctx->glxwin, - (void *)ctx->glxwin, (void *)ctx->context); - } - } - else - { - if (!glXMakeCurrent(ctx->display, ctx->win, ctx->context)) - { - ERR("glXMakeCurrent(%p, %p, %p) failed.", - (void *)ctx->display, (void *)ctx->win, - (void *)ctx->context); - } + ERR("glXMakeContextCurrent(%p, %p, %p, %p) faild.", + (void *)ctx->display, (void *)ctx->glxwin, + (void *)ctx->win, (void *)ctx->context); } #endif } @@ -1093,26 +1096,15 @@ eng_outbuf_swap_mode(Outbuf *ob) #ifdef GL_GLES EGLint age = 0; - if (!eglQuerySurface(ob->egl_disp, - ob->egl_surface[0], + if (!eglQuerySurface(ob->egl_disp, ob->egl_surface[0], EGL_BUFFER_AGE_EXT, &age)) age = 0; #else unsigned int age = 0; if (glsym_glXQueryDrawable) - { - if (ob->glxwin) - glsym_glXQueryDrawable(ob->disp, - ob->glxwin, - GLX_BACK_BUFFER_AGE_EXT, - &age); - else - glsym_glXQueryDrawable(ob->disp, - ob->win, - GLX_BACK_BUFFER_AGE_EXT, - &age); - } + glsym_glXQueryDrawable(ob->disp, ob->glxwin, + GLX_BACK_BUFFER_AGE_EXT, &age); #endif if (age == 1) swap_mode = MODE_COPY; else if (age == 2) swap_mode = MODE_DOUBLE; @@ -1135,7 +1127,7 @@ eng_outbuf_region_first_rect(Outbuf *ob) glsym_evas_gl_preload_render_lock(eng_preload_make_current, ob); #ifdef GL_GLES - // dont need to for egl - eng_window_use() can check for other ctxt's + // dont need to for egl - eng_window_use() can check for other ctxt's #else eng_window_use(NULL); #endif @@ -1346,7 +1338,7 @@ eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode) } // XXX: if partial swaps can be done use re->rects // measure(0, "swap"); - glXSwapBuffers(ob->disp, ob->win); + glXSwapBuffers(ob->disp, ob->glxwin); // measure(1, "swap"); if (ob->info->callback.post_swap) { -- 2.7.4