egl/x11_dri3: enable & require xfixes 2.0
[mesa.git] / src / egl / drivers / dri2 / platform_x11_dri3.c
index 2b1faf1a396c4953ff762d19a2d635b67fff4801..5c69a3b981e4a0f50ad9c82fccaddc9ce5cb3fd8 100644 (file)
 #include <xcb/xcb.h>
 #include <xcb/dri3.h>
 #include <xcb/present.h>
+#include <xcb/xfixes.h>
 
 #include <xf86drm.h>
 #include "util/macros.h"
 
 #include "egl_dri2.h"
-#include "egl_dri2_fallbacks.h"
 #include "platform_x11_dri3.h"
 
 #include "loader.h"
@@ -105,14 +105,12 @@ static const struct loader_dri3_vtable egl_dri3_vtable = {
 };
 
 static EGLBoolean
-dri3_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
+dri3_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
    xcb_drawable_t drawable = dri3_surf->loader_drawable.drawable;
 
-   (void) drv;
-
    loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
 
    if (surf->Type == EGL_PBUFFER_BIT)
@@ -125,8 +123,7 @@ dri3_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 }
 
 static EGLBoolean
-dri3_set_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
-                       EGLint interval)
+dri3_set_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
 
@@ -137,9 +134,8 @@ dri3_set_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
 }
 
 static _EGLSurface *
-dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
-                    _EGLConfig *conf, void *native_surface,
-                    const EGLint *attrib_list)
+dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
+                    void *native_surface, const EGLint *attrib_list)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    struct dri2_egl_config *dri2_conf = dri2_egl_config(conf);
@@ -147,8 +143,6 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    const __DRIconfig *dri_config;
    xcb_drawable_t drawable;
 
-   (void) drv;
-
    dri3_surf = calloc(1, sizeof *dri3_surf);
    if (!dri3_surf) {
       _eglError(EGL_BAD_ALLOC, "dri3_create_surface");
@@ -220,38 +214,36 @@ dri3_authenticate(_EGLDisplay *disp, uint32_t id)
 }
 
 /**
- * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ * Called via eglCreateWindowSurface(), drv->CreateWindowSurface().
  */
 static _EGLSurface *
-dri3_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp,
-                           _EGLConfig *conf, void *native_window,
-                           const EGLint *attrib_list)
+dri3_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf,
+                           void *native_window, const EGLint *attrib_list)
 {
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    _EGLSurface *surf;
 
-   surf = dri3_create_surface(drv, disp, EGL_WINDOW_BIT, conf,
+   surf = dri3_create_surface(disp, EGL_WINDOW_BIT, conf,
                               native_window, attrib_list);
    if (surf != NULL)
-      dri3_set_swap_interval(drv, disp, surf, dri2_dpy->default_swap_interval);
+      dri3_set_swap_interval(disp, surf, dri2_dpy->default_swap_interval);
 
    return surf;
 }
 
 static _EGLSurface *
-dri3_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp,
-                           _EGLConfig *conf, void *native_pixmap,
-                           const EGLint *attrib_list)
+dri3_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf,
+                           void *native_pixmap, const EGLint *attrib_list)
 {
-   return dri3_create_surface(drv, disp, EGL_PIXMAP_BIT, conf,
+   return dri3_create_surface(disp, EGL_PIXMAP_BIT, conf,
                               native_pixmap, attrib_list);
 }
 
 static _EGLSurface *
-dri3_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
-                                _EGLConfig *conf, const EGLint *attrib_list)
+dri3_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf,
+                            const EGLint *attrib_list)
 {
-   return dri3_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
+   return dri3_create_surface(disp, EGL_PBUFFER_BIT, conf,
                               NULL, attrib_list);
 }
 
@@ -375,8 +367,7 @@ dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx,
 #endif
 
 static _EGLImage *
-dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
-                      _EGLContext *ctx, EGLenum target,
+dri3_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target,
                       EGLClientBuffer buffer, const EGLint *attr_list)
 {
 #ifdef HAVE_DRI3_MODIFIERS
@@ -392,7 +383,7 @@ dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 #endif
       return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
    default:
-      return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
+      return dri2_create_image_khr(disp, ctx, target, buffer, attr_list);
    }
 }
 
@@ -422,7 +413,7 @@ const __DRIimageLoaderExtension dri3_image_loader_extension = {
 };
 
 static EGLBoolean
-dri3_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+dri3_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
 
@@ -432,8 +423,7 @@ dri3_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 }
 
 static EGLBoolean
-dri3_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
-                  void *native_pixmap_target)
+dri3_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
    xcb_pixmap_t target;
@@ -448,7 +438,7 @@ dri3_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
 }
 
 static int
-dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
+dri3_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
 
@@ -456,9 +446,8 @@ dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 }
 
 static EGLBoolean
-dri3_query_surface(_EGLDriver *drv, _EGLDisplay *disp,
-                   _EGLSurface *surf, EGLint attribute,
-                   EGLint *value)
+dri3_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
+                   EGLint attribute, EGLint *value)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
 
@@ -471,7 +460,7 @@ dri3_query_surface(_EGLDriver *drv, _EGLDisplay *disp,
       break;
    }
 
-   return _eglQuerySurface(drv, disp, surf, attribute, value);
+   return _eglQuerySurface(disp, surf, attribute, value);
 }
 
 static __DRIdrawable *
@@ -499,11 +488,9 @@ struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
    .create_image = dri3_create_image_khr,
    .swap_interval = dri3_set_swap_interval,
    .swap_buffers = dri3_swap_buffers,
-   .post_sub_buffer = dri2_fallback_post_sub_buffer,
    .copy_buffers = dri3_copy_buffers,
    .query_buffer_age = dri3_query_buffer_age,
    .query_surface = dri3_query_surface,
-   .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
    .get_sync_values = dri3_get_sync_values,
    .get_dri_drawable = dri3_get_dri_drawable,
    .close_screen_notify = dri3_close_screen_notify,
@@ -528,11 +515,14 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
    xcb_dri3_query_version_cookie_t dri3_query_cookie;
    xcb_present_query_version_reply_t *present_query;
    xcb_present_query_version_cookie_t present_query_cookie;
+   xcb_xfixes_query_version_reply_t *xfixes_query;
+   xcb_xfixes_query_version_cookie_t xfixes_query_cookie;
    xcb_generic_error_t *error;
    const xcb_query_extension_reply_t *extension;
 
    xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
    xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_present_id);
+   xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_xfixes_id);
 
    extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_dri3_id);
    if (!(extension && extension->present))
@@ -542,6 +532,10 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
    if (!(extension && extension->present))
       return EGL_FALSE;
 
+   extension = xcb_get_extension_data(dri2_dpy->conn, &xcb_xfixes_id);
+   if (!(extension && extension->present))
+      return EGL_FALSE;
+
    dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn,
                                               DRI3_SUPPORTED_MAJOR,
                                               DRI3_SUPPORTED_MINOR);
@@ -550,6 +544,10 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
                                                     PRESENT_SUPPORTED_MAJOR,
                                                     PRESENT_SUPPORTED_MINOR);
 
+   xfixes_query_cookie = xcb_xfixes_query_version(dri2_dpy->conn,
+                                                  XCB_XFIXES_MAJOR_VERSION,
+                                                  XCB_XFIXES_MINOR_VERSION);
+
    dri3_query =
       xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, &error);
    if (dri3_query == NULL || error != NULL) {
@@ -577,6 +575,18 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
    dri2_dpy->present_minor_version = present_query->minor_version;
    free(present_query);
 
+   xfixes_query =
+      xcb_xfixes_query_version_reply(dri2_dpy->conn,
+                                      xfixes_query_cookie, &error);
+   if (xfixes_query == NULL || error != NULL ||
+       xfixes_query->major_version < 2) {
+      _eglLog(_EGL_WARNING, "DRI3: failed to query xfixes version");
+      free(error);
+      free(xfixes_query);
+      return EGL_FALSE;
+   }
+   free(xfixes_query);
+
    dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, dri2_dpy->screen->root, 0);
    if (dri2_dpy->fd < 0) {
       int conn_error = xcb_connection_has_error(dri2_dpy->conn);