egl: drop unused _EGLDriver from SwapInterval()
[mesa.git] / src / egl / drivers / dri2 / platform_x11_dri3.c
index b781987c7372a2739f23f4add9e9508d55a1ed3d..c5af9b50834829df6c45e2e2d7e429afdb25e74c 100644 (file)
@@ -30,9 +30,9 @@
 #include <xcb/present.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"
@@ -44,43 +44,14 @@ loader_drawable_to_egl_surface(struct loader_dri3_drawable *draw) {
    return (struct dri3_egl_surface *)(((void*) draw) - offset);
 }
 
-static int
-egl_dri3_get_swap_interval(struct loader_dri3_drawable *draw)
-{
-   struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
-
-   return dri3_surf->base.SwapInterval;
-}
-
-static int
-egl_dri3_clamp_swap_interval(struct loader_dri3_drawable *draw, int interval)
-{
-   struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
-
-   if (interval > dri3_surf->base.Config->MaxSwapInterval)
-      interval = dri3_surf->base.Config->MaxSwapInterval;
-   else if (interval < dri3_surf->base.Config->MinSwapInterval)
-      interval = dri3_surf->base.Config->MinSwapInterval;
-
-   return interval;
-}
-
-static void
-egl_dri3_set_swap_interval(struct loader_dri3_drawable *draw, int interval)
-{
-   struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
-
-   dri3_surf->base.SwapInterval = interval;
-}
-
 static void
 egl_dri3_set_drawable_size(struct loader_dri3_drawable *draw,
                            int width, int height)
 {
    struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
 
-   dri3_surf->base.Width = width;
-   dri3_surf->base.Height = height;
+   dri3_surf->surf.base.Width = width;
+   dri3_surf->surf.base.Height = height;
 }
 
 static bool
@@ -89,7 +60,7 @@ egl_dri3_in_current_context(struct loader_dri3_drawable *draw)
    struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
    _EGLContext *ctx = _eglGetCurrentContext();
 
-   return ctx->Resource.Display == dri3_surf->base.Resource.Display;
+   return ctx->Resource.Display == dri3_surf->surf.base.Resource.Display;
 }
 
 static __DRIcontext *
@@ -103,81 +74,73 @@ egl_dri3_get_dri_context(struct loader_dri3_drawable *draw)
    return dri2_ctx->dri_context;
 }
 
+static __DRIscreen *
+egl_dri3_get_dri_screen(void)
+{
+   _EGLContext *ctx = _eglGetCurrentContext();
+   struct dri2_egl_context *dri2_ctx;
+   if (!ctx)
+      return NULL;
+   dri2_ctx = dri2_egl_context(ctx);
+   return dri2_egl_display(dri2_ctx->base.Resource.Display)->dri_screen;
+}
+
 static void
 egl_dri3_flush_drawable(struct loader_dri3_drawable *draw, unsigned flags)
 {
    struct dri3_egl_surface *dri3_surf = loader_drawable_to_egl_surface(draw);
-   _EGLDisplay *disp = dri3_surf->base.Resource.Display;
+   _EGLDisplay *disp = dri3_surf->surf.base.Resource.Display;
 
-   dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->base);
+   dri2_flush_drawable_for_swapbuffers(disp, &dri3_surf->surf.base);
 }
 
-static struct loader_dri3_vtable egl_dri3_vtable = {
-   .get_swap_interval = egl_dri3_get_swap_interval,
-   .clamp_swap_interval = egl_dri3_clamp_swap_interval,
-   .set_swap_interval = egl_dri3_set_swap_interval,
+static const struct loader_dri3_vtable egl_dri3_vtable = {
    .set_drawable_size = egl_dri3_set_drawable_size,
    .in_current_context = egl_dri3_in_current_context,
    .get_dri_context = egl_dri3_get_dri_context,
+   .get_dri_screen = egl_dri3_get_dri_screen,
    .flush_drawable = egl_dri3_flush_drawable,
    .show_fps = NULL,
 };
 
 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);
-
-   (void) drv;
-
-   if (!_eglPutSurface(surf))
-      return EGL_TRUE;
+   xcb_drawable_t drawable = dri3_surf->loader_drawable.drawable;
 
    loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
 
+   if (surf->Type == EGL_PBUFFER_BIT)
+      xcb_free_pixmap (dri2_dpy->conn, drawable);
+
+   dri2_fini_surface(surf);
    free(surf);
 
    return EGL_TRUE;
 }
 
 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);
 
+   dri3_surf->surf.base.SwapInterval = interval;
    loader_dri3_set_swap_interval(&dri3_surf->loader_drawable, interval);
 
    return EGL_TRUE;
 }
 
-static xcb_screen_t *
-get_xcb_screen(xcb_screen_iterator_t iter, int screen)
-{
-    for (; iter.rem; --screen, xcb_screen_next(&iter))
-        if (screen == 0)
-            return iter.data;
-
-    return NULL;
-}
-
 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);
    struct dri3_egl_surface *dri3_surf;
    const __DRIconfig *dri_config;
    xcb_drawable_t drawable;
-   xcb_screen_iterator_t s;
-   xcb_screen_t *screen;
-
-   STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
-   drawable = (uintptr_t) native_surface;
-
-   (void) drv;
 
    dri3_surf = calloc(1, sizeof *dri3_surf);
    if (!dri3_surf) {
@@ -185,29 +148,33 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       return NULL;
    }
 
-   if (!_eglInitSurface(&dri3_surf->base, disp, type, conf, attrib_list))
+   if (!dri2_init_surface(&dri3_surf->surf.base, disp, type, conf,
+                          attrib_list, false, native_surface))
       goto cleanup_surf;
 
    if (type == EGL_PBUFFER_BIT) {
-      s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
-      screen = get_xcb_screen(s, dri2_dpy->screen);
-      if (!screen) {
-         _eglError(EGL_BAD_NATIVE_WINDOW, "dri3_create_surface");
-         goto cleanup_surf;
-      }
-
       drawable = xcb_generate_id(dri2_dpy->conn);
       xcb_create_pixmap(dri2_dpy->conn, conf->BufferSize,
-                        drawable, screen->root,
-                        dri3_surf->base.Width, dri3_surf->base.Height);
+                        drawable, dri2_dpy->screen->root,
+                        dri3_surf->surf.base.Width, dri3_surf->surf.base.Height);
+   } else {
+      STATIC_ASSERT(sizeof(uintptr_t) == sizeof(native_surface));
+      drawable = (uintptr_t) native_surface;
    }
 
    dri_config = dri2_get_dri_config(dri2_conf, type,
-                                    dri3_surf->base.GLColorspace);
+                                    dri3_surf->surf.base.GLColorspace);
+
+   if (!dri_config) {
+      _eglError(EGL_BAD_MATCH, "Unsupported surfacetype/colorspace configuration");
+      goto cleanup_pixmap;
+   }
 
    if (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
                                  dri2_dpy->dri_screen,
-                                 dri2_dpy->is_different_gpu, dri_config,
+                                 dri2_dpy->is_different_gpu,
+                                 dri2_dpy->multibuffers_available,
+                                 dri_config,
                                  &dri2_dpy->loader_dri3_ext,
                                  &egl_dri3_vtable,
                                  &dri3_surf->loader_drawable)) {
@@ -215,7 +182,7 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
       goto cleanup_pixmap;
    }
 
-   return &dri3_surf->base;
+   return &dri3_surf->surf.base;
 
  cleanup_pixmap:
    if (type == EGL_PBUFFER_BIT)
@@ -226,40 +193,57 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    return NULL;
 }
 
+static int
+dri3_authenticate(_EGLDisplay *disp, uint32_t id)
+{
+#ifdef HAVE_WAYLAND_PLATFORM
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   if (dri2_dpy->device_name) {
+      _eglLog(_EGL_WARNING,
+              "Wayland client render node authentication is unnecessary");
+      return 0;
+   }
+
+   _eglLog(_EGL_WARNING,
+           "Wayland client primary node authentication isn't supported");
+#endif
+
+   return -1;
+}
+
 /**
- * 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,
-                              XCB_WINDOW_NONE, attrib_list);
+   return dri3_create_surface(disp, EGL_PBUFFER_BIT, conf,
+                              NULL, attrib_list);
 }
 
 static EGLBoolean
@@ -294,17 +278,8 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
       return NULL;
    }
 
-   switch (bp_reply->depth) {
-   case 16:
-      format = __DRI_IMAGE_FORMAT_RGB565;
-      break;
-   case 24:
-      format = __DRI_IMAGE_FORMAT_XRGB8888;
-      break;
-   case 32:
-      format = __DRI_IMAGE_FORMAT_ARGB8888;
-      break;
-   default:
+   format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
+   if (format == __DRI_IMAGE_FORMAT_NONE) {
       _eglError(EGL_BAD_PARAMETER,
                 "dri3_create_image_khr: unsupported pixmap depth");
       free(bp_reply);
@@ -314,13 +289,11 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
    dri2_img = malloc(sizeof *dri2_img);
    if (!dri2_img) {
       _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
+      free(bp_reply);
       return EGL_NO_IMAGE_KHR;
    }
 
-   if (!_eglInitImage(&dri2_img->base, disp)) {
-      free(dri2_img);
-      return EGL_NO_IMAGE_KHR;
-   }
+   _eglInitImage(&dri2_img->base, disp);
 
    dri2_img->dri_image = loader_dri3_create_image(dri2_dpy->conn,
                                                   bp_reply,
@@ -334,15 +307,80 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
    return &dri2_img->base;
 }
 
+#ifdef HAVE_DRI3_MODIFIERS
 static _EGLImage *
-dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
+dri3_create_image_khr_pixmap_from_buffers(_EGLDisplay *disp, _EGLContext *ctx,
+                                          EGLClientBuffer buffer,
+                                          const EGLint *attr_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct dri2_egl_image *dri2_img;
+   xcb_dri3_buffers_from_pixmap_cookie_t bp_cookie;
+   xcb_dri3_buffers_from_pixmap_reply_t  *bp_reply;
+   xcb_drawable_t drawable;
+   unsigned int format;
+
+   drawable = (xcb_drawable_t) (uintptr_t) buffer;
+   bp_cookie = xcb_dri3_buffers_from_pixmap(dri2_dpy->conn, drawable);
+   bp_reply = xcb_dri3_buffers_from_pixmap_reply(dri2_dpy->conn,
+                                                 bp_cookie, NULL);
+
+   if (!bp_reply) {
+      _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   format = dri2_format_for_depth(dri2_dpy, bp_reply->depth);
+   if (format == __DRI_IMAGE_FORMAT_NONE) {
+      _eglError(EGL_BAD_PARAMETER,
+                "dri3_create_image_khr: unsupported pixmap depth");
+      free(bp_reply);
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   dri2_img = malloc(sizeof *dri2_img);
+   if (!dri2_img) {
+      _eglError(EGL_BAD_ALLOC, "dri3_create_image_khr");
+      free(bp_reply);
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   _eglInitImage(&dri2_img->base, disp);
+
+   dri2_img->dri_image = loader_dri3_create_image_from_buffers(dri2_dpy->conn,
+                                                               bp_reply,
+                                                               format,
+                                                               dri2_dpy->dri_screen,
+                                                               dri2_dpy->image,
+                                                               dri2_img);
+   free(bp_reply);
+
+   if (!dri2_img->dri_image) {
+      _eglError(EGL_BAD_ATTRIBUTE, "dri3_create_image_khr");
+      free(dri2_img);
+      return EGL_NO_IMAGE_KHR;
+   }
+
+   return &dri2_img->base;
+}
+#endif
+
+static _EGLImage *
+dri3_create_image_khr(const _EGLDriver *drv, _EGLDisplay *disp,
                       _EGLContext *ctx, EGLenum target,
                       EGLClientBuffer buffer, const EGLint *attr_list)
 {
-   (void) drv;
+#ifdef HAVE_DRI3_MODIFIERS
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+#endif
 
    switch (target) {
    case EGL_NATIVE_PIXMAP_KHR:
+#ifdef HAVE_DRI3_MODIFIERS
+      if (dri2_dpy->multibuffers_available)
+         return dri3_create_image_khr_pixmap_from_buffers(disp, ctx, buffer,
+                                                          attr_list);
+#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);
@@ -356,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 = {
@@ -373,21 +413,17 @@ const __DRIimageLoaderExtension dri3_image_loader_extension = {
 };
 
 static EGLBoolean
-dri3_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
+dri3_swap_buffers(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(draw);
 
-   /* No-op for a pixmap or pbuffer surface */
-   if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
-      return 0;
-
    return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable,
                                        0, 0, 0, 0,
                                        draw->SwapBehavior == EGL_BUFFER_PRESERVED) != -1;
 }
 
 static EGLBoolean
-dri3_copy_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
+dri3_copy_buffers(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
                   void *native_pixmap_target)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
@@ -403,13 +439,31 @@ 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(const _EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 {
    struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
 
    return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
 }
 
+static EGLBoolean
+dri3_query_surface(_EGLDisplay *disp, _EGLSurface *surf,
+                   EGLint attribute, EGLint *value)
+{
+   struct dri3_egl_surface *dri3_surf = dri3_egl_surface(surf);
+
+   switch (attribute) {
+   case EGL_WIDTH:
+   case EGL_HEIGHT:
+      loader_dri3_update_drawable_geometry(&dri3_surf->loader_drawable);
+      break;
+   default:
+      break;
+   }
+
+   return _eglQuerySurface(disp, surf, attribute, value);
+}
+
 static __DRIdrawable *
 dri3_get_dri_drawable(_EGLSurface *surf)
 {
@@ -418,8 +472,16 @@ dri3_get_dri_drawable(_EGLSurface *surf)
    return dri3_surf->loader_drawable.dri_drawable;
 }
 
+static void
+dri3_close_screen_notify(_EGLDisplay *disp)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+
+   loader_dri3_close_screen(dri2_dpy->dri_screen);
+}
+
 struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
-   .authenticate = NULL,
+   .authenticate = dri3_authenticate,
    .create_window_surface = dri3_create_window_surface,
    .create_pixmap_surface = dri3_create_pixmap_surface,
    .create_pbuffer_surface = dri3_create_pbuffer_surface,
@@ -427,16 +489,26 @@ 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,
-   .post_sub_buffer = dri2_fallback_post_sub_buffer,
    .copy_buffers = dri3_copy_buffers,
    .query_buffer_age = dri3_query_buffer_age,
-   .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
+   .query_surface = dri3_query_surface,
    .get_sync_values = dri3_get_sync_values,
    .get_dri_drawable = dri3_get_dri_drawable,
+   .close_screen_notify = dri3_close_screen_notify,
 };
 
+/* Only request versions of these protocols which we actually support. */
+#define DRI3_SUPPORTED_MAJOR 1
+#define PRESENT_SUPPORTED_MAJOR 1
+
+#ifdef HAVE_DRI3_MODIFIERS
+#define DRI3_SUPPORTED_MINOR 2
+#define PRESENT_SUPPORTED_MINOR 2
+#else
+#define PRESENT_SUPPORTED_MINOR 0
+#define DRI3_SUPPORTED_MINOR 0
+#endif
+
 EGLBoolean
 dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
 {
@@ -445,8 +517,6 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
    xcb_present_query_version_reply_t *present_query;
    xcb_present_query_version_cookie_t present_query_cookie;
    xcb_generic_error_t *error;
-   xcb_screen_iterator_t s;
-   xcb_screen_t *screen;
    const xcb_query_extension_reply_t *extension;
 
    xcb_prefetch_extension_data (dri2_dpy->conn, &xcb_dri3_id);
@@ -461,12 +531,12 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
       return EGL_FALSE;
 
    dri3_query_cookie = xcb_dri3_query_version(dri2_dpy->conn,
-                                              XCB_DRI3_MAJOR_VERSION,
-                                              XCB_DRI3_MINOR_VERSION);
+                                              DRI3_SUPPORTED_MAJOR,
+                                              DRI3_SUPPORTED_MINOR);
 
    present_query_cookie = xcb_present_query_version(dri2_dpy->conn,
-                                                    XCB_PRESENT_MAJOR_VERSION,
-                                                    XCB_PRESENT_MINOR_VERSION);
+                                                    PRESENT_SUPPORTED_MAJOR,
+                                                    PRESENT_SUPPORTED_MINOR);
 
    dri3_query =
       xcb_dri3_query_version_reply(dri2_dpy->conn, dri3_query_cookie, &error);
@@ -476,6 +546,9 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
       free(error);
       return EGL_FALSE;
    }
+
+   dri2_dpy->dri3_major_version = dri3_query->major_version;
+   dri2_dpy->dri3_minor_version = dri3_query->minor_version;
    free(dri3_query);
 
    present_query =
@@ -487,16 +560,12 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
       free(error);
       return EGL_FALSE;
    }
-   free(present_query);
 
-   s = xcb_setup_roots_iterator(xcb_get_setup(dri2_dpy->conn));
-   screen = get_xcb_screen(s, dri2_dpy->screen);
-   if (!screen) {
-      _eglError(EGL_BAD_NATIVE_WINDOW, "dri3_x11_connect");
-      return EGL_FALSE;
-   }
+   dri2_dpy->present_major_version = present_query->major_version;
+   dri2_dpy->present_minor_version = present_query->minor_version;
+   free(present_query);
 
-   dri2_dpy->fd = loader_dri3_open(dri2_dpy->conn, screen->root, 0);
+   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);
       _eglLog(_EGL_WARNING, "DRI3: Screen seems not DRI3 capable");
@@ -509,18 +578,19 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
 
    dri2_dpy->fd = loader_get_user_preferred_fd(dri2_dpy->fd, &dri2_dpy->is_different_gpu);
 
-   dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd, 0);
+   dri2_dpy->driver_name = loader_get_driver_for_fd(dri2_dpy->fd);
    if (!dri2_dpy->driver_name) {
       _eglLog(_EGL_WARNING, "DRI3: No driver found");
       close(dri2_dpy->fd);
       return EGL_FALSE;
    }
 
-   /* Only try to get a render device name since it's only needed for
-    * WL_bind_wayland_display and dri3 doesn't provide a mechanism for
-    * authenticating client opened device node fds. If this fails then
-    * don't advertise the extension. */
+#ifdef HAVE_WAYLAND_PLATFORM
+   /* Only try to get a render device name since dri3 doesn't provide a
+    * mechanism for authenticating client opened device node fds. If this
+    * fails then don't advertise the extension. */
    dri2_dpy->device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd);
+#endif
 
    return EGL_TRUE;
 }