egl/dri2: Move dri2_egl_display virtual funcs to vtbl
[mesa.git] / src / egl / drivers / dri2 / platform_x11.c
index 936e3806521ad8e65b5b39f58a9ca7a51c01259b..b5df0f990c8371a3eecdb28278269d42d0342b00 100644 (file)
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
+#ifdef HAVE_LIBDRM
 #include <xf86drm.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include "egl_dri2.h"
 
-/* From xmlpool/options.h, user exposed so should be stable */
-#define DRI_CONF_VBLANK_NEVER 0
-#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
-#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
-#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
-
 static void
 swrastCreateDrawable(struct dri2_egl_display * dri2_dpy,
                      struct dri2_egl_surface * dri2_surf,
@@ -284,14 +280,15 @@ dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
 
    surf = dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
                               window, attrib_list);
-
-   /* When we first create the DRI2 drawable, its swap interval on the server
-    * side is 1.
-    */
-   surf->SwapInterval = 1;
-
-   /* Override that with a driconf-set value. */
-   drv->API.SwapInterval(drv, disp, surf, dri2_dpy->default_swap_interval);
+   if (surf != NULL) {
+      /* When we first create the DRI2 drawable, its swap interval on the
+       * server side is 1.
+       */
+      surf->SwapInterval = 1;
+
+      /* Override that with a driconf-set value. */
+      drv->API.SwapInterval(drv, disp, surf, dri2_dpy->default_swap_interval);
+   }
 
    return surf;
 }
@@ -605,6 +602,7 @@ dri2_x11_authenticate(_EGLDisplay *disp, uint32_t id)
 static EGLBoolean
 dri2_authenticate(_EGLDisplay *disp)
 {
+#ifdef HAVE_LIBDRM
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    drm_magic_t magic;
 
@@ -617,7 +615,7 @@ dri2_authenticate(_EGLDisplay *disp)
       _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
       return EGL_FALSE;
    }
-
+#endif
    return EGL_TRUE;
 }
 
@@ -629,6 +627,7 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
    xcb_depth_iterator_t d;
    xcb_visualtype_t *visuals;
    int i, j, id;
+   unsigned int rgba_masks[4];
    EGLint surface_type;
    EGLint config_attrs[] = {
           EGL_NATIVE_VISUAL_ID,   0,
@@ -659,8 +658,26 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
             config_attrs[1] = visuals[i].visual_id;
             config_attrs[3] = visuals[i]._class;
 
+            rgba_masks[0] = visuals[i].red_mask;
+            rgba_masks[1] = visuals[i].green_mask;
+            rgba_masks[2] = visuals[i].blue_mask;
+            rgba_masks[3] = 0;
            dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
-                           d.data->depth, surface_type, config_attrs, NULL);
+                           surface_type, config_attrs, rgba_masks);
+
+            /* Allow a 24-bit RGB visual to match a 32-bit RGBA EGLConfig.
+             * Otherwise it will only match a 32-bit RGBA visual.  On a
+             * composited window manager on X11, this will make all of the
+             * EGLConfigs with destination alpha get blended by the
+             * compositor.  This is probably not what the application
+             * wants... especially on drivers that only have 32-bit RGBA
+             * EGLConfigs! */
+            if (d.data->depth == 24) {
+               rgba_masks[3] =
+                  ~(rgba_masks[0] | rgba_masks[1] | rgba_masks[2]);
+               dri2_add_config(disp, dri2_dpy->driver_configs[j], id++,
+                               surface_type, config_attrs, rgba_masks);
+            }
         }
       }
 
@@ -742,6 +759,20 @@ dri2_swap_buffers_msc(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
       free(reply);
    }
 
+   /* Since we aren't watching for the server's invalidate events like we're
+    * supposed to (due to XCB providing no mechanism for filtering the events
+    * the way xlib does), and SwapBuffers is a common cause of invalidate
+    * events, just shove one down to the driver, even though we haven't told
+    * the driver that we're the kind of loader that provides reliable
+    * invalidate events.  This causes the driver to request buffers again at
+    * its next draw, so that we get the correct buffers if a pageflip
+    * happened.  The driver should still be using the viewport hack to catch
+    * window resizes.
+    */
+   if (dri2_dpy->flush &&
+       dri2_dpy->flush->base.version >= 3 && dri2_dpy->flush->invalidate)
+      (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);
+
    return swap_count;
 }
 
@@ -794,7 +825,7 @@ static EGLBoolean
 dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw,
                     EGLint x, EGLint y, EGLint width, EGLint height)
 {
-   const EGLint rect[4] = { x, draw->Height - y - height, width, height };
+   const EGLint rect[4] = { x, y, width, height };
 
    if (x < 0 || y < 0 || width < 0 || height < 0)
       _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV");
@@ -954,6 +985,14 @@ dri2_x11_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
    }
 }
 
+static struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = {
+   .authenticate = NULL,
+};
+
+static struct dri2_egl_display_vtbl dri2_x11_display_vtbl = {
+   .authenticate = dri2_x11_authenticate,
+};
+
 static EGLBoolean
 dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
 {
@@ -1013,6 +1052,11 @@ dri2_initialize_x11_swrast(_EGLDriver *drv, _EGLDisplay *disp)
    disp->VersionMajor = 1;
    disp->VersionMinor = 4;
 
+   /* Fill vtbl last to prevent accidentally calling virtual function during
+    * initialization.
+    */
+   dri2_dpy->vtbl = &dri2_x11_swrast_display_vtbl;
+
    return EGL_TRUE;
 
  cleanup_configs:
@@ -1162,10 +1206,7 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_create_screen(disp))
       goto cleanup_fd;
 
-   if (dri2_dpy->conn) {
-      if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
-        goto cleanup_configs;
-   }
+   dri2_setup_swap_interval(dri2_dpy);
 
    disp->Extensions.KHR_image_pixmap = EGL_TRUE;
    disp->Extensions.NOK_swap_region = EGL_TRUE;
@@ -1175,13 +1216,20 @@ dri2_initialize_x11_dri2(_EGLDriver *drv, _EGLDisplay *disp)
 #ifdef HAVE_WAYLAND_PLATFORM
    disp->Extensions.WL_bind_wayland_display = EGL_TRUE;
 #endif
-   dri2_dpy->authenticate = dri2_x11_authenticate;
+
+   if (dri2_dpy->conn) {
+      if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
+        goto cleanup_configs;
+   }
 
    /* we're supporting EGL 1.4 */
    disp->VersionMajor = 1;
    disp->VersionMinor = 4;
 
-   dri2_setup_swap_interval(dri2_dpy);
+   /* Fill vtbl last to prevent accidentally calling virtual function during
+    * initialization.
+    */
+   dri2_dpy->vtbl = &dri2_x11_display_vtbl;
 
    return EGL_TRUE;