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
This commit is contained in:
Carsten Haitzler 2014-10-25 20:04:52 +09:00
parent e9e61718d1
commit 696346c467
7 changed files with 476 additions and 346 deletions

View File

@ -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);

View File

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

View File

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

View File

@ -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);

View File

@ -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__, "");

View File

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

View File

@ -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;
}
}
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
// 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")))
}
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"))
{
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"))
{
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,22 +663,14 @@ 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))
if (!__glXMakeContextCurrent(gw->disp, gw->glxwin, gw->context))
{
ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->glxwin, (void *)gw->context);
ERR("glXMakeContextCurrent(%p, %p, %p, %p)", (void *)gw->disp, (void *)gw->glxwin, (void *)gw->win, (void *)gw->context);
}
#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);
}
#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)
{
XVisualInfo *xvi, vi_in;
int nvi, i;
XRenderPictFormat *fmt;
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 =
calloc(1, sizeof(XVisualInfo));
if (_evas_gl_x11_rgba_vi)
memcpy(_evas_gl_x11_rgba_vi,
&(xvi[i]), sizeof(XVisualInfo));
break;
}
}
XFree (xvi);
}
config_attrs[n++] = EGL_ALPHA_SIZE;
config_attrs[n++] = 1;
}
else
{
_evas_gl_x11_vi = calloc(1, sizeof(XVisualInfo));
XMatchVisualInfo(einfo->info.display,
einfo->info.screen, depth, TrueColor,
_evas_gl_x11_vi);
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, 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)
{
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;
}
}
}
if (xvi) XFree(xvi);
}
if (!found)
{
// 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)
{