egl_dri2: Initialize config attributes with visual id and class from X
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 10 Feb 2010 01:49:40 +0000 (20:49 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 10 Feb 2010 02:24:15 +0000 (21:24 -0500)
src/egl/drivers/dri2/egl_dri2.c

index a1a89e9a1773d300293812847be382dcdc0cc50c..08e7e0106e8f50caa27fe0b1436999ab9007aee6 100644 (file)
@@ -87,7 +87,6 @@ struct dri2_egl_surface
    __DRIbuffer          buffers[5];
    int                  buffer_count;
    xcb_xfixes_region_t  region;
-   int                  have_back;
    int                  have_fake_front;
    int                  swap_interval;
 };
@@ -153,7 +152,8 @@ EGLint dri2_to_egl_attribute_map[] = {
 };
 
 static void
-dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id)
+dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
+               int depth, xcb_visualtype_t *visual)
 {
    struct dri2_egl_config *conf;
    struct dri2_egl_display *dri2_dpy;
@@ -215,21 +215,39 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id)
       }
    }
 
-   /* EGL_SWAP_BEHAVIOR_PRESERVED_BIT */
+   /* In EGL, double buffer or not isn't a config attribute.  Pixmaps
+    * surfaces are always single buffered, pbuffer surfaces are always
+    * back buffers and windows can be either, selected by passing an
+    * attribute at window surface construction time.  To support this
+    * we ignore all double buffer configs and manipulate the buffer we
+    * return in the getBuffer callback to get the behaviour we want. */
 
-   /* FIXME: Figure out how to get the visual ID and types */
    if (double_buffer) {
+      free(conf);
+      return;
+   }
+
+   /* EGL_SWAP_BEHAVIOR_PRESERVED_BIT */
+
+   if (visual != NULL) {
+      if (depth != _eglGetConfigKey(&conf->base, EGL_BUFFER_SIZE)) {
+        free(conf);
+        return;
+      }
+
       _eglSetConfigKey(&conf->base, EGL_SURFACE_TYPE,
                       EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT);
-      _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_ID, 0x21);
-      _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_TYPE,
-                      XCB_VISUAL_CLASS_TRUE_COLOR);
+      _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_ID, visual->visual_id);
+      _eglSetConfigKey(&conf->base, EGL_NATIVE_VISUAL_TYPE, visual->_class);
    } else {
       _eglSetConfigKey(&conf->base, EGL_SURFACE_TYPE,
                       EGL_PIXMAP_BIT | EGL_PBUFFER_BIT);
    }
+
    _eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGB, bind_to_texture_rgb);
-   _eglSetConfigKey(&conf->base, EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba);
+   if (_eglGetConfigKey(&conf->base, EGL_ALPHA_SIZE) > 0)
+      _eglSetConfigKey(&conf->base,
+                      EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba);
 
    /* EGL_OPENGL_ES_BIT, EGL_OPENVG_BIT, EGL_OPENGL_ES2_BIT */
    _eglSetConfigKey(&conf->base, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT);
@@ -261,7 +279,6 @@ dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
 
    dri2_surf->buffer_count = count;
    dri2_surf->have_fake_front = 0;
-   dri2_surf->have_back = 0;
 
    /* This assumes the DRI2 buffer attachment tokens matches the
     * __DRIbuffer tokens. */
@@ -271,10 +288,14 @@ dri2_process_buffers(struct dri2_egl_surface *dri2_surf,
       dri2_surf->buffers[i].pitch = buffers[i].pitch;
       dri2_surf->buffers[i].cpp = buffers[i].cpp;
       dri2_surf->buffers[i].flags = buffers[i].flags;
+
+      /* We only use the DRI drivers single buffer configs.  This
+       * means that if we try to render to a window, DRI2 will give us
+       * the fake front buffer, which we'll use as a back buffer.
+       * Note that EGL doesn't require that several clients rendering
+       * to the same window must see the same aux buffers. */
       if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
          dri2_surf->have_fake_front = 1;
-      if (dri2_surf->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
-         dri2_surf->have_back = 1;
    }
 
    if (dri2_surf->region != XCB_NONE)
@@ -448,7 +469,9 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
    xcb_generic_error_t *error;
    drm_magic_t magic;
    xcb_screen_iterator_t s;
-   int i;
+   xcb_depth_iterator_t d;
+   xcb_visualtype_t *visuals;
+   int i, j, id;
 
    dri2_dpy = malloc(sizeof *dri2_dpy);
    if (!dri2_dpy)
@@ -608,8 +631,27 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
    if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
       goto cleanup_dri_screen;
 
-   for (i = 0; driver_configs[i]; i++)
-      dri2_add_config(disp, driver_configs[i], i + 1);
+   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
+   d = xcb_screen_allowed_depths_iterator(s.data);
+   id = 1;
+   while (d.rem > 0) {
+      EGLBoolean class_added[6] = { 0, };
+
+      visuals = xcb_depth_visuals(d.data);
+      for (i = 0; i < xcb_depth_visuals_length(d.data); i++) {
+        if (class_added[visuals[i]._class])
+           continue;
+
+        class_added[visuals[i]._class] = EGL_TRUE;
+        for (j = 0; driver_configs[j]; j++)
+           dri2_add_config(disp, driver_configs[j],
+                           id++, d.data->depth, &visuals[i]);
+
+      }
+
+      xcb_depth_next(&d);      
+   }
+
    if (!disp->NumConfigs) {
       _eglLog(_EGL_WARNING, "DRI2: failed to create any config");
       goto cleanup_configs;
@@ -885,14 +927,14 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 #endif
 #endif
 
-   if (!dri2_surf->have_back)
+   if (!dri2_surf->have_fake_front)
       return EGL_TRUE;
 
    cookie = xcb_dri2_copy_region_unchecked(dri2_dpy->conn,
                                           dri2_surf->drawable,
                                           dri2_surf->region,
                                           XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
-                                          XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT);
+                                          XCB_DRI2_ATTACHMENT_BUFFER_FAKE_FRONT_LEFT);
    free(xcb_dri2_copy_region_reply(dri2_dpy->conn, cookie, NULL));
 
    return EGL_TRUE;