sna: Validate cpu/gpu damage never overlaps
References: https://bugs.freedesktop.org/show_bug.cgi?id=50477 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
d2312c8f95
commit
92e1693e5f
|
|
@ -318,8 +318,12 @@ fi
|
|||
if test "x$DEBUG" = xmemory; then
|
||||
AC_DEFINE(DEBUG_MEMORY,1,[Enable memory debugging])
|
||||
fi
|
||||
if test "x$DEBUG" = xpixmap; then
|
||||
AC_DEFINE(DEBUG_PIXMAP,1,[Enable pixmap debugging])
|
||||
fi
|
||||
if test "x$DEBUG" = xfull; then
|
||||
AC_DEFINE(DEBUG_MEMORY,1,[Enable memory debugging])
|
||||
AC_DEFINE(DEBUG_PIXMAP,1,[Enable pixmap debugging])
|
||||
AC_DEFINE(HAS_DEBUG_FULL,1,[Enable all debugging])
|
||||
CFLAGS="$CFLAGS -O0 -ggdb3"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ typedef struct box32 {
|
|||
#define PM_IS_SOLID(_draw, _pm) \
|
||||
(((_pm) & FbFullMask((_draw)->depth)) == FbFullMask((_draw)->depth))
|
||||
|
||||
#if DEBUG_ACCEL
|
||||
#ifdef DEBUG_PIXMAP
|
||||
static void _assert_pixmap_contains_box(PixmapPtr pixmap, const BoxRec *box, const char *function)
|
||||
{
|
||||
if (box->x1 < 0 || box->y1 < 0 ||
|
||||
|
|
@ -296,15 +296,53 @@ static void _assert_drawable_contains_box(DrawablePtr drawable, const BoxRec *bo
|
|||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void assert_pixmap_damage(PixmapPtr p)
|
||||
{
|
||||
struct sna_pixmap *priv;
|
||||
RegionRec reg, cpu, gpu;
|
||||
|
||||
priv = sna_pixmap(p);
|
||||
if (priv == NULL)
|
||||
return;
|
||||
|
||||
if (DAMAGE_IS_ALL(priv->gpu_damage) && DAMAGE_IS_ALL(priv->cpu_damage))
|
||||
/* special upload buffer */
|
||||
return;
|
||||
|
||||
assert(!DAMAGE_IS_ALL(priv->gpu_damage) || priv->cpu_damage == NULL);
|
||||
assert(!DAMAGE_IS_ALL(priv->cpu_damage) || priv->gpu_damage == NULL);
|
||||
|
||||
/* Avoid reducing damage to minimise interferrence */
|
||||
RegionNull(®);
|
||||
RegionNull(&gpu);
|
||||
RegionNull(&cpu);
|
||||
|
||||
if (priv->gpu_damage)
|
||||
_sna_damage_debug_get_region(DAMAGE_PTR(priv->gpu_damage), &gpu);
|
||||
|
||||
if (priv->cpu_damage)
|
||||
_sna_damage_debug_get_region(DAMAGE_PTR(priv->cpu_damage), &cpu);
|
||||
|
||||
RegionIntersect(®, &cpu, &gpu);
|
||||
assert(!RegionNotEmpty(®));
|
||||
|
||||
RegionUninit(®);
|
||||
RegionUninit(&gpu);
|
||||
RegionUninit(&cpu);
|
||||
}
|
||||
|
||||
#define assert_pixmap_contains_box(p, b) _assert_pixmap_contains_box(p, b, __FUNCTION__)
|
||||
#define assert_drawable_contains_box(d, b) _assert_drawable_contains_box(d, b, __FUNCTION__)
|
||||
#define assert_pixmap_contains_boxes(p, b, n, x, y) _assert_pixmap_contains_boxes(p, b, n, x, y, __FUNCTION__)
|
||||
#define assert_pixmap_contains_points(p, pt, n, x, y) _assert_pixmap_contains_points(p, pt, n, x, y, __FUNCTION__)
|
||||
|
||||
#else
|
||||
#define assert_pixmap_contains_box(p, b)
|
||||
#define assert_pixmap_contains_boxes(p, b, n, x, y)
|
||||
#define assert_pixmap_contains_points(p, pt, n, x, y)
|
||||
#define assert_drawable_contains_box(d, b)
|
||||
#define assert_pixmap_damage(p)
|
||||
#endif
|
||||
|
||||
inline static bool
|
||||
|
|
@ -441,6 +479,8 @@ static Bool sna_destroy_private(PixmapPtr pixmap, struct sna_pixmap *priv)
|
|||
list_del(&priv->list);
|
||||
list_del(&priv->inactive);
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
|
||||
sna_damage_destroy(&priv->gpu_damage);
|
||||
sna_damage_destroy(&priv->cpu_damage);
|
||||
|
||||
|
|
@ -536,6 +576,8 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
|
||||
bo = kgem_create_2d(&sna->kgem,
|
||||
pixmap->drawable.width,
|
||||
pixmap->drawable.height,
|
||||
|
|
@ -939,6 +981,8 @@ sna_pixmap_create_mappable_gpu(PixmapPtr pixmap)
|
|||
if (wedged(sna))
|
||||
return false;
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
|
||||
assert(priv->gpu_bo == NULL);
|
||||
priv->gpu_bo =
|
||||
kgem_create_2d(&sna->kgem,
|
||||
|
|
@ -993,6 +1037,8 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
|
|||
pixmap->drawable.height,
|
||||
flags));
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
|
||||
priv = sna_pixmap(pixmap);
|
||||
if (priv == NULL) {
|
||||
DBG(("%s: not attached\n", __FUNCTION__));
|
||||
|
|
@ -1052,6 +1098,7 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
|
|||
sna_pixmap_free_cpu(sna, priv);
|
||||
}
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1105,6 +1152,8 @@ skip_inplace_map:
|
|||
priv->undamaged = false;
|
||||
priv->clear = false;
|
||||
}
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1203,6 +1252,7 @@ done:
|
|||
}
|
||||
assert(pixmap->devPrivate.ptr);
|
||||
assert(pixmap->devKind);
|
||||
assert_pixmap_damage(pixmap);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1295,6 +1345,8 @@ static inline bool region_inplace(struct sna *sna,
|
|||
struct sna_pixmap *priv,
|
||||
bool write_only)
|
||||
{
|
||||
assert_pixmap_damage(pixmap);
|
||||
|
||||
if (FORCE_INPLACE)
|
||||
return FORCE_INPLACE > 0;
|
||||
|
||||
|
|
@ -1353,6 +1405,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
|
|||
RegionExtents(region)->x2, RegionExtents(region)->y2,
|
||||
flags));
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
if (flags & MOVE_WRITE) {
|
||||
assert_drawable_contains_box(drawable, ®ion->extents);
|
||||
}
|
||||
|
|
@ -1432,6 +1485,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
|
|||
region);
|
||||
|
||||
priv->clear = false;
|
||||
assert_pixmap_damage(pixmap);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1470,6 +1524,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
|
|||
} else
|
||||
sna_damage_add(&priv->gpu_damage, region);
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
priv->clear = false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1501,6 +1556,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
|
|||
sna_damage_subtract(&priv->cpu_damage,
|
||||
region);
|
||||
}
|
||||
assert_pixmap_damage(pixmap);
|
||||
priv->clear = false;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1771,16 +1827,6 @@ done:
|
|||
}
|
||||
if (priv->flush)
|
||||
list_move(&priv->list, &sna->dirty_pixmaps);
|
||||
#ifdef HAVE_FULL_DEBUG
|
||||
{
|
||||
RegionRec need;
|
||||
|
||||
RegionNull(&need);
|
||||
assert(priv->gpu_damage == NULL ||
|
||||
!sna_damage_intersect(priv->gpu_damage, r, &need));
|
||||
RegionUninit(&need);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dx | dy)
|
||||
|
|
@ -1797,6 +1843,7 @@ out:
|
|||
}
|
||||
assert(pixmap->devPrivate.ptr);
|
||||
assert(pixmap->devKind);
|
||||
assert_pixmap_damage(pixmap);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1914,6 +1961,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
|
|||
|
||||
DBG(("%s()\n", __FUNCTION__));
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
assert_pixmap_contains_box(pixmap, box);
|
||||
|
||||
if (sna_damage_is_all(&priv->gpu_damage,
|
||||
|
|
@ -1961,6 +2009,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
|
|||
sna_damage_subtract_box(&priv->cpu_damage, box);
|
||||
|
||||
sna_damage_reduce(&priv->cpu_damage);
|
||||
assert_pixmap_damage(pixmap);
|
||||
if (priv->cpu_damage == NULL) {
|
||||
list_del(&priv->list);
|
||||
goto done;
|
||||
|
|
@ -2082,6 +2131,7 @@ done:
|
|||
if (!priv->pinned && (priv->create & KGEM_CAN_CREATE_LARGE) == 0)
|
||||
list_move(&priv->inactive, &sna->active_pixmaps);
|
||||
priv->clear = false;
|
||||
assert_pixmap_damage(pixmap);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2107,6 +2157,7 @@ sna_drawable_use_bo(DrawablePtr drawable,
|
|||
DBG(("%s((%d, %d), (%d, %d))...\n", __FUNCTION__,
|
||||
box->x1, box->y1, box->x2, box->y2));
|
||||
|
||||
assert_pixmap_damage(pixmap);
|
||||
assert_drawable_contains_box(drawable, box);
|
||||
|
||||
if (priv == NULL) {
|
||||
|
|
@ -2482,6 +2533,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
|
|||
sna_damage_destroy(&priv->cpu_damage);
|
||||
|
||||
sna_damage_reduce(&priv->cpu_damage);
|
||||
assert_pixmap_damage(pixmap);
|
||||
DBG(("%s: CPU damage? %d\n", __FUNCTION__, priv->cpu_damage != NULL));
|
||||
if (priv->gpu_bo == NULL) {
|
||||
DBG(("%s: creating GPU bo (%dx%d@%d), create=%x\n",
|
||||
|
|
|
|||
|
|
@ -1626,3 +1626,101 @@ void sna_damage_selftest(void)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void _sna_damage_debug_get_region(struct sna_damage *damage, RegionRec *r)
|
||||
{
|
||||
int n, nboxes;
|
||||
BoxPtr boxes;
|
||||
struct sna_damage_box *iter;
|
||||
|
||||
RegionCopy(r, &damage->region);
|
||||
if (!damage->dirty)
|
||||
return;
|
||||
|
||||
nboxes = damage->embedded_box.size;
|
||||
list_for_each_entry(iter, &damage->embedded_box.list, list)
|
||||
nboxes += iter->size;
|
||||
nboxes -= damage->remain;
|
||||
if (nboxes == 0)
|
||||
return;
|
||||
|
||||
if (nboxes == 1) {
|
||||
pixman_region16_t tmp;
|
||||
|
||||
tmp.extents = damage->embedded_box.box[0];
|
||||
tmp.data = NULL;
|
||||
|
||||
if (damage->mode == DAMAGE_ADD)
|
||||
pixman_region_union(r, r, &tmp);
|
||||
else
|
||||
pixman_region_subtract(r, r, &tmp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (damage->mode == DAMAGE_ADD)
|
||||
nboxes += REGION_NUM_RECTS(r);
|
||||
|
||||
iter = list_entry(damage->embedded_box.list.prev,
|
||||
struct sna_damage_box,
|
||||
list);
|
||||
n = iter->size - damage->remain;
|
||||
boxes = malloc(sizeof(BoxRec)*nboxes);
|
||||
if (boxes == NULL)
|
||||
return;
|
||||
|
||||
if (list_is_empty(&damage->embedded_box.list)) {
|
||||
memcpy(boxes,
|
||||
damage->embedded_box.box,
|
||||
n*sizeof(BoxRec));
|
||||
} else {
|
||||
if (boxes != (BoxPtr)(iter+1))
|
||||
memcpy(boxes, iter+1, n*sizeof(BoxRec));
|
||||
|
||||
iter = list_entry(iter->list.prev,
|
||||
struct sna_damage_box,
|
||||
list);
|
||||
while (&iter->list != &damage->embedded_box.list) {
|
||||
memcpy(boxes + n, iter+1,
|
||||
iter->size * sizeof(BoxRec));
|
||||
n += iter->size;
|
||||
|
||||
iter = list_entry(iter->list.prev,
|
||||
struct sna_damage_box,
|
||||
list);
|
||||
}
|
||||
|
||||
memcpy(boxes + n,
|
||||
damage->embedded_box.box,
|
||||
sizeof(damage->embedded_box.box));
|
||||
n += damage->embedded_box.size;
|
||||
}
|
||||
|
||||
if (damage->mode == DAMAGE_ADD) {
|
||||
memcpy(boxes + n,
|
||||
REGION_RECTS(r),
|
||||
REGION_NUM_RECTS(r)*sizeof(BoxRec));
|
||||
assert(n + REGION_NUM_RECTS(r) == nboxes);
|
||||
pixman_region_fini(r);
|
||||
pixman_region_init_rects(r, boxes, nboxes);
|
||||
|
||||
assert(pixman_region_not_empty(r));
|
||||
assert(damage->extents.x1 == r->extents.x1 &&
|
||||
damage->extents.y1 == r->extents.y1 &&
|
||||
damage->extents.x2 == r->extents.x2 &&
|
||||
damage->extents.y2 == r->extents.y2);
|
||||
} else {
|
||||
pixman_region16_t tmp;
|
||||
|
||||
pixman_region_init_rects(&tmp, boxes, nboxes);
|
||||
pixman_region_subtract(r, r, &tmp);
|
||||
pixman_region_fini(&tmp);
|
||||
|
||||
assert(damage->extents.x1 <= r->extents.x1 &&
|
||||
damage->extents.y1 <= r->extents.y1 &&
|
||||
damage->extents.x2 >= r->extents.x2 &&
|
||||
damage->extents.y2 >= r->extents.y2);
|
||||
}
|
||||
|
||||
free(boxes);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,6 +285,8 @@ static inline void sna_damage_destroy(struct sna_damage **damage)
|
|||
*damage = NULL;
|
||||
}
|
||||
|
||||
void _sna_damage_debug_get_region(struct sna_damage *damage, RegionRec *r);
|
||||
|
||||
#if DEBUG_DAMAGE && TEST_DAMAGE
|
||||
void sna_damage_selftest(void);
|
||||
#else
|
||||
|
|
|
|||
Loading…
Reference in New Issue