egl/x11_dri3: enable & require xfixes 2.0
[mesa.git] / src / egl / drivers / dri2 / platform_x11_dri3.c
index 1206cd39ae642fdbf32a9cbd8ee54c91f2569619..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,15 +143,14 @@ 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");
       return NULL;
    }
 
-   if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf, attrib_list, false))
+   if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf,
+                          attrib_list, false, native_surface))
       goto cleanup_surf;
 
    if (type == EGL_PBUFFER_BIT) {
@@ -219,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);
 }
 
@@ -374,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
@@ -391,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);
    }
 }
 
@@ -402,13 +394,15 @@ dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 static void
 dri3_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
 {
+   struct loader_dri3_drawable *draw = loaderPrivate;
+   (void) driDrawable;
+
    /* There does not seem to be any kind of consensus on whether we should
     * support front-buffer rendering or not:
     * http://lists.freedesktop.org/archives/mesa-dev/2013-June/040129.html
     */
-   _eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
-   (void) driDrawable;
-   (void) loaderPrivate;
+   if (!draw->is_pixmap)
+      _eglLog(_EGL_WARNING, "FIXME: egl/x11 doesn't support front buffer rendering.");
 }
 
 const __DRIimageLoaderExtension dri3_image_loader_extension = {
@@ -419,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);
 
@@ -429,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;
@@ -445,7 +438,7 @@ dri3_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
 }
 
 static int
-dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
+dri3_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
 
@@ -453,9 +446,8 @@ dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
 }
 
 static EGLBoolean
-dri3_query_surface(_EGLDriver *drv, _EGLDisplay *dpy,
-                   _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);
 
@@ -468,7 +460,7 @@ dri3_query_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       break;
    }
 
-   return _eglQuerySurface(drv, dpy, surf, attribute, value);
+   return _eglQuerySurface(disp, surf, attribute, value);
 }
 
 static __DRIdrawable *
@@ -480,9 +472,9 @@ dri3_get_dri_drawable(_EGLSurface *surf)
 }
 
 static void
-dri3_close_screen_notify(_EGLDisplay *dpy)
+dri3_close_screen_notify(_EGLDisplay *disp)
 {
-   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
 
    loader_dri3_close_screen(dri2_dpy->dri_screen);
 }
@@ -496,14 +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,
-   .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
-   .swap_buffers_region = dri2_fallback_swap_buffers_region,
-   .set_damage_region = dri2_fallback_set_damage_region,
-   .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);