From abec42c9a300b431751a940679628218b73ea016 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 13 May 2021 18:38:50 +0000 Subject: [PATCH] gallium/dri: implement EGL_KHR_mutable_render_buffer Tested with low-lantency stylus apps with this extension enabled, no regression on the cts. Signed-off-by: Yiwei Zhang Reviewed-by: Emma Anholt Part-of: --- src/gallium/frontends/dri/dri2.c | 53 ++++++++++++++++++++----- src/gallium/frontends/dri/dri_context.h | 6 +++ src/gallium/frontends/dri/dri_screen.h | 2 +- 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c index 0a84e0f2c9c..b664ad0dbe9 100644 --- a/src/gallium/frontends/dri/dri2.c +++ b/src/gallium/frontends/dri/dri2.c @@ -506,6 +506,21 @@ dri2_allocate_textures(struct dri_context *ctx, pipe_resource_reference(buf, texture); } + if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + struct pipe_resource *texture = images.back->texture; + + dri_drawable->w = texture->width0; + dri_drawable->h = texture->height0; + + pipe_resource_reference(buf, texture); + + ctx->is_shared_buffer_bound = true; + } else { + ctx->is_shared_buffer_bound = false; + } + /* Note: if there is both a back and a front buffer, * then they have the same size. */ @@ -680,26 +695,41 @@ dri2_flush_frontbuffer(struct dri_context *ctx, __DRIdrawable *dri_drawable = drawable->dPriv; const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; + const __DRImutableRenderBufferLoaderExtension *shared_buffer_loader = + drawable->sPriv->mutableRenderBuffer.loader; struct pipe_context *pipe = ctx->st->pipe; + struct pipe_fence_handle *fence = NULL; + int fence_fd = -1; - if (statt != ST_ATTACHMENT_FRONT_LEFT) - return false; + /* We need to flush for front buffer rendering when either we're using the + * front buffer at the GL API level, or when EGL_KHR_mutable_render_buffer + * has redirected GL_BACK to the front buffer. + */ + if (statt != ST_ATTACHMENT_FRONT_LEFT && + (!ctx->is_shared_buffer_bound || statt != ST_ATTACHMENT_BACK_LEFT)) + return false; if (drawable->stvis.samples > 1) { - /* Resolve the front buffer. */ - dri_pipe_blit(ctx->st->pipe, - drawable->textures[ST_ATTACHMENT_FRONT_LEFT], - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); + /* Resolve the buffer used for front rendering. */ + dri_pipe_blit(ctx->st->pipe, drawable->textures[statt], + drawable->msaa_textures[statt]); } - if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) { - pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]); + if (drawable->textures[statt]) { + pipe->flush_resource(pipe, drawable->textures[statt]); } - pipe->flush(pipe, NULL, 0); + pipe->flush(pipe, ctx->is_shared_buffer_bound ? &fence : NULL, 0); if (image) { image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); + if (ctx->is_shared_buffer_bound) { + if (fence) + fence_fd = pipe->screen->fence_get_fd(pipe->screen, fence); + + shared_buffer_loader->displaySharedBuffer(dri_drawable, fence_fd, + dri_drawable->loaderPrivate); + } } else if (loader->flushFrontBuffer) { loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); @@ -2178,6 +2208,10 @@ static const __DRI2blobExtension driBlobExtension = { .set_cache_funcs = set_blob_cache_funcs }; +static const __DRImutableRenderBufferDriverExtension driMutableRenderBufferExtension = { + .base = { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1 }, +}; + /* * Backend function init_screen. */ @@ -2192,6 +2226,7 @@ static const __DRIextension *dri_screen_extensions_base[] = { &dri2InteropExtension.base, &dri2NoErrorExtension.base, &driBlobExtension.base, + &driMutableRenderBufferExtension.base, }; /** diff --git a/src/gallium/frontends/dri/dri_context.h b/src/gallium/frontends/dri/dri_context.h index 96e21e0695c..4b2b045092c 100644 --- a/src/gallium/frontends/dri/dri_context.h +++ b/src/gallium/frontends/dri/dri_context.h @@ -52,6 +52,12 @@ struct dri_context unsigned int bind_count; + /** + * True if the __DRIdrawable's current __DRIimageBufferMask is + * __DRI_IMAGE_BUFFER_SHARED. + */ + bool is_shared_buffer_bound; + /* gallium */ struct st_api *stapi; struct st_context_iface *st; diff --git a/src/gallium/frontends/dri/dri_screen.h b/src/gallium/frontends/dri/dri_screen.h index c967e9416c8..c6c08f9e3ea 100644 --- a/src/gallium/frontends/dri/dri_screen.h +++ b/src/gallium/frontends/dri/dri_screen.h @@ -87,7 +87,7 @@ struct dri_screen __DRI2bufferDamageExtension buffer_damage_extension; /* DRI exts on this screen. Populated at init time based on device caps. */ - const __DRIextension *screen_extensions[13]; + const __DRIextension *screen_extensions[14]; /* OpenCL interop */ mtx_t opencl_func_mutex;