xf86-video-intel: src/sna/sna_accel.c src/sna/sna_damage.c src/sna/sna_damage.h

Chris Wilson ickle at kemper.freedesktop.org
Thu Oct 20 10:00:38 PDT 2011


 src/sna/sna_accel.c  |   23 ++++---
 src/sna/sna_damage.c |  153 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/sna/sna_damage.h |   10 +++
 3 files changed, 175 insertions(+), 11 deletions(-)

New commits:
commit 1229bf6a690e7f315ab22957da23481f58515ff9
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 20 17:37:41 2011 +0100

    sna: Actually apply the composite offset for the self-copy
    
    I translated the region to copy by the composite pixmap offset, only
    failed to use the translated region for the actual copy command (using
    instead the original boxes). Fix that mistake by avoiding the temporary
    region entirely and applying the translation inplace.
    
    We also have to be careful in the case of copying between two composited
    windows that have different offsets into the same screen pixmap.
    
    This fixes the regression introduced with a3466c8b69af (sna/accel:
    Implement a simpler path for CopyArea between the same pixmaps).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 22f5468..8153d34 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1254,7 +1254,6 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 	PixmapPtr pixmap = get_drawable_pixmap(src);
 	struct sna_pixmap *priv = sna_pixmap(pixmap);
 	int alu = gc ? gc->alu : GXcopy;
-	RegionRec region;
 	int16_t tx, ty;
 
 	if (n == 0 || (dx | dy) == 0)
@@ -1266,10 +1265,11 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 	     dx, dy, alu,
 	     pixmap->drawable.width, pixmap->drawable.height));
 
-	pixman_region_init_rects(&region, box, n);
-	get_drawable_deltas(dst, pixmap, &tx, &ty);
-	RegionTranslate(&region, tx, ty);
-	assert_pixmap_contains_box(pixmap, RegionExtents(&region));
+	get_drawable_deltas(src, pixmap, &tx, &ty);
+	dx += tx;
+	dy += ty;
+	if (dst != src)
+		get_drawable_deltas(dst, pixmap, &tx, &ty);
 
 	if (priv && priv->gpu_bo) {
 		if (!sna_pixmap_move_to_gpu(pixmap)) {
@@ -1280,14 +1280,14 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 
 		if (!sna->render.copy_boxes(sna, alu,
 					    pixmap, priv->gpu_bo, dx, dy,
-					    pixmap, priv->gpu_bo, 0, 0,
+					    pixmap, priv->gpu_bo, tx, ty,
 					    box, n)) {
 			DBG(("%s: fallback - accelerated copy boxes failed\n",
 			     __FUNCTION__));
 			goto fallback;
 		}
 
-		sna_damage_add(&priv->gpu_damage, &region);
+		sna_damage_add_boxes(&priv->gpu_damage, box, n, tx, ty);
 	} else {
 		FbBits *dst_bits, *src_bits;
 		int stride, bpp;
@@ -1299,7 +1299,9 @@ fallback:
 		stride = pixmap->devKind;
 		bpp = pixmap->drawable.bitsPerPixel;
 		if (alu == GXcopy && !reverse && !upsidedown && bpp >= 8) {
-			dst_bits = pixmap->devPrivate.ptr;
+			dst_bits = (FbBits *)
+				((char *)pixmap->devPrivate.ptr +
+				 ty * stride + tx * bpp / 8);
 			src_bits = (FbBits *)
 				((char *)pixmap->devPrivate.ptr +
 				 dy * stride + dx * bpp / 8);
@@ -1323,9 +1325,9 @@ fallback:
 				      stride,
 				      (box->x1 + dx) * bpp,
 
-				      dst_bits + box->y1 * stride,
+				      dst_bits + (box->y1 + ty) * stride,
 				      stride,
-				      box->x1 * bpp,
+				      (box->x1 + tx) * bpp,
 
 				      (box->x2 - box->x1) * bpp,
 				      (box->y2 - box->y1),
@@ -1336,7 +1338,6 @@ fallback:
 			}while (--n);
 		}
 	}
-	RegionUninit(&region);
 }
 
 static void
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index f6ffef0..b5d0084 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -231,6 +231,73 @@ _sna_damage_create_elt(struct sna_damage *damage,
 			  boxes, count * sizeof(BoxRec));
 }
 
+static void
+_sna_damage_create_elt_with_translation(struct sna_damage *damage,
+					enum mode mode,
+					const BoxRec *boxes, int count,
+					int16_t dx, int16_t dy)
+{
+	struct sna_damage_elt *elt;
+	int i;
+
+	DBG(("    %s(%s): n=%d, prev=(%s, remain %d)\n", __FUNCTION__,
+	     mode == ADD ? "add" : "subtract",
+	     damage->n,
+	     damage->n ? damage->elts[damage->n-1].mode == ADD ? "add" : "subtract" : "none",
+	     damage->last_box ? damage->last_box->remain : 0));
+
+	if (damage->last_box && damage->elts[damage->n-1].mode == mode) {
+		int n;
+		BoxRec *b;
+
+		n = count;
+		if (n > damage->last_box->remain)
+			n = damage->last_box->remain;
+
+		elt = damage->elts + damage->n-1;
+		b = elt->box + elt->n;
+		for (i = 0; i < n; i++) {
+			b[i].x1 = boxes[i].x1 + dx;
+			b[i].x2 = boxes[i].x2 + dx;
+			b[i].y1 = boxes[i].y1 + dy;
+			b[i].y2 = boxes[i].y2 + dy;
+		}
+		elt->n += n;
+		damage->last_box->remain -= n;
+		if (damage->last_box->remain == 0)
+			damage->last_box = NULL;
+
+		count -=n;
+		boxes += n;
+		if (count == 0)
+			return;
+	}
+
+	if (damage->n == damage->size) {
+		int newsize = damage->size * 2;
+		struct sna_damage_elt *newelts = realloc(damage->elts,
+							 newsize*sizeof(*elt));
+		if (newelts == NULL)
+			return;
+
+		damage->elts = newelts;
+		damage->size = newsize;
+	}
+
+	DBG(("    %s(): new elt\n", __FUNCTION__));
+
+	elt = damage->elts + damage->n++;
+	elt->mode = mode;
+	elt->n = count;
+	elt->box = _sna_damage_create_boxes(damage, count);
+	for (i = 0; i < count; i++) {
+		elt->box[i].x1 = boxes[i].x1 + dx;
+		elt->box[i].x2 = boxes[i].x2 + dx;
+		elt->box[i].y1 = boxes[i].y1 + dy;
+		elt->box[i].y2 = boxes[i].y2 + dy;
+	}
+}
+
 static void free_list(struct list *head)
 {
 	while (!list_is_empty(head)) {
@@ -387,6 +454,92 @@ fastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage,
 }
 #endif
 
+inline static struct sna_damage *
+__sna_damage_add_boxes(struct sna_damage *damage,
+		       const BoxRec *box, int n,
+		       int16_t dx, int16_t dy)
+{
+	BoxRec extents;
+	int i;
+
+	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;
+	}
+
+	if (extents.y2 <= extents.y1 || extents.x2 <= extents.x1)
+		return damage;
+
+	extents.x1 += dx;
+	extents.x2 += dx;
+	extents.y1 += dy;
+	extents.y2 += dy;
+
+	if (!damage)
+		damage = _sna_damage_create();
+
+	if (damage->all)
+		return damage;
+
+	if (damage->mode == SUBTRACT)
+		__sna_damage_reduce(damage);
+	damage->mode = ADD;
+
+	if (pixman_region_contains_rectangle(&damage->region,
+					     &extents) == PIXMAN_REGION_IN)
+		return damage;
+
+	_sna_damage_create_elt_with_translation(damage, ADD, box, n, dx, dy);
+
+	if (damage->extents.x1 > extents.x1)
+		damage->extents.x1 = extents.x1;
+	if (damage->extents.x2 < extents.x2)
+		damage->extents.x2 = extents.x2;
+
+	if (damage->extents.y1 > extents.y1)
+		damage->extents.y1 = extents.y1;
+	if (damage->extents.y2 < extents.y2)
+		damage->extents.y2 = extents.y2;
+
+	return damage;
+}
+
+#if DEBUG_DAMAGE
+struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
+					 const BoxRec *box, int n,
+					 int16_t dx, int16_t dy)
+{
+	char damage_buf[1000];
+
+	DBG(("%s(%s + [(%d, %d), (%d, %d) ... x %d])\n", __FUNCTION__,
+	     _debug_describe_damage(damage_buf, sizeof(damage_buf), damage),
+	     box->x1, box->y1, box->x2, box->y2, n));
+
+	damage = __sna_damage_add_box(damage, boxes, n, dx, dy);
+
+	ErrorF("  = %s\n",
+	       _debug_describe_damage(damage_buf, sizeof(damage_buf), damage));
+
+	return damage;
+}
+#else
+struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
+					 const BoxRec *box, int n,
+					 int16_t dx, int16_t dy)
+{
+	return __sna_damage_add_boxes(damage, box, n, dx, dy);
+}
+#endif
+
 inline static struct sna_damage *__sna_damage_add_box(struct sna_damage *damage,
 						      const BoxRec *box)
 {
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index 5fb9aef..454ad84 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -34,6 +34,16 @@ static inline void sna_damage_add_box(struct sna_damage **damage,
 	*damage = _sna_damage_add_box(*damage, box);
 }
 
+struct sna_damage *_sna_damage_add_boxes(struct sna_damage *damage,
+					 const BoxRec *box, int n,
+					 int16_t dx, int16_t dy);
+static inline void sna_damage_add_boxes(struct sna_damage **damage,
+					const BoxRec *box, int n,
+					int16_t dx, int16_t dy)
+{
+	*damage = _sna_damage_add_boxes(*damage, box, n, dx, dy);
+}
+
 struct sna_damage *_sna_damage_is_all(struct sna_damage *damage,
 				       int width, int height);
 static inline bool sna_damage_is_all(struct sna_damage **damage,


More information about the xorg-commit mailing list