find the visuals to use, and the fbconfig we want to use for all available depths
authorDana Jansens <danakj@orodu.net>
Mon, 10 Mar 2008 04:00:02 +0000 (00:00 -0400)
committerDana Jansens <danakj@orodu.net>
Mon, 10 Mar 2008 04:00:02 +0000 (00:00 -0400)
glxrender.c

index d9fdf69..1a4a8da 100644 (file)
@@ -15,6 +15,8 @@
 #include <GL/glxtokens.h>
 #include <GL/gl.h>
 
+#define MAX_DEPTH 32
+
 static int plugin_id;
 
 typedef struct {
@@ -29,6 +31,8 @@ typedef struct {
     int xshadowoff;
     int yshadowoff;
 
+    uint32_t fbconfig[MAX_DEPTH + 1];
+
     xcb_glx_context_t context;
     xcb_glx_context_tag_t context_tag;
 } data_t;
@@ -38,7 +42,10 @@ typedef struct {
     xcb_glx_pixmap_t glpixmap;
 } window_data_t;
 
+static uint32_t glxrender_visual_info(uint32_t *props, int vis, int numprops,
+                                      uint32_t name);
 static gboolean glxrender_check_visual(d_screen_t *sc);
+static gboolean glxrender_find_fb_config(d_screen_t *sc, data_t *d);
 
 static void glxrender_paint(d_screen_t *sc);
 static void glxrender_root_pixmap_change(d_screen_t *sc);
@@ -93,6 +100,11 @@ glxrender_init(d_screen_t *sc, int id)
         exit(1);
     }
 
+    if (!(glxrender_find_fb_config(sc, d))) {
+        printf("unable to find FB configs\n");
+        exit(1);
+    }
+
     d->context = xcb_generate_id(sc->dpy->conn);
     ck = xcb_glx_create_context_checked(sc->dpy->conn, d->context,
                                         sc->overlay_visual, sc->num,
@@ -136,6 +148,35 @@ glxrender_init(d_screen_t *sc, int id)
 */
 }
 
+static uint32_t
+glxrender_visual_info(uint32_t *props, int vis, int numprops, uint32_t name)
+{
+    int s;
+
+    assert(numprops > 14);
+
+    /*
+    for (s = vis * numprops; s < vis*numprops + numprops; ++s)
+        printf("%x ", props[s]);
+    printf("\n");
+    */
+
+    s = vis * numprops;
+    switch (name) {
+    case GLX_VISUAL_ID:     return props[s+0];  /* id number */
+    case GLX_X_VISUAL_TYPE: return props[s+1];  /* XCB_CLASS_TRUE_COLOR etc */
+    case GLX_USE_GL:        return props[s+2];  /* boolean */
+    case GLX_RED_SIZE:      return props[s+3];  /* number */
+    case GLX_GREEN_SIZE:    return props[s+4];  /* number */
+    case GLX_BLUE_SIZE:     return props[s+5];  /* number */
+    case GLX_ALPHA_SIZE:    return props[s+6];  /* number */
+    case GLX_DOUBLEBUFFER:  return props[s+11]; /* boolean */
+    case GLX_DEPTH_SIZE:    return props[s+14]; /* number */
+    case GLX_STENCIL_SIZE:  return props[s+15]; /* number */
+    default: assert(0);
+    }
+}
+
 static gboolean
 glxrender_check_visual(d_screen_t *sc)
 {
@@ -146,10 +187,8 @@ glxrender_check_visual(d_screen_t *sc)
     ck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
     rep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, ck, NULL);
     if (rep) {
-        uint32_t *list;
-        unsigned int i, j;
-        int len;
-        gboolean depth, doublebuffer, rgba;
+        uint32_t *props;
+        unsigned int i, nprops;
 
 /*
         static int config[] = {
@@ -160,49 +199,23 @@ glxrender_check_visual(d_screen_t *sc)
         };
 */
 
-        list = xcb_glx_get_visual_configs_property_list(rep);
-        len = xcb_glx_get_visual_configs_property_list_length(rep);
-        printf("got %d %d, %d\n", rep->num_visuals, rep->num_properties, len);
+        props = xcb_glx_get_visual_configs_property_list(rep);
+        nprops = rep->num_properties;
 
         for (i = 0; i < rep->num_visuals; ++i) {
-            const int
-                ID = 0,
-                CLASS = 1,
-                USE_GL = 2,
-                RED_DEPTH = 3,
-                BLUE_DEPTH = 4,
-                GREEN_DEPTH = 5,
-                ALPHA_DEPTH = 6,
-                DOUBLE_BUFFER = 11,
-                DEPTH_SIZE = 14;
-            int s = i * rep->num_properties;
-
-            depth = doublebuffer = rgba = FALSE;
-
             /* look for the overlay's visual */
-            if (list[s+ID] != sc->overlay_visual) continue;
-
-            printf("0x%x ", list[s+ID]);
-            printf("%d ", list[s+CLASS]);
-            printf("%s ", list[s+USE_GL] ? "yes" : "no");
-            printf("%d ", list[s+RED_DEPTH]);
-            printf("%d ", list[s+GREEN_DEPTH]);
-            printf("%d ", list[s+BLUE_DEPTH]);
-            printf("%d ", list[s+ALPHA_DEPTH]);
-            printf("%s ", list[s+DOUBLE_BUFFER] ? "yes" : "no");
-            printf("%d ", list[s+DEPTH_SIZE]);
-
-            printf("\n");
-            for (j = 0; j < rep->num_properties; ++j)
-                printf("%d ", list[i*rep->num_properties+j]);
-            printf("\n");
-
-            if (!list[s+USE_GL]) {
+            if (glxrender_visual_info(props, i, nprops, GLX_VISUAL_ID) !=
+                sc->overlay_visual)
+            {
+                continue;
+            }
+
+            if (!glxrender_visual_info(props, i, nprops, GLX_USE_GL)) {
                 printf("overlay visual does not support GL\n");
                 break;
             }
 
-            if (!list[s+DOUBLE_BUFFER]) {
+            if (!glxrender_visual_info(props, i, nprops, GLX_DOUBLEBUFFER)) {
                 printf("overlay visual is not double buffered\n");
                 break;
             }
@@ -215,6 +228,165 @@ glxrender_check_visual(d_screen_t *sc)
     return ok;
 }
 
+static uint32_t
+glxrender_fbconfig_info(uint32_t *props, int con, int numprops, uint32_t name)
+{
+    int i;
+
+    for (i = 0; i < numprops; ++i) {
+        if (props[i*2 + con*numprops*2] == name)
+            return props[i*2 + con*numprops*2 + 1];
+    }
+    return 0;
+}
+
+static gboolean
+glxrender_find_fb_config(d_screen_t *sc, data_t *d)
+{
+    xcb_glx_get_visual_configs_cookie_t vck;
+    xcb_glx_get_visual_configs_reply_t *vrep;
+    xcb_glx_get_fb_configs_cookie_t fbck;
+    xcb_glx_get_fb_configs_reply_t *fbrep;
+    xcb_depth_iterator_t depth_it;
+    uint32_t fbcon = FALSE;
+    unsigned int i, nvprops, nfbprops;
+    uint32_t *vprops, *fbprops;
+    uint32_t db, stencil, depthsize;
+
+    vck = xcb_glx_get_visual_configs_unchecked(sc->dpy->conn, sc->num);
+    vrep = xcb_glx_get_visual_configs_reply(sc->dpy->conn, vck, NULL);
+    if (!vrep) return FALSE;
+
+    fbck = xcb_glx_get_fb_configs(sc->dpy->conn, sc->num);
+    fbrep = xcb_glx_get_fb_configs_reply(sc->dpy->conn, fbck, NULL);
+    if (!fbrep) return FALSE;
+
+    vprops = xcb_glx_get_visual_configs_property_list(vrep);
+    nvprops = vrep->num_properties;
+    fbprops = xcb_glx_get_fb_configs_property_list(fbrep);
+    nfbprops = fbrep->num_properties;
+
+    for (i = 0; i <= MAX_DEPTH; ++i)
+        d->fbconfig[i] = 0;
+
+    db = 32767;
+    stencil = 32767;
+    depthsize = 32767;
+    depth_it = xcb_screen_allowed_depths_iterator(&sc->super);
+    for (; depth_it.rem; xcb_depth_next(&depth_it)) {
+        uint32_t vid;
+        int j;
+        unsigned int k;
+        xcb_visualtype_t *visuals;
+        int nvisuals;
+
+        vid = 0;
+        if (depth_it.data->depth > MAX_DEPTH) continue;
+
+        visuals = xcb_depth_visuals(depth_it.data);
+        nvisuals = xcb_depth_visuals_length(depth_it.data);
+
+        /* pick the nicest visual for the depth */
+        for (j = 0; j < nvisuals; ++j) {
+            uint32_t val;
+
+            /* find the visual's properties */
+            for (k = 0; k < vrep->num_visuals; ++k)
+                if (glxrender_visual_info(vprops, k, nvprops, GLX_VISUAL_ID)
+                    == visuals[j].visual_id)
+                {
+                    break;
+                }
+            if (k == vrep->num_visuals) continue;
+
+            val = glxrender_visual_info(vprops, k, nvprops, GLX_USE_GL);
+            if (!val) continue;
+
+            val = glxrender_visual_info(vprops, k, nvprops, GLX_DOUBLEBUFFER);
+            if (!val > db) continue;
+            db = val;
+
+            val = glxrender_visual_info(vprops, k, nvprops, GLX_STENCIL_SIZE);
+            if (!val > stencil) continue;
+            stencil = val;
+
+            val = glxrender_visual_info(vprops, k, nvprops, GLX_DEPTH_SIZE);
+            if (!val > depthsize) continue;
+            depthsize = val;
+
+            /* use this visual */
+            vid = visuals[j].visual_id;
+        }
+
+        if (!vid) continue;
+
+        printf("found visual for depth %d\n", i);
+
+        for (k = 0; k < fbrep->num_FB_configs; ++k) {
+            uint32_t val;
+
+            printf("root visual 0x%x\n", sc->super.root_visual);
+            printf("overlay visual 0x%x\n", sc->overlay_visual);
+
+            val = glxrender_fbconfig_info(fbprops, k, nfbprops,
+                                          GLX_VISUAL_ID);
+            printf("x visual 0x%x\n", val);
+            if (val != vid) continue;
+
+            val = glxrender_fbconfig_info(fbprops, k, nfbprops,
+                                          GLX_DOUBLEBUFFER);
+            printf("dbl buffer %s\n", val ? "yes" : "no");
+            if (db) continue;
+
+            val = glxrender_fbconfig_info(fbprops, k, nfbprops,
+                                          GLX_DEPTH_SIZE);
+            printf("depth size %d\n", val);
+
+            val = glxrender_fbconfig_info(fbprops, k, nfbprops,
+                                          GLX_RED_SIZE);
+            printf("red size %d\n", val);
+            if (!val) continue;
+
+            val = glxrender_fbconfig_info(fbprops, k, nfbprops,
+                                          GLX_GREEN_SIZE);
+            printf("green size %d\n", val);
+            if (!val) continue;
+
+            val = glxrender_fbconfig_info(fbprops, k, nfbprops,
+                                          GLX_BLUE_SIZE);
+            printf("blue size %d\n", val);
+            if (!val) continue;
+
+            val = glxrender_fbconfig_info(fbprops, k, nfbprops,
+                                          GLX_ALPHA_SIZE);
+            printf("alpha size %d\n", val);
+            if (!val) continue;
+
+            val = glxrender_fbconfig_info(fbprops, j, nfbprops,
+                                          GLX_RENDER_TYPE);
+            printf("rgba bit %s\n", val & GLX_RGBA_BIT ? "yes" : "no");
+            if (!(val & GLX_RGBA_BIT)) continue;
+
+            val = glxrender_fbconfig_info(fbprops, j, nfbprops,
+                                          GLX_CONFIG_CAVEAT);
+            printf("caveat 0x%x\n", val);
+
+            val = glxrender_fbconfig_info(fbprops, j, nfbprops,
+                                          GLX_BIND_TO_TEXTURE_RGBA_EXT);
+            printf("bind ext %s\n", val ? "yes" : "no");
+            if (!val) continue;
+
+            d->fbconfig[depth_it.data->depth] =
+                glxrender_fbconfig_info(fbprops, i, nfbprops, GLX_FBCONFIG_ID);
+            break;
+        }
+    }
+
+    free(vrep);
+    free(fbrep);
+    return TRUE;
+}
+
 void
 glxrender_free(d_screen_t *sc)
 {