loader_dri3/glx/egl: Reinstate the loader_dri3_vtable get_dri_screen callback
[mesa.git] / src / egl / drivers / dri2 / platform_x11_dri3.c
index 31649fe849e3ad2753673df8a2cd603bca1ac307..2073c592dc94d8a73cdd2aee52136639621e8eaf 100644 (file)
@@ -30,6 +30,7 @@
 #include <xcb/present.h>
 
 #include <xf86drm.h>
+#include "util/macros.h"
 
 #include "egl_dri2.h"
 #include "egl_dri2_fallbacks.h"
@@ -44,43 +45,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 +61,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,22 +75,31 @@ 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,
 };
@@ -130,11 +111,9 @@ dri3_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
 
    (void) drv;
 
-   if (!_eglPutSurface(surf))
-      return EGL_TRUE;
-
    loader_dri3_drawable_fini(&dri3_surf->loader_drawable);
 
+   dri2_fini_surface(surf);
    free(surf);
 
    return EGL_TRUE;
@@ -146,21 +125,12 @@ dri3_set_swap_interval(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
 {
    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,
@@ -171,11 +141,6 @@ dri3_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
    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;
 
@@ -185,25 +150,21 @@ 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))
       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 (loader_dri3_drawable_init(dri2_dpy->conn, drawable,
                                  dri2_dpy->dri_screen,
@@ -215,7 +176,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)
@@ -278,7 +239,7 @@ dri3_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *disp,
                                 _EGLConfig *conf, const EGLint *attrib_list)
 {
    return dri3_create_surface(drv, disp, EGL_PBUFFER_BIT, conf,
-                              XCB_WINDOW_NONE, attrib_list);
+                              NULL, attrib_list);
 }
 
 static EGLBoolean
@@ -320,6 +281,9 @@ dri3_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
    case 24:
       format = __DRI_IMAGE_FORMAT_XRGB8888;
       break;
+   case 30:
+      format = __DRI_IMAGE_FORMAT_XRGB2101010;
+      break;
    case 32:
       format = __DRI_IMAGE_FORMAT_ARGB8888;
       break;
@@ -333,13 +297,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,
@@ -358,8 +320,6 @@ dri3_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
                       _EGLContext *ctx, EGLenum target,
                       EGLClientBuffer buffer, const EGLint *attr_list)
 {
-   (void) drv;
-
    switch (target) {
    case EGL_NATIVE_PIXMAP_KHR:
       return dri3_create_image_khr_pixmap(disp, ctx, buffer, attr_list);
@@ -398,7 +358,7 @@ dri3_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
 
    /* No-op for a pixmap or pbuffer surface */
    if (draw->Type == EGL_PIXMAP_BIT || draw->Type == EGL_PBUFFER_BIT)
-      return 0;
+      return EGL_FALSE;
 
    return loader_dri3_swap_buffers_msc(&dri3_surf->loader_drawable,
                                        0, 0, 0, 0,
@@ -429,6 +389,25 @@ dri3_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
    return loader_dri3_query_buffer_age(&dri3_surf->loader_drawable);
 }
 
+static EGLBoolean
+dri3_query_surface(_EGLDriver *drv, _EGLDisplay *dpy,
+                   _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(drv, dpy, surf, attribute, value);
+}
+
 static __DRIdrawable *
 dri3_get_dri_drawable(_EGLSurface *surf)
 {
@@ -437,6 +416,14 @@ dri3_get_dri_drawable(_EGLSurface *surf)
    return dri3_surf->loader_drawable.dri_drawable;
 }
 
+static void
+dri3_close_screen_notify(_EGLDisplay *dpy)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
+
+   loader_dri3_close_screen(dri2_dpy->dri_screen);
+}
+
 struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
    .authenticate = dri3_authenticate,
    .create_window_surface = dri3_create_window_surface,
@@ -448,12 +435,15 @@ struct dri2_egl_display_vtbl dri3_x11_display_vtbl = {
    .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,
 };
 
 EGLBoolean
@@ -464,8 +454,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);
@@ -508,14 +496,7 @@ dri3_x11_connect(struct dri2_egl_display *dri2_dpy)
    }
    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->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");
@@ -528,7 +509,7 @@ 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);