diff --git a/src/gallium/frontends/dri/dri_drawable.c b/src/gallium/frontends/dri/dri_drawable.c index c9099671fbd..46275ba921a 100644 --- a/src/gallium/frontends/dri/dri_drawable.c +++ b/src/gallium/frontends/dri/dri_drawable.c @@ -212,6 +212,9 @@ dri_destroy_drawable(struct dri_drawable *drawable) /* Notify the st manager that this drawable is no longer valid */ st_api_destroy_drawable(&drawable->base); + if (screen->type == DRI_SCREEN_KOPPER) + kopper_destroy_drawable(drawable); + FREE(drawable->damage_rects); FREE(drawable); } diff --git a/src/gallium/frontends/dri/dri_drawable.h b/src/gallium/frontends/dri/dri_drawable.h index f66942cafce..1d27771c35f 100644 --- a/src/gallium/frontends/dri/dri_drawable.h +++ b/src/gallium/frontends/dri/dri_drawable.h @@ -33,6 +33,10 @@ #include "frontend/api.h" #include "dri_util.h" +#ifdef VK_USE_PLATFORM_XCB_KHR +#include +#endif + struct pipe_context; struct dri_context; struct dri_screen; @@ -93,6 +97,9 @@ struct dri_drawable struct dri_image *image; //texture_from_pixmap bool is_window; bool window_valid; +#ifdef VK_USE_PLATFORM_XCB_KHR + xcb_special_event_t *special_event; +#endif /* hooks filled in by dri2 & drisw */ void (*allocate_textures)(struct dri_context *ctx, @@ -161,6 +168,8 @@ void drisw_init_drawable(struct dri_drawable *drawable, bool isPixmap, int alphaBits); void dri2_init_drawable(struct dri_drawable *drawable, bool isPixmap, int alphaBits); +void +kopper_destroy_drawable(struct dri_drawable *drawable); #endif /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/dri_util.h b/src/gallium/frontends/dri/dri_util.h index 9f059c37ad8..7458575bf25 100644 --- a/src/gallium/frontends/dri/dri_util.h +++ b/src/gallium/frontends/dri/dri_util.h @@ -167,6 +167,10 @@ kopperQueryBufferAge(struct dri_drawable *drawable); PUBLIC void driswCopySubBuffer(struct dri_drawable *drawable, int x, int y, int w, int h); +PUBLIC int +kopperGetSyncValues(struct dri_drawable *drawable, int64_t target_msc, int64_t divisor, + int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc); + PUBLIC void dri_set_tex_buffer2(struct dri_context *ctx, GLint target, GLint format, struct dri_drawable *drawable); diff --git a/src/gallium/frontends/dri/kopper.c b/src/gallium/frontends/dri/kopper.c index 1ec930e3893..99916e231d7 100644 --- a/src/gallium/frontends/dri/kopper.c +++ b/src/gallium/frontends/dri/kopper.c @@ -523,6 +523,34 @@ kopper_init_drawable(struct dri_drawable *drawable, bool isPixmap, int alphaBits screen->kopper_loader->SetSurfaceCreateInfo(drawable->loaderPrivate, &drawable->info); drawable->is_window = !isPixmap && drawable->info.bos.sType != 0; + +#ifdef VK_USE_PLATFORM_XCB_KHR + if (drawable->info.bos.sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) { + VkXcbSurfaceCreateInfoKHR *xcb = (VkXcbSurfaceCreateInfoKHR *)&drawable->info.bos; + xcb_connection_t *conn = xcb->connection; + + int32_t eid = xcb_generate_id(conn); + if (drawable->is_window) { + xcb_present_select_input(conn, eid, xcb->window, + XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY); + } + + drawable->special_event = + xcb_register_for_special_xge(conn, &xcb_present_id, eid, NULL); + } +#endif +} + +void +kopper_destroy_drawable(struct dri_drawable *drawable) +{ +#ifdef VK_USE_PLATFORM_XCB_KHR + if (drawable->info.bos.sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR) { + VkXcbSurfaceCreateInfoKHR *xcb = (VkXcbSurfaceCreateInfoKHR *)&drawable->info.bos; + xcb_connection_t *conn = xcb->connection; + xcb_unregister_for_special_event(conn, drawable->special_event); + } +#endif } int64_t @@ -639,5 +667,55 @@ kopperQueryBufferAge(struct dri_drawable *drawable) return zink_kopper_query_buffer_age(ctx->st->pipe, ptex); } +int +kopperGetSyncValues(struct dri_drawable *drawable, int64_t target_msc, int64_t divisor, + int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) +{ +#ifdef VK_USE_PLATFORM_XCB_KHR + struct kopper_loader_info *info = &drawable->info; + + assert(info->bos.sType == VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR); + + VkXcbSurfaceCreateInfoKHR *xcb = (VkXcbSurfaceCreateInfoKHR *)&info->bos; + xcb_connection_t *conn = xcb->connection; + + xcb_void_cookie_t cookie = + xcb_present_notify_msc(conn, xcb->window, 0, target_msc, divisor, remainder); + + xcb_generic_event_t *event; + int ret = 0; + + xcb_flush(conn); + + while ((event = xcb_wait_for_special_event(conn, drawable->special_event)) != NULL) { + xcb_present_generic_event_t *ev = (xcb_present_generic_event_t *)event; + if (ev->evtype == XCB_PRESENT_COMPLETE_NOTIFY) { + xcb_present_complete_notify_event_t *ce = + (xcb_present_complete_notify_event_t *) event; + + if (ce->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC) { + *ust = ce->ust; + *msc = ce->msc; + *sbc = ce->serial; + + if (event->full_sequence != cookie.sequence) { + free(event); + continue; + } + + ret = 1; + free(event); + break; + } + } + + free(event); + } + + return ret; +#else + return 0; +#endif +} /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/frontends/dri/kopper_stubs.c b/src/gallium/frontends/dri/kopper_stubs.c index fdb92bf610b..efa442ecc2e 100644 --- a/src/gallium/frontends/dri/kopper_stubs.c +++ b/src/gallium/frontends/dri/kopper_stubs.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: MIT */ +#include "dri_drawable.h" #include "dri_util.h" int64_t @@ -25,6 +26,13 @@ kopperQueryBufferAge(struct dri_drawable *dPriv) return 0; } +int +kopperGetSyncValues(struct dri_drawable *drawable, int64_t target_msc, int64_t divisor, + int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) +{ + return 0; +} + const struct dri_config ** kopper_init_screen(struct dri_screen *screen, bool driver_name_is_inferred); const struct dri_config ** @@ -40,3 +48,10 @@ void kopper_init_drawable(struct dri_drawable *drawable, bool isPixmap, int alphaBits) { } + +void +kopper_destroy_drawable(struct dri_drawable *drawable); +void +kopper_destroy_drawable(struct dri_drawable *drawable) +{ +} diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c index 26f7569a5c7..b5ba0cdd4fc 100644 --- a/src/glx/drisw_glx.c +++ b/src/glx/drisw_glx.c @@ -619,6 +619,21 @@ kopperGetSwapInterval(__GLXDRIdrawable *pdraw) return pdp->swapInterval; } +static int +kopperWaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, + int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc) +{ + return kopperGetSyncValues(pdraw->dri_drawable, target_msc, divisor, remainder, ust, msc, sbc); +} + +static int +kopperGetDrawableMSC(struct glx_screen *psc, __GLXDRIdrawable *pdraw, + int64_t *ust, int64_t *msc, int64_t *sbc) +{ + return kopperGetSyncValues(pdraw->dri_drawable, 0, 0, 0, ust, msc, sbc); +} + + struct glx_screen * driswCreateScreen(int screen, struct glx_display *priv, enum glx_driver glx_driver, bool driver_name_is_inferred) { @@ -670,6 +685,8 @@ driswCreateScreen(int screen, struct glx_display *priv, enum glx_driver glx_driv psp->setSwapInterval = driswKopperSetSwapInterval; psp->getSwapInterval = kopperGetSwapInterval; psp->maxSwapInterval = 1; + psp->getDrawableMSC = kopperGetDrawableMSC; + psp->waitForMSC = kopperWaitForMSC; } return &psc->base;