From cef12efc15ca1444d6d8cd839116b318a4668692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Louis-Francis=20Ratt=C3=A9-Boulianne?= Date: Wed, 28 Feb 2018 01:19:44 +0000 Subject: [PATCH] glamor: Implement GetSupportedModifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Daniel Stone Acked-by: Keith Packard Reviewed-by: Adam Jackson --- 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 +- .../drivers/modesetting/drmmode_display.c | 38 +++++ .../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, 372 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 773567b53..f82c0a66a 100644 --- a/configure.ac +++ b/configure.ac @@ -2087,6 +2087,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 c890d0ce0..c7077dd84 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 cf2513491..c00fb3c1b 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -505,6 +505,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) { @@ -626,6 +715,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 31e167387..b48afd612 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 #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 88a42257c..f20284bb0 100644 --- a/hw/xfree86/drivers/modesetting/driver.c +++ b/hw/xfree86/drivers/modesetting/driver.c @@ -1601,15 +1601,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 1f7a9fd0a..1027e637a 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.c +++ b/hw/xfree86/drivers/modesetting/drmmode_display.c @@ -45,6 +45,7 @@ #include #include "xf86Crtc.h" #include "drmmode_display.h" +#include "present.h" #include @@ -175,6 +176,24 @@ get_modifiers_set(ScrnInfoPtr scrn, uint32_t format, uint64_t **modifiers, *modifiers = ret; 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; +} #endif static Bool @@ -3121,6 +3140,25 @@ 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; + } +#ifdef GBM_BO_WITH_MODIFIERS + glamor_set_drawable_modifiers_func(pScreen, get_drawable_modifiers); +#endif + } +#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 607fe8179..ee59711cb 100644 --- a/hw/xfree86/drivers/modesetting/drmmode_display.h +++ b/hw/xfree86/drivers/modesetting/drmmode_display.h @@ -263,6 +263,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 c39c00420..e6abf22f8 100644 --- a/include/meson.build +++ b/include/meson.build @@ -79,6 +79,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 d64fb0ca3..3579d078a 100644 --- a/meson.build +++ b/meson.build @@ -262,9 +262,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_ */