summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-12-14 23:48:00 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-12-14 23:48:00 +0000
commit6593ad3fecb3d044ee5ca161176d8ecaa0b4126a (patch)
tree7038853c7aa8d6ac17c76ec301325bef384733a6
parent9df9585cb00958b42461b3139bb7aec32090a869 (diff)
sna/dri: Store and check size of front/back bo attached to a DRI2 drawable
So that we can prevent feeding back a stale bo when the DRI2 client tries to swap an old buffer. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=57212 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_dri.c61
1 files changed, 40 insertions, 21 deletions
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index e7e5e35a..c05e8b41 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -100,7 +100,8 @@ struct sna_dri_frame_event {
struct sna_dri_private {
PixmapPtr pixmap;
struct kgem_bo *bo;
- unsigned long serial;
+ bool scanout;
+ uint32_t size;
int refcnt;
};
@@ -241,12 +242,15 @@ sna_dri_create_buffer(DrawablePtr draw,
struct sna_dri_private *private;
PixmapPtr pixmap;
struct kgem_bo *bo;
+ unsigned flags = CREATE_EXACT;
+ uint32_t size;
int bpp;
DBG(("%s(attachment=%d, format=%d, drawable=%dx%d)\n",
__FUNCTION__, attachment, format, draw->width, draw->height));
pixmap = NULL;
+ size = (uint32_t)draw->height << 16 | draw->width;
switch (attachment) {
case DRI2BufferFrontLeft:
pixmap = get_drawable_pixmap(draw);
@@ -279,6 +283,9 @@ sna_dri_create_buffer(DrawablePtr draw,
__FUNCTION__,
pixmap->drawable.width, pixmap->drawable.height,
pixmap, pixmap->refcnt));
+ if (pixmap == sna->front)
+ flags |= CREATE_SCANOUT;
+ size = (uint32_t)pixmap->drawable.height << 16 | pixmap->drawable.width;
break;
case DRI2BufferBackLeft:
@@ -287,12 +294,15 @@ sna_dri_create_buffer(DrawablePtr draw,
case DRI2BufferFakeFrontLeft:
case DRI2BufferFakeFrontRight:
bpp = draw->bitsPerPixel;
+ if (draw->width == sna->front->drawable.width &&
+ draw->height == sna->front->drawable.height)
+ flags |= CREATE_SCANOUT;
bo = kgem_create_2d(&sna->kgem,
draw->width,
draw->height,
draw->bitsPerPixel,
color_tiling(sna, draw),
- CREATE_SCANOUT | CREATE_EXACT);
+ flags);
break;
case DRI2BufferStencil:
@@ -323,7 +333,7 @@ sna_dri_create_buffer(DrawablePtr draw,
bo = kgem_create_2d(&sna->kgem,
ALIGN(draw->width, 64),
ALIGN((draw->height + 1) / 2, 64),
- bpp, I915_TILING_NONE, CREATE_EXACT);
+ bpp, I915_TILING_NONE, flags);
break;
case DRI2BufferDepth:
@@ -334,7 +344,7 @@ sna_dri_create_buffer(DrawablePtr draw,
bo = kgem_create_2d(&sna->kgem,
draw->width, draw->height, bpp,
other_tiling(sna, draw),
- CREATE_EXACT);
+ flags);
break;
default:
@@ -358,7 +368,8 @@ sna_dri_create_buffer(DrawablePtr draw,
private->refcnt = 1;
private->bo = bo;
private->pixmap = pixmap;
- private->serial = get_drawable_pixmap(draw)->drawable.serialNumber;
+ private->scanout = !!(flags & CREATE_SCANOUT);
+ private->size = size;
if (buffer->name == 0)
goto err;
@@ -825,14 +836,14 @@ can_blit(struct sna * sna,
DRI2BufferPtr front,
DRI2BufferPtr back)
{
- PixmapPtr pixmap;
+ uint32_t f, b;
if (draw->type == DRAWABLE_PIXMAP)
return true;
- pixmap = get_drawable_pixmap(draw);
- return (get_private(front)->serial == pixmap->drawable.serialNumber &&
- get_private(back)->serial == pixmap->drawable.serialNumber);
+ f = get_private(front)->size;
+ b = get_private(back)->size;
+ return (f >> 16) >= (b >> 16) && (f & 0xffff) >= (b & 0xffff);
}
static void
@@ -1097,16 +1108,19 @@ can_flip(struct sna * sna,
return false;
}
+ if (!get_private(front)->scanout) {
+ DBG(("%s: no, DRI2 drawable not attached at time of creation)\n",
+ __FUNCTION__));
+ return false;
+ }
assert(get_private(front)->pixmap == sna->front);
- assert(get_private(front)->serial == pixmap->drawable.serialNumber);
- if (get_private(back)->serial != pixmap->drawable.serialNumber) {
- DBG(("%s: no, DRI2 drawable has a stale reference to the pixmap (DRI2 pixmap=%ld, X pixmap=%ld)\n",
- __FUNCTION__,
- get_private(back)->serial,
- pixmap->drawable.serialNumber));
+ if (!get_private(back)->scanout) {
+ DBG(("%s: no, DRI2 drawable was too small at time of creation)\n",
+ __FUNCTION__));
return false;
}
+ assert(get_private(back)->size == get_private(front)->size);
DBG(("%s: window size: %dx%d, clip=(%d, %d), (%d, %d) x %d\n",
__FUNCTION__,
@@ -1203,14 +1217,19 @@ can_exchange(struct sna * sna,
return false;
}
- assert(get_private(front)->serial == pixmap->drawable.serialNumber);
- if (get_private(back)->serial != pixmap->drawable.serialNumber) {
- DBG(("%s: no, DRI2 drawable has a stale reference to the pixmap (DRI2 pixmap=%ld, X pixmap=%ld)\n",
- __FUNCTION__,
- get_private(back)->serial,
- pixmap->drawable.serialNumber));
+ if (!get_private(front)->scanout) {
+ DBG(("%s: no, DRI2 drawable not attached at time of creation)\n",
+ __FUNCTION__));
+ return false;
+ }
+ assert(get_private(front)->pixmap == sna->front);
+
+ if (!get_private(back)->scanout) {
+ DBG(("%s: no, DRI2 drawable was too small at time of creation)\n",
+ __FUNCTION__));
return false;
}
+ assert(get_private(back)->size == get_private(front)->size);
return true;
}