[RFC xserver v6 12/14] glamor: Implement GetSupportedModifiers

Louis-Francis Ratté-Boulianne lfrb at collabora.com
Fri Feb 16 04:15:45 UTC 2018


Implement function added in DRI3 v1.1.

A newest version of libepoxy (>= 1.4.4) is required as earlier
versions use a problematic version of Khronos
EXT_image_dma_buf_import_modifiers spec.

v4: Only send scanout-supported modifiers if flipping is possible
v5: Fix memory corruption in XWayland (uninitialized pointer)

Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Reviewed-by: Daniel Stone <daniels at collabora.com>
---
 configure.ac                                     |   4 +
 glamor/glamor.c                                  |  25 +++++
 glamor/glamor.h                                  |  23 ++++
 glamor/glamor_egl.c                              |  92 +++++++++++++++
 glamor/glamor_priv.h                             |   1 +
 glamor/meson.build                               |   4 +-
 hw/kdrive/ephyr/meson.build                      |   1 +
 hw/xfree86/common/xf86Mode.c                     |   1 +
 hw/xfree86/drivers/modesetting/driver.c          |  12 +-
 hw/xfree86/drivers/modesetting/drmmode_display.c |  36 ++++++
 hw/xfree86/drivers/modesetting/drmmode_display.h |   1 +
 hw/xwayland/xwayland-glamor.c                    | 135 ++++++++++++++++++++---
 hw/xwayland/xwayland.h                           |   9 +-
 include/dix-config.h.in                          |   3 +
 include/meson.build                              |   2 +
 meson.build                                      |   4 +-
 present/present.c                                |  38 +++++++
 present/present.h                                |   3 +
 18 files changed, 370 insertions(+), 24 deletions(-)

diff --git a/configure.ac b/configure.ac
index a9577aa82..baa295749 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2092,6 +2092,10 @@ if test "x$GLAMOR" = xyes; then
 	AC_DEFINE(GLAMOR, 1, [Build glamor])
 	PKG_CHECK_MODULES([GLAMOR], [epoxy])
 
+	PKG_CHECK_EXISTS(epoxy >= 1.4.4,
+			 [AC_DEFINE(GLAMOR_HAS_EGL_QUERY_DMABUF, 1, [Have GLAMOR_HAS_EGL_QUERY_DMABUF])],
+			 [])
+
 	PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
 	if test "x$GBM" = xyes; then
 		AC_DEFINE(GLAMOR_HAS_GBM, 1,
diff --git a/glamor/glamor.c b/glamor/glamor.c
index c4f6bcbf9..1559310db 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -793,6 +793,31 @@ glamor_supports_pixmap_import_export(ScreenPtr screen)
     return glamor_priv->dri3_enabled;
 }
 
+_X_EXPORT void
+glamor_set_drawable_modifiers_func(ScreenPtr screen,
+                                   GetDrawableModifiersFuncPtr func)
+{
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+
+    glamor_priv->get_drawable_modifiers = func;
+}
+
+_X_EXPORT Bool
+glamor_get_drawable_modifiers(DrawablePtr draw, CARD32 format,
+                              CARD32 *num_modifiers, uint64_t **modifiers)
+{
+    struct glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(draw->pScreen);
+
+    if (glamor_priv->get_drawable_modifiers) {
+        return glamor_priv->get_drawable_modifiers(draw, format,
+                                                   num_modifiers, modifiers);
+    }
+    *num_modifiers = 0;
+    *modifiers = NULL;
+    return TRUE;
+}
+
 _X_EXPORT int
 glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
                        uint32_t *strides, uint32_t *offsets,
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 8f8c31b45..5475aedbb 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -60,6 +60,11 @@ typedef enum glamor_pixmap_type {
     GLAMOR_TEXTURE_ONLY,
 } glamor_pixmap_type_t;
 
+typedef Bool (*GetDrawableModifiersFuncPtr) (DrawablePtr draw,
+                                             CARD32 format,
+                                             CARD32 *num_modifiers,
+                                             uint64_t **modifiers);
+
 #define GLAMOR_EGL_EXTERNAL_BUFFER 3
 #define GLAMOR_USE_EGL_SCREEN		(1 << 0)
 #define GLAMOR_NO_DRI3			(1 << 1)
@@ -272,6 +277,24 @@ extern _X_EXPORT Bool glamor_back_pixmap_from_fd(PixmapPtr pixmap,
                                                  CARD16 stride,
                                                  CARD8 depth,
                                                  CARD8 bpp);
+
+extern _X_EXPORT Bool glamor_get_formats(ScreenPtr screen,
+                                         CARD32 *num_formats,
+                                         CARD32 **formats);
+
+extern _X_EXPORT Bool glamor_get_modifiers(ScreenPtr screen,
+                                           CARD32 format,
+                                           CARD32 *num_modifiers,
+                                           uint64_t **modifiers);
+
+extern _X_EXPORT Bool glamor_get_drawable_modifiers(DrawablePtr draw,
+                                                    CARD32 format,
+                                                    CARD32 *num_modifiers,
+                                                    uint64_t **modifiers);
+
+extern _X_EXPORT void glamor_set_drawable_modifiers_func(ScreenPtr screen,
+                                                         GetDrawableModifiersFuncPtr func);
+
 #ifdef GLAMOR_FOR_XORG
 
 #define GLAMOR_EGL_MODULE_NAME  "glamoregl"
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index f70b4693a..e22bc1f6a 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -504,6 +504,95 @@ glamor_pixmap_from_fds(ScreenPtr screen,
     return pixmap;
 }
 
+_X_EXPORT Bool
+glamor_get_formats(ScreenPtr screen,
+                   CARD32 *num_formats, CARD32 **formats)
+{
+#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF
+    struct glamor_egl_screen_private *glamor_egl;
+    EGLint num;
+
+    glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
+
+    if (!glamor_egl->dmabuf_capable)
+        return FALSE;
+
+    if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, 0, NULL, &num)) {
+        *num_formats = 0;
+        return FALSE;
+    }
+
+    if (num == 0) {
+        *num_formats = 0;
+        return TRUE;
+    }
+
+    *formats = calloc(num, sizeof(CARD32));
+    if (*formats == NULL) {
+        *num_formats = 0;
+        return FALSE;
+    }
+
+    if (!eglQueryDmaBufFormatsEXT(glamor_egl->display, num,
+                                  (EGLint *) *formats, &num)) {
+        *num_formats = 0;
+        free(*formats);
+        return FALSE;
+    }
+
+    *num_formats = num;
+    return TRUE;
+#else
+    *num_formats = 0;
+    return TRUE;
+#endif
+}
+
+_X_EXPORT Bool
+glamor_get_modifiers(ScreenPtr screen, CARD32 format,
+                     CARD32 *num_modifiers, uint64_t **modifiers)
+{
+#ifdef GLAMOR_HAS_EGL_QUERY_DMABUF
+    struct glamor_egl_screen_private *glamor_egl;
+    EGLint num;
+
+    glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen));
+
+    if (!glamor_egl->dmabuf_capable)
+        return FALSE;
+
+    if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, 0, NULL,
+                                    NULL, &num)) {
+        *num_modifiers = 0;
+        return FALSE;
+    }
+
+    if (num == 0) {
+        *num_modifiers = 0;
+        return TRUE;
+    }
+
+    *modifiers = calloc(num, sizeof(uint64_t));
+    if (*modifiers == NULL) {
+        *num_modifiers = 0;
+        return FALSE;
+    }
+
+    if (!eglQueryDmaBufModifiersEXT(glamor_egl->display, format, num,
+                                    (EGLuint64KHR *) *modifiers, NULL, &num)) {
+        *num_modifiers = 0;
+        free(*modifiers);
+        return FALSE;
+    }
+
+    *num_modifiers = num;
+    return TRUE;
+#else
+    *num_modifiers = 0;
+    return TRUE;
+#endif
+}
+
 static Bool
 glamor_egl_destroy_pixmap(PixmapPtr pixmap)
 {
@@ -625,6 +714,9 @@ static dri3_screen_info_rec glamor_dri3_info = {
     .open_client = glamor_dri3_open_client,
     .pixmap_from_fds = glamor_pixmap_from_fds,
     .fds_from_pixmap = glamor_egl_fds_from_pixmap,
+    .get_formats = glamor_get_formats,
+    .get_modifiers = glamor_get_modifiers,
+    .get_drawable_modifiers = glamor_get_drawable_modifiers,
 };
 #endif /* DRI3 */
 
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 2344066cb..3fff6396c 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -281,6 +281,7 @@ typedef struct glamor_screen_private {
     int radial_max_nstops;
 
     struct glamor_saved_procs saved_procs;
+    GetDrawableModifiersFuncPtr get_drawable_modifiers;
     int flags;
     ScreenPtr screen;
     int dri3_enabled;
diff --git a/glamor/meson.build b/glamor/meson.build
index 0b963275e..268af593e 100644
--- a/glamor/meson.build
+++ b/glamor/meson.build
@@ -38,12 +38,14 @@ if build_xv
     srcs_glamor += 'glamor_xv.c'
 endif
 
+epoxy_dep = dependency('epoxy')
+
 glamor = static_library('glamor',
     srcs_glamor,
     include_directories: inc,
     dependencies: [
         common_dep,
-        dependency('epoxy'),
+        epoxy_dep,
     ],
 )
 
diff --git a/hw/kdrive/ephyr/meson.build b/hw/kdrive/ephyr/meson.build
index 615649865..3c18a6096 100644
--- a/hw/kdrive/ephyr/meson.build
+++ b/hw/kdrive/ephyr/meson.build
@@ -30,6 +30,7 @@ if build_glamor
     xephyr_glamor += glamor
     xephyr_glamor += glamor_egl_stubs
     xephyr_dep += dependency('x11-xcb')
+    xephyr_dep += epoxy_dep
 endif
 
 if build_xv
diff --git a/hw/xfree86/common/xf86Mode.c b/hw/xfree86/common/xf86Mode.c
index 40d09a9f4..484cde7ab 100644
--- a/hw/xfree86/common/xf86Mode.c
+++ b/hw/xfree86/common/xf86Mode.c
@@ -86,6 +86,7 @@
 
 #include <X11/X.h>
 #include "xf86Modes.h"
+#include "xf86Crtc.h"
 #include "os.h"
 #include "servermd.h"
 #include "globals.h"
diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 28cf03648..11d84b6e0 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -1600,15 +1600,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
 
     fbPictureInit(pScreen, NULL, 0);
 
-#ifdef GLAMOR_HAS_GBM
-    if (ms->drmmode.glamor) {
-        if (!glamor_init(pScreen, GLAMOR_USE_EGL_SCREEN)) {
-            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-                       "Failed to initialize glamor at ScreenInit() time.\n");
-            return FALSE;
-        }
+    if (drmmode_init(pScrn, &ms->drmmode) == FALSE) {
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "Failed to initialize glamor at ScreenInit() time.\n");
+        return FALSE;
     }
-#endif
 
     if (ms->drmmode.shadow_enable && !msShadowInit(pScreen)) {
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "shadow fb init failed\n");
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.c b/hw/xfree86/drivers/modesetting/drmmode_display.c
index 106cf64f7..248eeec0d 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.c
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.c
@@ -45,6 +45,7 @@
 #include <xf86drm.h>
 #include "xf86Crtc.h"
 #include "drmmode_display.h"
+#include "present.h"
 
 #include <cursorstr.h>
 
@@ -175,6 +176,24 @@ get_modifiers_set(ScrnInfoPtr scrn, uint32_t format, uint64_t **modifiers,
     return count_modifiers;
 }
 
+static Bool
+get_drawable_modifiers(DrawablePtr draw, uint32_t format,
+                       uint32_t *num_modifiers, uint64_t **modifiers)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
+    modesettingPtr ms = modesettingPTR(scrn);
+
+    if (!present_can_window_flip((WindowPtr) draw) ||
+        !ms->drmmode.pageflip || ms->drmmode.dri2_flipping || !scrn->vtSema) {
+        *num_modifiers = 0;
+        *modifiers = NULL;
+        return TRUE;
+    }
+
+    *num_modifiers = get_modifiers_set(scrn, format, modifiers, TRUE, FALSE);
+    return TRUE;
+}
+
 static Bool
 drmmode_zaphod_string_matches(ScrnInfoPtr scrn, const char *s, char *output_name)
 {
@@ -2940,6 +2959,23 @@ drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
     return TRUE;
 }
 
+Bool
+drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+{
+#ifdef GLAMOR_HAS_GBM
+    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
+
+    if (drmmode->glamor) {
+        if (!glamor_init(pScreen, GLAMOR_USE_EGL_SCREEN)) {
+            return FALSE;
+        }
+        glamor_set_drawable_modifiers_func(pScreen, get_drawable_modifiers);
+    }
+#endif
+
+    return TRUE;
+}
+
 void
 drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
 {
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 52015c5df..923e1aa6e 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -256,6 +256,7 @@ Bool drmmode_SharedPixmapFlip(PixmapPtr frontTarget, xf86CrtcPtr crtc,
 void drmmode_DisableSharedPixmapFlipping(xf86CrtcPtr crtc, drmmode_ptr drmmode);
 
 extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp);
+extern Bool drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
 void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y);
 extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw);
 extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 774a18893..72e2625fb 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -407,19 +407,6 @@ xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
 static void
 xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
 {
-   struct xwl_screen *xwl_screen = data;
-
-   switch (format) {
-   case WL_DRM_FORMAT_ARGB8888:
-      xwl_screen->formats |= XWL_FORMAT_ARGB8888;
-      break;
-   case WL_DRM_FORMAT_XRGB8888:
-      xwl_screen->formats |= XWL_FORMAT_XRGB8888;
-      break;
-   case WL_DRM_FORMAT_RGB565:
-      xwl_screen->formats |= XWL_FORMAT_RGB565;
-      break;
-   }
 }
 
 static void
@@ -446,6 +433,54 @@ static const struct wl_drm_listener xwl_drm_listener = {
     xwl_drm_handle_capabilities
 };
 
+static void
+xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
+                         uint32_t format)
+{
+}
+
+static void
+xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
+                           uint32_t format, uint32_t modifier_hi,
+                           uint32_t modifier_lo)
+{
+   struct xwl_screen *xwl_screen = data;
+    struct xwl_format *xwl_format = NULL;
+    int i;
+
+    for (i = 0; i < xwl_screen->num_formats; i++) {
+        if (xwl_screen->formats[i].format == format) {
+            xwl_format = &xwl_screen->formats[i];
+            break;
+        }
+    }
+
+    if (xwl_format == NULL) {
+       xwl_screen->num_formats++;
+       xwl_screen->formats = realloc(xwl_screen->formats,
+                                     xwl_screen->num_formats * sizeof(*xwl_format));
+       if (!xwl_screen->formats)
+          return;
+       xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
+       xwl_format->format = format;
+       xwl_format->num_modifiers = 0;
+       xwl_format->modifiers = NULL;
+    }
+
+    xwl_format->num_modifiers++;
+    xwl_format->modifiers = realloc(xwl_format->modifiers,
+                                    xwl_format->num_modifiers * sizeof(uint64_t));
+    if (!xwl_format->modifiers)
+       return;
+    xwl_format->modifiers[xwl_format->num_modifiers - 1]  = (uint64_t) modifier_lo;
+    xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
+}
+
+static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
+    .format   = xwl_dmabuf_handle_format,
+    .modifier = xwl_dmabuf_handle_modifier
+};
+
 Bool
 xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
                              uint32_t id, uint32_t version)
@@ -470,6 +505,7 @@ xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
 
     xwl_screen->dmabuf =
         wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
+    zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf, &xwl_dmabuf_listener, xwl_screen);
 
     return TRUE;
 }
@@ -678,12 +714,85 @@ glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
 #endif
 }
 
+_X_EXPORT Bool
+glamor_get_formats(ScreenPtr screen,
+                   CARD32 *num_formats, CARD32 **formats)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    int i;
+
+    if (!xwl_screen->dmabuf_capable || !xwl_screen->dmabuf)
+        return FALSE;
+
+    if (xwl_screen->num_formats == 0) {
+       *num_formats = 0;
+       return TRUE;
+    }
+
+    *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
+    if (*formats == NULL) {
+        *num_formats = 0;
+        return FALSE;
+    }
+
+    for (i = 0; i < xwl_screen->num_formats; i++)
+       (*formats)[i] = xwl_screen->formats[i].format;
+    *num_formats = xwl_screen->num_formats;
+
+    return TRUE;
+}
+
+_X_EXPORT Bool
+glamor_get_modifiers(ScreenPtr screen, CARD32 format,
+                     CARD32 *num_modifiers, uint64_t **modifiers)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_format *xwl_format = NULL;
+    int i;
+
+    if (!xwl_screen->dmabuf_capable || !xwl_screen->dmabuf)
+        return FALSE;
+
+    if (xwl_screen->num_formats == 0) {
+       *num_modifiers = 0;
+       return TRUE;
+    }
+
+    for (i = 0; i < xwl_screen->num_formats; i++) {
+       if (xwl_screen->formats[i].format == format) {
+          xwl_format = &xwl_screen->formats[i];
+          break;
+       }
+    }
+
+    if (!xwl_format) {
+	*num_modifiers = 0;
+        return FALSE;
+    }
+
+    *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
+    if (*modifiers == NULL) {
+        *num_modifiers = 0;
+        return FALSE;
+    }
+
+    for (i = 0; i < xwl_format->num_modifiers; i++)
+       (*modifiers)[i] = xwl_format->modifiers[i];
+    *num_modifiers = xwl_format->num_modifiers;
+
+    return TRUE;
+}
+
+
 static dri3_screen_info_rec xwl_dri3_info = {
     .version = 2,
     .open = NULL,
     .pixmap_from_fds = glamor_pixmap_from_fds,
     .fds_from_pixmap = glamor_fds_from_pixmap,
     .open_client = xwl_dri3_open_client,
+    .get_formats = glamor_get_formats,
+    .get_modifiers = glamor_get_modifiers,
+    .get_drawable_modifiers = glamor_get_drawable_modifiers,
 };
 
 Bool
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index be95bab55..36ebeaa83 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -49,6 +49,12 @@
 #include "xdg-output-unstable-v1-client-protocol.h"
 #include "linux-dmabuf-unstable-v1-client-protocol.h"
 
+struct xwl_format {
+    uint32_t format;
+    int num_modifiers;
+    uint64_t *modifiers;
+};
+
 struct xwl_screen {
     int width;
     int height;
@@ -100,7 +106,8 @@ struct xwl_screen {
     int drm_authenticated;
     struct wl_drm *drm;
     struct zwp_linux_dmabuf_v1 *dmabuf;
-    uint32_t formats;
+    uint32_t num_formats;
+    struct xwl_format *formats;
     uint32_t capabilities;
     void *egl_display, *egl_context;
     struct gbm_device *gbm;
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index ea932c46d..58585724c 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -500,6 +500,9 @@
 /* Glamor can retrieve supported DRM formats/modifiers */
 #undef GLAMOR_HAS_DRM_MODIFIERS
 
+/* Glamor can use eglQueryDmaBuf* functions */
+#undef GLAMOR_HAS_EGL_QUERY_DMABUF
+
 /* byte order */
 #undef X_BYTE_ORDER
 
diff --git a/include/meson.build b/include/meson.build
index 8d9b6278e..c157dad10 100644
--- a/include/meson.build
+++ b/include/meson.build
@@ -80,6 +80,8 @@ conf_data.set('GLAMOR_HAS_DRM_NAME_FROM_FD_2',
               libdrm_dep.found() and libdrm_dep.version().version_compare('>= 2.4.74'))
 conf_data.set('GLAMOR_HAS_DRM_MODIFIERS',
               libdrm_dep.found() and libdrm_dep.version().version_compare('>= 2.4.83'))
+conf_data.set('GLAMOR_HAS_EGL_QUERY_DMABUF',
+              epoxy_dep.found() and epoxy_dep.version().version_compare('>= 1.4.4'))
 conf_data.set('GLXEXT', build_glx)
 conf_data.set('GLAMOR', build_glamor)
 conf_data.set('GLAMOR_HAS_GBM', gbm_dep.found())
diff --git a/meson.build b/meson.build
index 01eddaac3..6e780d94e 100644
--- a/meson.build
+++ b/meson.build
@@ -263,9 +263,11 @@ else
     build_glamor = get_option('glamor') == 'true'
 endif
 
-gbm_dep = dependency('', required:false)
+gbm_dep = dependency('', required: false)
+epoxy_dep = dependency('', required: false)
 if build_glamor
     gbm_dep = dependency('gbm', version: '>= 10.2', required: false)
+    epoxy_dep = dependency('epoxy', required: false)
 endif
 
 # XXX: Add more sha1 options, because Linux is about choice
diff --git a/present/present.c b/present/present.c
index 42e5fb4fc..080cafcba 100644
--- a/present/present.c
+++ b/present/present.c
@@ -614,6 +614,44 @@ present_check_flip_window (WindowPtr window)
     }
 }
 
+Bool
+present_can_window_flip(WindowPtr window)
+{
+    ScreenPtr                   screen = window->drawable.pScreen;
+    PixmapPtr                   window_pixmap;
+    WindowPtr                   root = screen->root;
+    present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
+
+    if (!screen_priv)
+        return FALSE;
+
+    if (!screen_priv->info)
+        return FALSE;
+
+    /* Check to see if the driver supports flips at all */
+    if (!screen_priv->info->flip)
+        return FALSE;
+
+    /* Make sure the window hasn't been redirected with Composite */
+    window_pixmap = screen->GetWindowPixmap(window);
+    if (window_pixmap != screen->GetScreenPixmap(screen) &&
+        window_pixmap != screen_priv->flip_pixmap &&
+        window_pixmap != present_flip_pending_pixmap(screen))
+        return FALSE;
+
+    /* Check for full-screen window */
+    if (!RegionEqual(&window->clipList, &root->winSize)) {
+        return FALSE;
+    }
+
+    /* Does the window match the pixmap exactly? */
+    if (window->drawable.x != 0 || window->drawable.y != 0) {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 /*
  * Called when the wait fence is triggered; just gets the current msc/ust and
  * calls present_execute again. That will re-check the fence and pend the
diff --git a/present/present.h b/present/present.h
index 6542dc385..ade838bda 100644
--- a/present/present.h
+++ b/present/present.h
@@ -135,4 +135,7 @@ typedef void (*present_complete_notify_proc)(WindowPtr window,
 extern _X_EXPORT void
 present_register_complete_notify(present_complete_notify_proc proc);
 
+extern _X_EXPORT Bool
+present_can_window_flip(WindowPtr window);
+
 #endif /* _PRESENT_H_ */
-- 
2.14.3



More information about the xorg-devel mailing list