Mesa (main): kopper: Implement {EGL,GLX}_EXT_buffer_age
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Jul 18 20:13:43 UTC 2022
Module: Mesa
Branch: main
Commit: c123ab213797c1d0d2a34e57c503428261324cc6
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=c123ab213797c1d0d2a34e57c503428261324cc6
Author: Adam Jackson <ajax at redhat.com>
Date: Tue Jul 12 14:26:15 2022 -0400
kopper: Implement {EGL,GLX}_EXT_buffer_age
Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17527>
---
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;
More information about the mesa-commit
mailing list