glx: Always request an ARGB visual
authorEmmanuele Bassi <ebassi@linux.intel.com>
Tue, 1 Dec 2009 16:18:39 +0000 (16:18 +0000)
committerEmmanuele Bassi <ebassi@linux.intel.com>
Tue, 1 Dec 2009 16:25:54 +0000 (16:25 +0000)
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
clutter/glx/clutter-backend-glx.h
clutter/glx/clutter-glx.h
clutter/glx/clutter-stage-glx.c
clutter/x11/clutter-backend-x11.c
clutter/x11/clutter-x11.h

index 8870037..ce1256e 100644 (file)
@@ -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);
     }
index 2bd3808..e7d6d98 100644 (file)
@@ -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 */
index bb2455b..967cfec 100644 (file)
@@ -43,9 +43,4 @@
 #include <clutter/clutter.h>
 #include <clutter/glx/clutter-glx-texture-pixmap.h>
 
-G_BEGIN_DECLS
-
-
-G_END_DECLS
-
 #endif /* __CLUTTER_GLX_H__ */
index 9c1105b..f770c88 100644 (file)
@@ -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 |
index ae6ff82..ec9afeb 100644 (file)
@@ -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;
 }
-
index 58fc7a6..2b96057 100644 (file)
@@ -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