kopper: Implement {EGL,GLX}_EXT_buffer_age

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17527>
This commit is contained in:
Adam Jackson 2022-07-12 14:26:15 -04:00 committed by Marge Bot
parent 81d83e81db
commit c123ab2137
6 changed files with 83 additions and 0 deletions

View File

@ -75,6 +75,7 @@ struct __DRIkopperExtensionRec {
int pixmap);
int64_t (*swapBuffers)(__DRIdrawable *draw);
void (*setSwapInterval)(__DRIdrawable *drawable, int interval);
int (*queryBufferAge)(__DRIdrawable *drawable);
};
/**

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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 = {

View File

@ -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;