xf86-video-intel: 2 commits - src/sna/sna_damage.c src/sna/sna_driver.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Jan 28 03:11:36 PST 2014


 src/sna/sna_damage.c |  352 +++++++++++++++++++++++++++++----------------------
 src/sna/sna_driver.c |   12 +
 2 files changed, 212 insertions(+), 152 deletions(-)

New commits:
commit 47effa1854e331643302146db238e6b092de8a9a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jan 27 21:48:33 2014 +0000

    sna: Rearrange damage allocation to handle malloc failure more gracefully
    
    If we fail to allocate new damage boxes, first try collescing the
    existing boxes to free up memory.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 51b15d3..47e8883 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -191,6 +191,143 @@ struct sna_damage *sna_damage_create(void)
 	return _sna_damage_create();
 }
 
+static void free_list(struct list *head)
+{
+	while (!list_is_empty(head)) {
+		struct list *l = head->next;
+		list_del(l);
+		free(l);
+	}
+}
+
+static void __sna_damage_reduce(struct sna_damage *damage)
+{
+	int n, nboxes;
+	BoxPtr boxes, free_boxes = NULL;
+	pixman_region16_t *region = &damage->region;
+	struct sna_damage_box *iter;
+
+	assert(damage->mode != DAMAGE_ALL);
+	assert(damage->dirty);
+
+	DBG(("    reduce: before region.n=%ld\n", (long)REGION_NUM_RECTS(region)));
+
+	nboxes = damage->embedded_box.size;
+	list_for_each_entry(iter, &damage->embedded_box.list, list)
+		nboxes += iter->size;
+	DBG(("   nboxes=%d, residual=%d\n", nboxes, damage->remain));
+	nboxes -= damage->remain;
+	if (nboxes == 0)
+		goto done;
+	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(region, region, &tmp);
+		else
+			pixman_region_subtract(region, region, &tmp);
+		damage->extents = region->extents;
+
+		goto done;
+	}
+
+	if (damage->mode == DAMAGE_ADD)
+		nboxes += REGION_NUM_RECTS(region);
+
+	iter = list_entry(damage->embedded_box.list.prev,
+			  struct sna_damage_box,
+			  list);
+	n = iter->size - damage->remain;
+	boxes = (BoxRec *)(iter+1);
+	DBG(("   last box count=%d/%d, need=%d\n", n, iter->size, nboxes));
+	if (nboxes > iter->size) {
+		boxes = malloc(sizeof(BoxRec)*nboxes);
+		if (boxes == NULL)
+			goto done;
+
+		free_boxes = boxes;
+	}
+
+	if (boxes != damage->embedded_box.box) {
+		if (list_is_empty(&damage->embedded_box.list)) {
+			DBG(("   copying embedded boxes\n"));
+			memcpy(boxes,
+			       damage->embedded_box.box,
+			       n*sizeof(BoxRec));
+		} else {
+			if (boxes != (BoxPtr)(iter+1)) {
+				DBG(("   copying %d boxes from last\n", n));
+				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) {
+				DBG(("   copy %d boxes from %d\n",
+				     iter->size, n));
+				memcpy(boxes + n, iter+1,
+				       iter->size * sizeof(BoxRec));
+				n += iter->size;
+
+				iter = list_entry(iter->list.prev,
+						  struct sna_damage_box,
+						  list);
+			}
+
+			DBG(("   copying embedded boxes to %d\n", n));
+			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(region),
+		       REGION_NUM_RECTS(region)*sizeof(BoxRec));
+		assert(n + REGION_NUM_RECTS(region) == nboxes);
+		pixman_region_fini(region);
+		pixman_region_init_rects(region, boxes, nboxes);
+
+		assert(pixman_region_not_empty(region));
+		assert(damage->extents.x1 == region->extents.x1 &&
+		       damage->extents.y1 == region->extents.y1 &&
+		       damage->extents.x2 == region->extents.x2 &&
+		       damage->extents.y2 == region->extents.y2);
+	} else {
+		pixman_region16_t tmp;
+
+		assert(n == nboxes);
+		pixman_region_init_rects(&tmp, boxes, nboxes);
+		pixman_region_subtract(region, region, &tmp);
+		pixman_region_fini(&tmp);
+
+		assert(damage->extents.x1 <= region->extents.x1 &&
+		       damage->extents.y1 <= region->extents.y1 &&
+		       damage->extents.x2 >= region->extents.x2 &&
+		       damage->extents.y2 >= region->extents.y2);
+		if (pixman_region_not_empty(region))
+			damage->extents = region->extents;
+		else
+			reset_extents(damage);
+	}
+
+	free(free_boxes);
+
+done:
+	damage->mode = DAMAGE_ADD;
+	free_list(&damage->embedded_box.list);
+	reset_embedded_box(damage);
+
+	DBG(("    reduce: after region.n=%ld\n", (long)REGION_NUM_RECTS(region)));
+}
+
+
 static bool _sna_damage_create_boxes(struct sna_damage *damage,
 				     int count)
 {
@@ -206,7 +343,7 @@ static bool _sna_damage_create_boxes(struct sna_damage *damage,
 
 	DBG(("    %s(%d->%d): new\n", __FUNCTION__, count, n));
 
-	if (n > (INT_MAX - sizeof(*box)) / sizeof(BoxRec))
+	if (n >= (INT_MAX - sizeof(*box)) / sizeof(BoxRec))
 		return false;
 
 	box = malloc(sizeof(*box) + sizeof(BoxRec)*n);
@@ -229,7 +366,7 @@ _sna_damage_create_elt(struct sna_damage *damage,
 	DBG(("    %s: prev=(remain %d), count=%d\n",
 	     __FUNCTION__, damage->remain, count));
 
-	damage->dirty = true;
+restart:
 	n = count;
 	if (n > damage->remain)
 		n = damage->remain;
@@ -237,6 +374,7 @@ _sna_damage_create_elt(struct sna_damage *damage,
 		memcpy(damage->box, boxes, n * sizeof(BoxRec));
 		damage->box += n;
 		damage->remain -= n;
+		damage->dirty = true;
 
 		count -= n;
 		boxes += n;
@@ -246,11 +384,23 @@ _sna_damage_create_elt(struct sna_damage *damage,
 
 	DBG(("    %s(): new elt\n", __FUNCTION__));
 
-	if (_sna_damage_create_boxes(damage, count)) {
-		memcpy(damage->box, boxes, count * sizeof(BoxRec));
-		damage->box += count;
-		damage->remain -= count;
+	if (!_sna_damage_create_boxes(damage, count)) {
+		unsigned mode;
+
+		if (!damage->dirty)
+			return damage;
+
+		mode = damage->mode;
+		__sna_damage_reduce(damage);
+		damage->mode = mode;
+
+		goto restart;
 	}
+
+	memcpy(damage->box, boxes, count * sizeof(BoxRec));
+	damage->box += count;
+	damage->remain -= count;
+	damage->dirty = true;
 	assert(damage->remain >= 0);
 
 	return damage;
@@ -265,7 +415,7 @@ _sna_damage_create_elt_from_boxes(struct sna_damage *damage,
 
 	DBG(("    %s: prev=(remain %d)\n", __FUNCTION__, damage->remain));
 
-	damage->dirty = true;
+restart:
 	n = count;
 	if (n > damage->remain)
 		n = damage->remain;
@@ -278,6 +428,7 @@ _sna_damage_create_elt_from_boxes(struct sna_damage *damage,
 		}
 		damage->box += n;
 		damage->remain -= n;
+		damage->dirty = true;
 
 		count -= n;
 		boxes += n;
@@ -287,8 +438,18 @@ _sna_damage_create_elt_from_boxes(struct sna_damage *damage,
 
 	DBG(("    %s(): new elt\n", __FUNCTION__));
 
-	if (!_sna_damage_create_boxes(damage, count))
-		return damage;
+	if (!_sna_damage_create_boxes(damage, count)) {
+		unsigned mode;
+
+		if (!damage->dirty)
+			return damage;
+
+		mode = damage->mode;
+		__sna_damage_reduce(damage);
+		damage->mode = mode;
+
+		goto restart;
+	}
 
 	for (i = 0; i < count; i++) {
 		damage->box[i].x1 = boxes[i].x1 + dx;
@@ -298,6 +459,7 @@ _sna_damage_create_elt_from_boxes(struct sna_damage *damage,
 	}
 	damage->box += count;
 	damage->remain -= count;
+	damage->dirty = true;
 	assert(damage->remain >= 0);
 
 	return damage;
@@ -313,7 +475,7 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage,
 	DBG(("    %s: prev=(remain %d), count=%d\n",
 	     __FUNCTION__, damage->remain, count));
 
-	damage->dirty = true;
+restart:
 	n = count;
 	if (n > damage->remain)
 		n = damage->remain;
@@ -326,6 +488,7 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage,
 		}
 		damage->box += n;
 		damage->remain -= n;
+		damage->dirty = true;
 
 		count -= n;
 		r += n;
@@ -335,8 +498,18 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage,
 
 	DBG(("    %s(): new elt\n", __FUNCTION__));
 
-	if (!_sna_damage_create_boxes(damage, count))
-		return damage;
+	if (!_sna_damage_create_boxes(damage, count)) {
+		unsigned mode;
+
+		if (!damage->dirty)
+			return damage;
+
+		mode = damage->mode;
+		__sna_damage_reduce(damage);
+		damage->mode = mode;
+
+		goto restart;
+	}
 
 	for (i = 0; i < count; i++) {
 		damage->box[i].x1 = r[i].x + dx;
@@ -346,6 +519,7 @@ _sna_damage_create_elt_from_rectangles(struct sna_damage *damage,
 	}
 	damage->box += count;
 	damage->remain -= count;
+	damage->dirty = true;
 	assert(damage->remain >= 0);
 
 	return damage;
@@ -361,7 +535,7 @@ _sna_damage_create_elt_from_points(struct sna_damage *damage,
 	DBG(("    %s: prev=(remain %d), count=%d\n",
 	     __FUNCTION__, damage->remain, count));
 
-	damage->dirty = true;
+restart:
 	n = count;
 	if (n > damage->remain)
 		n = damage->remain;
@@ -374,6 +548,7 @@ _sna_damage_create_elt_from_points(struct sna_damage *damage,
 		}
 		damage->box += n;
 		damage->remain -= n;
+		damage->dirty = true;
 
 		count -= n;
 		p += n;
@@ -383,8 +558,18 @@ _sna_damage_create_elt_from_points(struct sna_damage *damage,
 
 	DBG(("    %s(): new elt\n", __FUNCTION__));
 
-	if (!_sna_damage_create_boxes(damage, count))
-		return damage;
+	if (!_sna_damage_create_boxes(damage, count)) {
+		unsigned mode;
+
+		if (!damage->dirty)
+			return damage;
+
+		mode = damage->mode;
+		__sna_damage_reduce(damage);
+		damage->mode = mode;
+
+		goto restart;
+	}
 
 	for (i = 0; i < count; i++) {
 		damage->box[i].x1 = p[i].x + dx;
@@ -394,147 +579,12 @@ _sna_damage_create_elt_from_points(struct sna_damage *damage,
 	}
 	damage->box += count;
 	damage->remain -= count;
+	damage->dirty = true;
 	assert(damage->remain >= 0);
 
 	return damage;
 }
 
-static void free_list(struct list *head)
-{
-	while (!list_is_empty(head)) {
-		struct list *l = head->next;
-		list_del(l);
-		free(l);
-	}
-}
-
-static void __sna_damage_reduce(struct sna_damage *damage)
-{
-	int n, nboxes;
-	BoxPtr boxes, free_boxes = NULL;
-	pixman_region16_t *region = &damage->region;
-	struct sna_damage_box *iter;
-
-	assert(damage->mode != DAMAGE_ALL);
-	assert(damage->dirty);
-
-	DBG(("    reduce: before region.n=%ld\n", (long)REGION_NUM_RECTS(region)));
-
-	nboxes = damage->embedded_box.size;
-	list_for_each_entry(iter, &damage->embedded_box.list, list)
-		nboxes += iter->size;
-	DBG(("   nboxes=%d, residual=%d\n", nboxes, damage->remain));
-	nboxes -= damage->remain;
-	if (nboxes == 0)
-		goto done;
-	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(region, region, &tmp);
-		else
-			pixman_region_subtract(region, region, &tmp);
-		damage->extents = region->extents;
-
-		goto done;
-	}
-
-	if (damage->mode == DAMAGE_ADD)
-		nboxes += REGION_NUM_RECTS(region);
-
-	iter = list_entry(damage->embedded_box.list.prev,
-			  struct sna_damage_box,
-			  list);
-	n = iter->size - damage->remain;
-	boxes = (BoxRec *)(iter+1);
-	DBG(("   last box count=%d/%d, need=%d\n", n, iter->size, nboxes));
-	if (nboxes > iter->size) {
-		boxes = malloc(sizeof(BoxRec)*nboxes);
-		if (boxes == NULL)
-			goto done;
-
-		free_boxes = boxes;
-	}
-
-	if (boxes != damage->embedded_box.box) {
-		if (list_is_empty(&damage->embedded_box.list)) {
-			DBG(("   copying embedded boxes\n"));
-			memcpy(boxes,
-			       damage->embedded_box.box,
-			       n*sizeof(BoxRec));
-		} else {
-			if (boxes != (BoxPtr)(iter+1)) {
-				DBG(("   copying %d boxes from last\n", n));
-				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) {
-				DBG(("   copy %d boxes from %d\n",
-				     iter->size, n));
-				memcpy(boxes + n, iter+1,
-				       iter->size * sizeof(BoxRec));
-				n += iter->size;
-
-				iter = list_entry(iter->list.prev,
-						  struct sna_damage_box,
-						  list);
-			}
-
-			DBG(("   copying embedded boxes to %d\n", n));
-			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(region),
-		       REGION_NUM_RECTS(region)*sizeof(BoxRec));
-		assert(n + REGION_NUM_RECTS(region) == nboxes);
-		pixman_region_fini(region);
-		pixman_region_init_rects(region, boxes, nboxes);
-
-		assert(pixman_region_not_empty(region));
-		assert(damage->extents.x1 == region->extents.x1 &&
-		       damage->extents.y1 == region->extents.y1 &&
-		       damage->extents.x2 == region->extents.x2 &&
-		       damage->extents.y2 == region->extents.y2);
-	} else {
-		pixman_region16_t tmp;
-
-		assert(n == nboxes);
-		pixman_region_init_rects(&tmp, boxes, nboxes);
-		pixman_region_subtract(region, region, &tmp);
-		pixman_region_fini(&tmp);
-
-		assert(damage->extents.x1 <= region->extents.x1 &&
-		       damage->extents.y1 <= region->extents.y1 &&
-		       damage->extents.x2 >= region->extents.x2 &&
-		       damage->extents.y2 >= region->extents.y2);
-		if (pixman_region_not_empty(region))
-			damage->extents = region->extents;
-		else
-			reset_extents(damage);
-	}
-
-	free(free_boxes);
-
-done:
-	damage->mode = DAMAGE_ADD;
-	free_list(&damage->embedded_box.list);
-	reset_embedded_box(damage);
-
-	DBG(("    reduce: after region.n=%ld\n", (long)REGION_NUM_RECTS(region)));
-}
-
 static void damage_union(struct sna_damage *damage, const BoxRec *box)
 {
 	DBG(("%s: extending damage (%d, %d), (%d, %d) by (%d, %d), (%d, %d)\n",
commit ad7daf9aae487af13c0578de95652675d4d2ed7d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jan 27 21:20:40 2014 +0000

    sna: Use signal-safe DBG
    
    Otherwise we end up confusing the core Xserver functions when called
    from auxilliary threads.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 4472f25..fd0d3bd 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -1256,8 +1256,18 @@ _X_ATTRIBUTE_PRINTF(1, 0) void LogF(const char *f, ...)
 {
 	va_list ap;
 
+	/* As we not only may be called from any context, we may also
+	 * be called from a thread whilst the main thread is handling
+	 * signals, therefore we have to use the signal-safe variants
+	 * or else we trip over false positive assertions.
+	 */
+
 	va_start(ap, f);
-	LogVWrite(1, f, ap);
+#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,12,99,901,0)
+	LogVMessageVerbSigSafe(X_NONE, 1, f, ap);
+#else
+	LogVMessageVerb(X_NONE, 1, f, ap);
+#endif
 	va_end(ap);
 }
 #endif


More information about the xorg-commit mailing list