From c123ab213797c1d0d2a34e57c503428261324cc6 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 12 Jul 2022 14:26:15 -0400 Subject: [PATCH] kopper: Implement {EGL,GLX}_EXT_buffer_age Reviewed-by: Mike Blumenkrantz Part-of: --- include/kopper_interface.h | 1 + src/egl/drivers/dri2/platform_x11.c | 14 ++++++++++ src/gallium/drivers/zink/zink_kopper.c | 36 ++++++++++++++++++++++++++ src/gallium/drivers/zink/zink_kopper.h | 3 +++ src/gallium/frontends/dri/kopper.c | 13 ++++++++++ src/glx/drisw_glx.c | 16 ++++++++++++ 6 files changed, 83 insertions(+) diff --git a/include/kopper_interface.h b/include/kopper_interface.h index f5db825f425..665d17f6164 100644 --- a/include/kopper_interface.h +++ b/include/kopper_interface.h @@ -75,6 +75,7 @@ struct __DRIkopperExtensionRec { int pixmap); int64_t (*swapBuffers)(__DRIdrawable *draw); void (*setSwapInterval)(__DRIdrawable *drawable, int interval); + int (*queryBufferAge)(__DRIdrawable *drawable); }; /** diff --git a/src/egl/drivers/dri2/platform_x11.c b/src/egl/drivers/dri2/platform_x11.c index 53302981fc2..7165b740710 100644 --- a/src/egl/drivers/dri2/platform_x11.c +++ b/src/egl/drivers/dri2/platform_x11.c @@ -1230,6 +1230,19 @@ dri2_kopper_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, return surf; } +static EGLint +dri2_kopper_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); + + /* This can legitimately be null for lavapipe */ + if (dri2_dpy->kopper) + return dri2_dpy->kopper->queryBufferAge(dri2_surf->dri_drawable); + + return 0; +} + static const struct dri2_egl_display_vtbl dri2_x11_swrast_display_vtbl = { .authenticate = NULL, .create_window_surface = dri2_x11_create_window_surface, @@ -1258,6 +1271,7 @@ static const struct dri2_egl_display_vtbl dri2_x11_kopper_display_vtbl = { .swap_buffers_region = dri2_x11_swap_buffers_region, .post_sub_buffer = dri2_x11_post_sub_buffer, .copy_buffers = dri2_x11_copy_buffers, + .query_buffer_age = dri2_kopper_query_buffer_age, /* XXX: should really implement this since X11 has pixmaps */ .query_surface = dri2_query_surface, .get_dri_drawable = dri2_surface_get_dri_drawable, diff --git a/src/gallium/drivers/zink/zink_kopper.c b/src/gallium/drivers/zink/zink_kopper.c index be547ade0c2..95963e296a3 100644 --- a/src/gallium/drivers/zink/zink_kopper.c +++ b/src/gallium/drivers/zink/zink_kopper.c @@ -736,6 +736,22 @@ zink_kopper_present_queue(struct zink_screen *screen, struct zink_resource *res) cpi->info.pImageIndices = &cpi->image; cpi->info.pResults = NULL; res->obj->present = VK_NULL_HANDLE; + /* Ex GLX_EXT_buffer_age: + * + * Buffers' ages are initialized to 0 at buffer creation time. + * When a frame boundary is reached, the following occurs before + * any exchanging or copying of color buffers: + * + * * The current back buffer's age is set to 1. + * * Any other color buffers' ages are incremented by 1 if + * their age was previously greater than 0. + */ + for (int i = 0; i < cdt->swapchain->num_images; i++) { + if (i == res->obj->dt_idx) + cdt->swapchain->images[i].age = 1; + else if (cdt->swapchain->images[i].age > 0) + cdt->swapchain->images[i].age += 1; + } if (util_queue_is_initialized(&screen->flush_queue)) { p_atomic_inc(&cpi->swapchain->async_presents); util_queue_add_job(&screen->flush_queue, cpi, &cdt->present_fence, @@ -904,3 +920,23 @@ zink_kopper_set_swap_interval(struct pipe_screen *pscreen, struct pipe_resource if (old_present_mode != cdt->present_mode) update_swapchain(screen, cdt, cdt->caps.currentExtent.width, cdt->caps.currentExtent.height); } + +int +zink_kopper_query_buffer_age(struct pipe_context *pctx, struct pipe_resource *pres) +{ + struct zink_context *ctx = zink_context(pctx); + struct zink_resource *res = zink_resource(pres); + assert(res->obj->dt); + struct kopper_displaytarget *cdt = res->obj->dt; + + ctx = zink_tc_context_unwrap(pctx); + + /* Returning 0 here isn't ideal (yes, the buffer is undefined, because you + * lost it) but threading the error up is more hassle than it's worth. + */ + if (!zink_kopper_acquired(res->obj->dt, res->obj->dt_idx)) + if (!zink_kopper_acquire(ctx, res, UINT64_MAX)) + return 0; + + return cdt->swapchain->images[res->obj->dt_idx].age; +} diff --git a/src/gallium/drivers/zink/zink_kopper.h b/src/gallium/drivers/zink/zink_kopper.h index e570c806275..b5424dedd97 100644 --- a/src/gallium/drivers/zink/zink_kopper.h +++ b/src/gallium/drivers/zink/zink_kopper.h @@ -33,6 +33,7 @@ struct kopper_swapchain_image { bool init; bool acquired; bool dt_has_data; + int age; VkImage image; VkSemaphore acquire; }; @@ -137,4 +138,6 @@ bool zink_kopper_check(struct pipe_resource *pres); void zink_kopper_set_swap_interval(struct pipe_screen *pscreen, struct pipe_resource *pres, int interval); +int +zink_kopper_query_buffer_age(struct pipe_context *pctx, struct pipe_resource *pres); #endif diff --git a/src/gallium/frontends/dri/kopper.c b/src/gallium/frontends/dri/kopper.c index f8ef75d9b9d..0d8d66d91d3 100644 --- a/src/gallium/frontends/dri/kopper.c +++ b/src/gallium/frontends/dri/kopper.c @@ -992,11 +992,24 @@ kopperSetSwapInterval(__DRIdrawable *dPriv, int interval) cdraw->info.initial_swap_interval = interval; } +static int +kopperQueryBufferAge(__DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT] ? + drawable->textures[ST_ATTACHMENT_BACK_LEFT] : + drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + + return zink_kopper_query_buffer_age(ctx->st->pipe, ptex); +} + const __DRIkopperExtension driKopperExtension = { .base = { __DRI_KOPPER, 1 }, .createNewDrawable = kopperCreateNewDrawable, .swapBuffers = kopperSwapBuffers, .setSwapInterval = kopperSetSwapInterval, + .queryBufferAge = kopperQueryBufferAge, }; const struct __DriverAPIRec galliumvk_driver_api = { diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c index cdbcb31289d..5849486c393 100644 --- a/src/glx/drisw_glx.c +++ b/src/glx/drisw_glx.c @@ -528,6 +528,20 @@ drisw_release_tex_image(__GLXDRIdrawable *base, int buffer) } } +static int +kopper_get_buffer_age(__GLXDRIdrawable *pdraw) +{ + struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw; + + if (pdp) { + struct drisw_screen *psc = (struct drisw_screen *) pdraw->psc; + + if (psc->kopper) + return psc->kopper->queryBufferAge(pdp->driDrawable); + } + return 0; +} + static const struct glx_context_vtable drisw_context_vtable = { .destroy = drisw_destroy_context, .bind = drisw_bind_context, @@ -854,6 +868,7 @@ driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions) } if (psc->kopper) { + __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age"); __glXEnableDirectExtension(&psc->base, "GLX_EXT_swap_control"); __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control"); __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control"); @@ -1014,6 +1029,7 @@ driswCreateScreenDriver(int screen, struct glx_display *priv, psp->copySubBuffer = driswCopySubBuffer; if (psc->kopper) { + psp->getBufferAge = kopper_get_buffer_age; psp->setSwapInterval = kopperSetSwapInterval; psp->getSwapInterval = kopperGetSwapInterval; psp->maxSwapInterval = 1;