xf86-video-intel: 2 commits - configure.ac src/sna/kgem.c src/sna/sna_accel.c src/sna/sna_damage.c src/sna/sna_damage.h

Chris Wilson ickle at kemper.freedesktop.org
Mon Jun 18 13:31:25 PDT 2012


 configure.ac         |    4 ++
 src/sna/kgem.c       |    8 +++-
 src/sna/sna_accel.c  |   74 ++++++++++++++++++++++++++++++++------
 src/sna/sna_damage.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/sna/sna_damage.h |    2 +
 5 files changed, 173 insertions(+), 13 deletions(-)

New commits:
commit 92e1693e5fb3a1dd89fca5e5ecc660e2de78f9cd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 18 21:26:58 2012 +0100

    sna: Validate cpu/gpu damage never overlaps
    
    References: https://bugs.freedesktop.org/show_bug.cgi?id=50477
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index 0b93a2f..604db7d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index d72a591..c0c8ca4 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(&reg);
+	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(&reg, &cpu, &gpu);
+	assert(!RegionNotEmpty(&reg));
+
+	RegionUninit(&reg);
+	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, &region->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 1957177..ce16b77 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 1196912..a006ade 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
commit d2312c8f958002e54ddcb834f37916f4b46ac291
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 18 21:29:29 2012 +0100

    sna: Fixup tracking of vmap upload buffers
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 84475fe..aaddda4 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1032,7 +1032,9 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
 
 	if (IS_VMAP_MAP(bo->map)) {
 		assert(bo->rq == NULL);
-		free(MAP(bo->map));
+		assert(MAP(bo->map) != bo || bo->io);
+		if (bo != MAP(bo->map))
+			free(MAP(bo->map));
 		bo->map = NULL;
 	}
 	if (bo->map)
@@ -1578,6 +1580,7 @@ static void kgem_finish_partials(struct kgem *kgem)
 			    (kgem->has_llc || !IS_CPU_MAP(bo->base.map))) {
 				DBG(("%s: retaining partial upload buffer (%d/%d)\n",
 				     __FUNCTION__, bo->used, bytes(&bo->base)));
+				assert(!bo->base.vmap);
 				list_move(&bo->base.list,
 					  &kgem->active_partials);
 				continue;
@@ -3881,10 +3884,11 @@ struct kgem_bo *kgem_create_buffer(struct kgem *kgem,
 				DBG(("%s: created vmap handle=%d for buffer\n",
 				     __FUNCTION__, bo->base.handle));
 
-				bo->need_io = false;
 				bo->base.io = true;
 				bo->base.vmap = true;
+				bo->base.map = MAKE_VMAP_MAP(bo);
 				bo->mmapped = true;
+				bo->need_io = false;
 
 				goto init;
 			}


More information about the xorg-commit mailing list