sna/gen3: Apply damage to video pixmap

Reported-by: Paul Neumann <paul104x@yahoo.de>
References: https://bugs.freedesktop.org/show_bug.cgi?id=44504
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-01-24 18:22:12 +00:00
parent ff4b8a03a4
commit 3d1bba033b
3 changed files with 113 additions and 2 deletions

View File

@ -3610,6 +3610,7 @@ gen3_render_video(struct sna *sna,
short drw_w, short drw_h,
PixmapPtr pixmap)
{
struct sna_pixmap *priv = sna_pixmap(pixmap);
BoxPtr pbox = REGION_RECTS(dstRegion);
int nbox = REGION_NUM_RECTS(dstRegion);
int dxo = dstRegion->extents.x1;
@ -3623,7 +3624,7 @@ gen3_render_video(struct sna *sna,
DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__, src_w, src_h, drw_w, drw_h));
dst_bo = sna_pixmap_get_bo(pixmap);
dst_bo = priv->gpu_bo;
if (dst_bo == NULL)
return FALSE;
@ -3721,7 +3722,7 @@ gen3_render_video(struct sna *sna,
#endif
sna_blt_copy_boxes(sna, GXcopy,
dst_bo, -dxo, -dyo,
sna_pixmap_get_bo(pixmap), pix_xoff, pix_yoff,
priv->gpu_bo, pix_xoff, pix_yoff,
pixmap->drawable.bitsPerPixel,
REGION_RECTS(dstRegion),
REGION_NUM_RECTS(dstRegion));
@ -3729,6 +3730,22 @@ gen3_render_video(struct sna *sna,
kgem_bo_destroy(&sna->kgem, dst_bo);
}
if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
if ((pix_xoff | pix_yoff) == 0) {
sna_damage_add(&priv->gpu_damage, dstRegion);
sna_damage_subtract(&priv->cpu_damage, dstRegion);
} else {
sna_damage_add_boxes(&priv->gpu_damage,
REGION_RECTS(dstRegion),
REGION_NUM_RECTS(dstRegion),
pix_xoff, pix_yoff);
sna_damage_subtract_boxes(&priv->cpu_damage,
REGION_RECTS(dstRegion),
REGION_NUM_RECTS(dstRegion),
pix_xoff, pix_yoff);
}
}
return TRUE;
}

View File

@ -1148,6 +1148,88 @@ fastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage,
}
#endif
static struct sna_damage *__sna_damage_subtract_boxes(struct sna_damage *damage,
const BoxRec *box, int n,
int dx, int dy)
{
BoxRec extents;
int i;
if (damage == NULL)
return NULL;
assert(n);
extents = box[0];
for (i = 1; i < n; i++) {
if (extents.x1 > box[i].x1)
extents.x1 = box[i].x1;
if (extents.x2 < box[i].x2)
extents.x2 = box[i].x2;
if (extents.y1 > box[i].y1)
extents.y1 = box[i].y1;
if (extents.y2 < box[i].y2)
extents.y2 = box[i].y2;
}
assert(extents.y2 > extents.y1 && extents.x2 > extents.x1);
extents.x1 += dx;
extents.x2 += dx;
extents.y1 += dy;
extents.y2 += dy;
if (!sna_damage_maybe_contains_box(damage, &extents))
return damage;
if (n == 1)
return __sna_damage_subtract_box(damage, &extents);
if (damage->mode != DAMAGE_SUBTRACT) {
if (damage->dirty)
__sna_damage_reduce(damage);
if (!pixman_region_not_empty(&damage->region)) {
__sna_damage_destroy(damage);
return NULL;
}
damage->mode = DAMAGE_SUBTRACT;
}
return _sna_damage_create_elt_from_boxes(damage, box, n, dx, dy);
}
#if DEBUG_DAMAGE
fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
const BoxRec *box, int n,
int dx, int dy)
{
char damage_buf[1000];
char region_buf[120];
ErrorF("%s(%s - [(%d,%d), (%d,%d)...x%d])...\n", __FUNCTION__,
_debug_describe_damage(damage_buf, sizeof(damage_buf), damage),
box->x1 + dx, box->y1 + dy,
box->x2 + dx, box->y2 + dy,
n);
damage = __sna_damage_subtract_boxes(damage, box, n, dx, dy);
ErrorF(" = %s\n",
_debug_describe_damage(damage_buf, sizeof(damage_buf), damage));
return damage;
}
#else
fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
const BoxRec *box, int n,
int dx, int dy)
{
return __sna_damage_subtract_boxes(damage, box, n, dx, dy);
}
#endif
static int __sna_damage_contains_box(struct sna_damage *damage,
const BoxRec *box)
{

View File

@ -153,6 +153,18 @@ static inline void sna_damage_subtract_box(struct sna_damage **damage,
assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
}
fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
const BoxRec *box, int n,
int dx, int dy);
static inline void sna_damage_subtract_boxes(struct sna_damage **damage,
const BoxRec *box, int n,
int dx, int dy)
{
*damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage),
box, n, dx, dy);
assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
}
Bool _sna_damage_intersect(struct sna_damage *damage,
RegionPtr region, RegionPtr result);