diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-06-18 21:26:58 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-06-18 21:29:51 +0100 |
commit | 92e1693e5fb3a1dd89fca5e5ecc660e2de78f9cd (patch) | |
tree | 7ea8665579647a3243ae92c8c6e70b7171a69ea5 /src/sna | |
parent | d2312c8f958002e54ddcb834f37916f4b46ac291 (diff) |
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>
Diffstat (limited to 'src/sna')
-rw-r--r-- | src/sna/sna_accel.c | 74 | ||||
-rw-r--r-- | src/sna/sna_damage.c | 98 | ||||
-rw-r--r-- | src/sna/sna_damage.h | 2 |
3 files changed, 163 insertions, 11 deletions
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index d72a5917..c0c8ca43 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -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", diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c index 1957177b..ce16b773 100644 --- a/src/sna/sna_damage.c +++ b/src/sna/sna_damage.c @@ -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); +} diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h index 11969129..a006adee 100644 --- a/src/sna/sna_damage.h +++ b/src/sna/sna_damage.h @@ -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 |