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>
This commit is contained in:
Chris Wilson 2012-12-14 23:48:00 +00:00
parent 9df9585cb0
commit 6593ad3fec
1 changed files with 42 additions and 23 deletions

View File

@ -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;
}
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(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);
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;
}