From 87f7ec8a2ca393100bddb37f0b83488d7c158d4d Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Wed, 27 Nov 2019 11:25:40 +0100 Subject: [PATCH] st/dri: use st->flush callback to flush the backbuffer MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Previously the flush was done before the call to st->flush but could lead to problems as FLUSH_VERTICES could push some work that would change the backbuffer (or modify it). With this commit, all the backbuffer flushing code is executed right before the call to st_flush. Closes: https://gitlab.freedesktop.org/drm/amd/issues/842 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=205049 Reviewed-by: Marek Olšák --- src/gallium/state_trackers/dri/dri_drawable.c | 102 ++++++++++++++++---------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 64eed15..2ee4f18 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -404,6 +404,56 @@ dri_postprocessing(struct dri_context *ctx, pp_run(ctx->pp, src, src, zsbuf); } +struct notify_before_flush_cb_args { + struct dri_context *ctx; + struct dri_drawable *drawable; + unsigned flags; + enum __DRI2throttleReason reason; + bool swap_msaa_buffers; +}; + +static void +notify_before_flush_cb(void* _args) +{ + struct notify_before_flush_cb_args *args = (struct notify_before_flush_cb_args *) _args; + struct st_context_iface *st = args->ctx->st; + struct pipe_context *pipe = st->pipe; + + if (args->drawable->stvis.samples > 1 && + (args->reason == __DRI2_THROTTLE_SWAPBUFFER || + args->reason == __DRI2_THROTTLE_COPYSUBBUFFER)) { + /* Resolve the MSAA back buffer. */ + dri_pipe_blit(st->pipe, + args->drawable->textures[ST_ATTACHMENT_BACK_LEFT], + args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); + + if (args->reason == __DRI2_THROTTLE_SWAPBUFFER && + args->drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && + args->drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { + args->swap_msaa_buffers = true; + } + + /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ + } + + dri_postprocessing(args->ctx, args->drawable, ST_ATTACHMENT_BACK_LEFT); + + if (pipe->invalidate_resource && + (args->flags & __DRI2_FLUSH_INVALIDATE_ANCILLARY)) { + if (args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) + pipe->invalidate_resource(pipe, args->drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); + if (args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]) + pipe->invalidate_resource(pipe, args->drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]); + } + + if (args->ctx->hud) { + hud_run(args->ctx->hud, args->ctx->st->cso_context, + args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); + } + + pipe->flush_resource(pipe, args->drawable->textures[ST_ATTACHMENT_BACK_LEFT]); +} + /** * DRI2 flush extension, the flush_with_flags function. * @@ -422,7 +472,7 @@ dri_flush(__DRIcontext *cPriv, struct dri_drawable *drawable = dri_drawable(dPriv); struct st_context_iface *st; unsigned flush_flags; - bool swap_msaa_buffers = false; + struct notify_before_flush_cb_args args = { 0 }; if (!ctx) { assert(0); @@ -444,44 +494,18 @@ dri_flush(__DRIcontext *cPriv, flags &= ~__DRI2_FLUSH_DRAWABLE; } - /* Flush the drawable. */ if ((flags & __DRI2_FLUSH_DRAWABLE) && drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { - struct pipe_context *pipe = st->pipe; - - if (drawable->stvis.samples > 1 && - (reason == __DRI2_THROTTLE_SWAPBUFFER || - reason == __DRI2_THROTTLE_COPYSUBBUFFER)) { - /* Resolve the MSAA back buffer. */ - dri_pipe_blit(st->pipe, - drawable->textures[ST_ATTACHMENT_BACK_LEFT], - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); - - if (reason == __DRI2_THROTTLE_SWAPBUFFER && - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { - swap_msaa_buffers = true; - } - - /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ - } - - dri_postprocessing(ctx, drawable, ST_ATTACHMENT_BACK_LEFT); - - if (pipe->invalidate_resource && - (flags & __DRI2_FLUSH_INVALIDATE_ANCILLARY)) { - if (drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) - pipe->invalidate_resource(pipe, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); - if (drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]) - pipe->invalidate_resource(pipe, drawable->msaa_textures[ST_ATTACHMENT_DEPTH_STENCIL]); - } - - if (ctx->hud) { - hud_run(ctx->hud, ctx->st->cso_context, - drawable->textures[ST_ATTACHMENT_BACK_LEFT]); - } - - pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); + /* We can't do operations on the back buffer here, because there + * may be some pending operations that will get flushed by the + * call to st->flush (eg: FLUSH_VERTICES). + * Instead we register a callback to be notified when all operations + * have been submitted but before the call to st_flush. + */ + args.ctx = ctx; + args.drawable = drawable; + args.flags = flags; + args.reason = reason; } flush_flags = 0; @@ -509,7 +533,7 @@ dri_flush(__DRIcontext *cPriv, drawable->throttle_fence = new_fence; } else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { - st->flush(st, flush_flags, NULL, NULL, NULL); + st->flush(st, flush_flags, NULL, args.ctx ? notify_before_flush_cb : NULL, &args); } if (drawable) { @@ -520,7 +544,7 @@ dri_flush(__DRIcontext *cPriv, * from the front buffer after SwapBuffers returns what was * in the back buffer. */ - if (swap_msaa_buffers) { + if (args.swap_msaa_buffers) { struct pipe_resource *tmp = drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; -- 2.7.4