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