From b196e1a8cfbd2c6b53f688542bcda5bb8f7f8888 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sat, 9 Nov 2019 00:02:54 +0100 Subject: [PATCH] gallium: Fix the ->set_damage_region() implementation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit BACK_LEFT attachment can be outdated when the user calls KHR_partial_update() (->lastStamp != ->texture_stamp), leading to a damage region update on the wrong pipe_resource object. Let's delay the ->set_damage_region() call until the attachments are updated when we're in that case. Reported-by: Carsten Haitzler Fixes: 492ffbed63a2 ("st/dri2: Implement DRI2bufferDamageExtension") Cc: Signed-off-by: Boris Brezillon Reviewed-by: Marek Olšák --- src/gallium/state_trackers/dri/dri2.c | 23 +++++++++++++++---- src/gallium/state_trackers/dri/dri_drawable.c | 13 +++++++++++ src/gallium/state_trackers/dri/dri_drawable.h | 3 +++ 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c index 620a972917a..d62cf89f737 100644 --- a/src/gallium/state_trackers/dri/dri2.c +++ b/src/gallium/state_trackers/dri/dri2.c @@ -1879,8 +1879,6 @@ static void dri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects) { struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_resource *resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - struct pipe_screen *screen = resource->screen; struct pipe_box *boxes = NULL; if (nrects) { @@ -1894,8 +1892,25 @@ dri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects) } } - screen->set_damage_region(screen, resource, nrects, boxes); - FREE(boxes); + FREE(drawable->damage_rects); + drawable->damage_rects = boxes; + drawable->num_damage_rects = nrects; + + /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */ + if (drawable->texture_stamp == drawable->dPriv->lastStamp && + (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) { + struct pipe_screen *screen = drawable->screen->base.screen; + struct pipe_resource *resource; + + if (drawable->stvis.samples > 1) + resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; + else + resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + + screen->set_damage_region(screen, resource, + drawable->num_damage_rects, + drawable->damage_rects); + } } static __DRI2bufferDamageExtension dri2BufferDamageExtension = { diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 4b0ba5f6719..88eb6c01c1b 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -92,6 +92,18 @@ dri_st_framebuffer_validate(struct st_context_iface *stctx, } } while (lastStamp != drawable->dPriv->lastStamp); + /* Flush the pending set_damage_region request. */ + struct pipe_screen *pscreen = screen->base.screen; + + if (new_mask & (1 << ST_ATTACHMENT_BACK_LEFT) && + pscreen->set_damage_region) { + struct pipe_resource *resource = textures[ST_ATTACHMENT_BACK_LEFT]; + + pscreen->set_damage_region(pscreen, resource, + drawable->num_damage_rects, + drawable->damage_rects); + } + if (!out) return true; @@ -197,6 +209,7 @@ dri_destroy_buffer(__DRIdrawable * dPriv) /* Notify the st manager that this drawable is no longer valid */ stapi->destroy_drawable(stapi, &drawable->base); + FREE(drawable->damage_rects); FREE(drawable); } diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h index 05c82056697..d57ff1d84e0 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.h +++ b/src/gallium/state_trackers/dri/dri_drawable.h @@ -52,6 +52,9 @@ struct dri_drawable unsigned old_w; unsigned old_h; + struct pipe_box *damage_rects; + unsigned int num_damage_rects; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; unsigned int texture_mask, texture_stamp; -- 2.30.2