From e6ca2d891a2c48c91db45a0c2f5ce84d5e6621e1 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 1 Dec 2009 16:18:39 +0000 Subject: [PATCH] glx: Always request an ARGB visual When requesting the GLXFBConfig for creating the GLX context, we should always request one that links to an ARGB visual instead of a plain RGB one. By using an ARGB visual we allow the ClutterStage:use-alpha property to work as intended when running Clutter under a compositing manager. The default behaviour of requesting an ARGB visual can be disabled by using the: CLUTTER_DISABLE_ARGB_VISUAL Environment variable. --- clutter/glx/clutter-backend-glx.c | 128 ++++++++++++++++++++++++------ clutter/glx/clutter-backend-glx.h | 5 +- clutter/glx/clutter-glx.h | 5 -- clutter/glx/clutter-stage-glx.c | 13 +-- clutter/x11/clutter-backend-x11.c | 15 +++- clutter/x11/clutter-x11.h | 2 + 6 files changed, 125 insertions(+), 43 deletions(-) diff --git a/clutter/glx/clutter-backend-glx.c b/clutter/glx/clutter-backend-glx.c index 8870037b3..ce1256e6c 100644 --- a/clutter/glx/clutter-backend-glx.c +++ b/clutter/glx/clutter-backend-glx.c @@ -56,7 +56,7 @@ G_DEFINE_TYPE (ClutterBackendGLX, clutter_backend_glx, CLUTTER_TYPE_BACKEND_X11) /* singleton object */ static ClutterBackendGLX *backend_singleton = NULL; -static gchar *clutter_vblank_name = NULL; +static gchar *clutter_vblank_name = NULL; #ifdef __linux__ #define DRM_VBLANK_RELATIVE 0x1; @@ -354,6 +354,20 @@ clutter_backend_glx_get_features (ClutterBackend *backend) return flags; } +enum +{ + DRAWABLE_TYPE = 0, + RENDER_TYPE = 2, + DOUBLE_BUFFER = 4, + RED_SIZE = 6, + GREEN_SIZE = 8, + BLUE_SIZE = 10, + ALPHA_SIZE = 12, + DEPTH_SIZE = 14, + STENCIL_SIZE = 16, + TRANSPARENT_TYPE = 18 +}; + /* It seems the GLX spec never defined an invalid GLXFBConfig that * we could overload as an indication of error, so we have to return * an explicit boolean status. */ @@ -362,30 +376,43 @@ _clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_glx, GLXFBConfig *config) { ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx); - int attributes[] = { - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DOUBLEBUFFER, GL_TRUE, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_ALPHA_SIZE, 1, - GLX_DEPTH_SIZE, 1, - GLX_STENCIL_SIZE, 1, + GLXFBConfig *configs = NULL; + gboolean retval = FALSE; + gboolean use_argb = clutter_x11_has_argb_visuals (); + int n_configs, i; + static int attributes[] = { + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_DOUBLEBUFFER, GL_TRUE, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_ALPHA_SIZE, 1, + GLX_DEPTH_SIZE, 1, + GLX_STENCIL_SIZE, 1, + GLX_TRANSPARENT_TYPE, GLX_NONE, None }; - GLXFBConfig *configs = NULL; - int n_configs; if (backend_x11->xdpy == None || backend_x11->xscreen == None) return FALSE; - if (backend_glx->found_fbconfig) + if (backend_glx->found_fbconfig > 0) { - *config = backend_glx->fbconfig; + if (use_argb && backend_glx->found_fbconfig == 2) + *config = backend_glx->fbconfig_rgba; + else + *config = backend_glx->fbconfig_rgb; + return TRUE; } + if (use_argb) + { + attributes[ALPHA_SIZE] = 8; + attributes[TRANSPARENT_TYPE] = GLX_TRANSPARENT_RGB; + } + CLUTTER_NOTE (BACKEND, "Retrieving GL fbconfig, dpy: %p, xscreen; %p (%d)", backend_x11->xdpy, @@ -396,16 +423,64 @@ _clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_glx, backend_x11->xscreen_num, attributes, &n_configs); - if (configs) + if (!configs) + return FALSE; + + if (!use_argb) { *config = configs[0]; - backend_glx->found_fbconfig = TRUE; - backend_glx->fbconfig = configs[0]; - XFree (configs); - return TRUE; + + backend_glx->found_fbconfig = 1; + backend_glx->fbconfig_rgb = configs[0]; + + retval = TRUE; + + goto out; } - else - return FALSE; + + for (i = 0; i < n_configs; i++) + { + XVisualInfo *vinfo; + + vinfo = glXGetVisualFromFBConfig (backend_x11->xdpy, configs[i]); + if (vinfo == None) + continue; + + if (vinfo->depth == 32 && + (vinfo->red_mask == 0xff0000 && + vinfo->green_mask == 0x00ff00 && + vinfo->blue_mask == 0x0000ff)) + { + CLUTTER_NOTE (BACKEND, "Found GLX visual ARGB [index:%d]", i); + + *config = configs[i]; + + backend_glx->found_fbconfig = 2; + backend_glx->fbconfig_rgba = configs[i]; + + retval = TRUE; + + goto out; + } + } + + /* XXX - we might add a warning here */ + if (use_argb && !backend_glx->found_fbconfig != 2) + { + CLUTTER_NOTE (BACKEND, "ARGB visual requested, but none found"); + + *config = configs[0]; + + backend_glx->found_fbconfig = 1; + backend_glx->fbconfig_rgb = configs[0]; + + retval = TRUE; + } + +out: + XFree (configs); + + return retval; } static XVisualInfo * @@ -436,12 +511,14 @@ clutter_backend_glx_create_context (ClutterBackend *backend, { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, - "Unable to find suitable fbconfig for GL context"); + "Unable to find a suitable GLXFBConfig for " + "the GLX context"); return FALSE; } - CLUTTER_NOTE (GL, "Creating GL Context (display: %p)", + CLUTTER_NOTE (GL, "Creating GLX Context (display: %p)", backend_x11->xdpy); + backend_glx->gl_context = glXCreateNewContext (backend_x11->xdpy, config, @@ -460,7 +537,8 @@ clutter_backend_glx_create_context (ClutterBackend *backend, is_direct = glXIsDirect (backend_x11->xdpy, backend_glx->gl_context); - CLUTTER_NOTE (GL, "Setting %s context", + CLUTTER_NOTE (GL, + "Setting %s context", is_direct ? "direct" : "indirect"); _cogl_set_indirect_context (!is_direct); } diff --git a/clutter/glx/clutter-backend-glx.h b/clutter/glx/clutter-backend-glx.h index 2bd380813..e7d6d9836 100644 --- a/clutter/glx/clutter-backend-glx.h +++ b/clutter/glx/clutter-backend-glx.h @@ -63,8 +63,9 @@ struct _ClutterBackendGLX ClutterBackendX11 parent_instance; /* Single context for all wins */ - gboolean found_fbconfig; - GLXFBConfig fbconfig; + gint found_fbconfig; + GLXFBConfig fbconfig_rgb; + GLXFBConfig fbconfig_rgba; GLXContext gl_context; /* Vblank stuff */ diff --git a/clutter/glx/clutter-glx.h b/clutter/glx/clutter-glx.h index bb2455b8a..967cfec90 100644 --- a/clutter/glx/clutter-glx.h +++ b/clutter/glx/clutter-glx.h @@ -43,9 +43,4 @@ #include #include -G_BEGIN_DECLS - - -G_END_DECLS - #endif /* __CLUTTER_GLX_H__ */ diff --git a/clutter/glx/clutter-stage-glx.c b/clutter/glx/clutter-stage-glx.c index 9c1105b2e..f770c88d3 100644 --- a/clutter/glx/clutter-stage-glx.c +++ b/clutter/glx/clutter-stage-glx.c @@ -105,18 +105,11 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window) { XSetWindowAttributes xattr; unsigned long mask; - GLXFBConfig config; XVisualInfo *xvisinfo; CLUTTER_NOTE (MISC, "Creating stage X window"); - if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config)) - { - g_critical ("Unable to find suitable FBConfig to realize stage."); - return FALSE; - } - - xvisinfo = glXGetVisualFromFBConfig (backend_x11->xdpy, config); + xvisinfo = clutter_backend_x11_get_visual_info (backend_x11); if (xvisinfo == NULL) { g_critical ("Unable to find suitable GL visual."); @@ -145,9 +138,9 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window) XFree (xvisinfo); } - if (clutter_x11_has_event_retrieval()) + if (clutter_x11_has_event_retrieval ()) { - if (clutter_x11_has_xinput()) + if (clutter_x11_has_xinput ()) { XSelectInput (backend_x11->xdpy, stage_x11->xwin, StructureNotifyMask | diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c index ae6ff824c..ec9afebea 100644 --- a/clutter/x11/clutter-backend-x11.c +++ b/clutter/x11/clutter-backend-x11.c @@ -97,6 +97,7 @@ static ClutterBackendX11 *backend_singleton = NULL; /* various flags corresponding to pre init setup calls */ static gboolean _no_xevent_retrieval = FALSE; static gboolean clutter_enable_xinput = FALSE; +static gboolean clutter_enable_argb = TRUE; static Display *_foreign_dpy = NULL; /* options */ @@ -124,6 +125,13 @@ clutter_backend_x11_pre_parse (ClutterBackend *backend, env_string = NULL; } + env_string = g_getenv ("CLUTTER_DISABLE_ARGB_VISUAL"); + if (env_string) + { + clutter_enable_argb = FALSE; + env_string = NULL; + } + return TRUE; } @@ -980,6 +988,12 @@ clutter_x11_has_composite_extension (void) return have_composite; } +gboolean +clutter_x11_has_argb_visuals (void) +{ + return clutter_enable_argb; +} + XVisualInfo * clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11) { @@ -993,4 +1007,3 @@ clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11) return NULL; } - diff --git a/clutter/x11/clutter-x11.h b/clutter/x11/clutter-x11.h index 58fc7a63e..2b960578c 100644 --- a/clutter/x11/clutter-x11.h +++ b/clutter/x11/clutter-x11.h @@ -124,6 +124,8 @@ gboolean clutter_x11_has_xinput (void); gboolean clutter_x11_has_composite_extension (void); +gboolean clutter_x11_has_argb_visuals (void); + Time clutter_x11_get_current_event_time (void); G_END_DECLS