summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2020-05-06 18:56:39 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2020-05-06 19:03:18 +0100
commite781d43dadde342a7a5b8661b8bf4690b8a1bb6e (patch)
tree1776eba46db4fb4411019c707e4d9ffce44bc1d2
parent846b53dacd96981329bcb9ef348e6acba0b53e94 (diff)
sna/dri2: Prevent copying stale buffers
The back buffer of window/pixmap is invalidated by DRI2ScheduleSwap, and is not available until the client calls DRI2GetBuffers. If they try to use their old handles, they will only get stale data. Similarly if they ask us to DRI2CopyRegion before the GetBuffers has reallocated a new back buffer, that back buffer is stale. Since the back buffer is out-of-date [likely containing data from a couple of swaps ago], we should ignore the copy to avoid glitching [by hopefully having a less noticeable glitch!] It's not entirely clear what the client intended at this point... Closes: https://gitlab.freedesktop.org/xorg/driver/xf86-video-intel/-/issues/195 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_dri2.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index f2f2c1d3..4ee76627 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1421,25 +1421,30 @@ sna_dri2_copy_region(DrawablePtr draw,
PixmapPtr pixmap = get_drawable_pixmap(draw);
struct sna *sna = to_sna_from_pixmap(pixmap);
- DBG(("%s: pixmap=%ld, src=%u (refs=%d/%d, flush=%d, attach=%d) , dst=%u (refs=%d/%d, flush=%d, attach=%d)\n",
+ DBG(("%s: pixmap=%ld, src=%u (attach=%d, refs=%d/%d, flush=%d, stale=%d) , dst=%u (attach=%d, refs=%d/%d, flush=%d, stale=%d)\n",
__FUNCTION__,
pixmap->drawable.serialNumber,
get_private(src)->bo->handle,
+ src->attachment,
get_private(src)->refcnt,
get_private(src)->bo->refcnt,
get_private(src)->bo->flush,
- src->attachment,
+ get_private(src)->stale,
get_private(dst)->bo->handle,
+ dst->attachment,
get_private(dst)->refcnt,
get_private(dst)->bo->refcnt,
get_private(dst)->bo->flush,
- dst->attachment));
+ get_private(dst)->stale));
assert(src != dst);
assert(get_private(src)->refcnt);
assert(get_private(dst)->refcnt);
+ if (get_private(src)->stale)
+ return;
+
assert(get_private(src)->bo != get_private(dst)->bo);
assert(get_private(src)->bo->refcnt);