xf86-video-intel: 3 commits - src/sna/kgem.c src/sna/sna_damage.c src/sna/sna_damage.h src/sna/sna.h src/sna/sna_render.c src/sna/sna_render.h src/sna/sna_video_textured.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Jan 27 12:35:29 PST 2012


 src/sna/kgem.c               |    5 -
 src/sna/sna.h                |    7 -
 src/sna/sna_damage.c         |   20 +++++
 src/sna/sna_damage.h         |   12 +++
 src/sna/sna_render.c         |  164 +++++++++++++++++++++++++++++++++++++++----
 src/sna/sna_render.h         |    1 
 src/sna/sna_video_textured.c |    2 
 7 files changed, 189 insertions(+), 22 deletions(-)

New commits:
commit 8f4bae01e39392faa8978090db4cbe28fa00b013
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 27 20:28:44 2012 +0000

    sna/video: Ensure the video pixmap is on the GPU
    
    The presumption that the pixmap is the scanout and so will always be
    pinned is false if there is a shadow or under a compositor. In those
    cases, the pixmap may be idle and so the GPU bo reaped. This was
    compounded by that the video path did not mark the pixmap as busy. So
    whilst watching a video under xfce4 with compositing enabled (has to be
    a non-GL compositor) the video would suddenly stall.
    
    Reported-by: Paul Neumann <paul104x at yahoo.de>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=45279
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index bc14967..5910daf 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -476,13 +476,6 @@ sna_drawable_move_to_gpu(DrawablePtr drawable, unsigned flags)
 	return sna_pixmap_move_to_gpu(get_drawable_pixmap(drawable), flags) != NULL;
 }
 
-static inline Bool
-sna_pixmap_is_gpu(PixmapPtr pixmap)
-{
-	struct sna_pixmap *priv = pixmap ? sna_pixmap(pixmap) : NULL;
-	return priv && priv->gpu_bo;
-}
-
 static inline struct kgem_bo *sna_pixmap_get_bo(PixmapPtr pixmap)
 {
 	return sna_pixmap(pixmap)->gpu_bo;
diff --git a/src/sna/sna_video_textured.c b/src/sna/sna_video_textured.c
index 6f69135..d99f884 100644
--- a/src/sna/sna_video_textured.c
+++ b/src/sna/sna_video_textured.c
@@ -240,7 +240,7 @@ sna_video_textured_put_image(ScrnInfoPtr scrn,
 		return BadAlloc;
 	}
 
-	if (!sna_pixmap_is_gpu(pixmap)) {
+	if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ | MOVE_WRITE)) {
 		DBG(("%s: attempting to render to a non-GPU pixmap\n",
 		     __FUNCTION__));
 		return BadAlloc;
commit d02bd80b2f9f8ee3840be5d8d6b8d389192c57f5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 27 20:12:49 2012 +0000

    sna: Use a proxy rather than a temporary bo for too-tall but thin targets
    
    If the render target is thin enough to fit within the 3D pipeline, but is
    too tall, we can fudge the address of the origin and coordinates to fit
    within the constaints of the pipeline.
    
    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 d15ec60..ab825aa 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -187,6 +187,11 @@ static struct sna_damage *_sna_damage_create(void)
 	return damage;
 }
 
+struct sna_damage *sna_damage_create(void)
+{
+	return _sna_damage_create();
+}
+
 static bool _sna_damage_create_boxes(struct sna_damage *damage,
 				     int count)
 {
@@ -1395,6 +1400,21 @@ int _sna_damage_get_boxes(struct sna_damage *damage, BoxPtr *boxes)
 }
 #endif
 
+struct sna_damage *_sna_damage_combine(struct sna_damage *l,
+				       struct sna_damage *r,
+				       int dx, int dy)
+{
+	if (r->dirty)
+		__sna_damage_reduce(r);
+
+	if (pixman_region_not_empty(&r->region)) {
+		pixman_region_translate(&r->region, dx, dy);
+		l = __sna_damage_add(l, &r->region);
+	}
+
+	return l;
+}
+
 void __sna_damage_destroy(struct sna_damage *damage)
 {
 	free_list(&damage->embedded_box.list);
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index 228aba0..422a124 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -27,6 +27,18 @@ struct sna_damage {
 #define DAMAGE_MARK_ALL(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))|1))
 #define DAMAGE_PTR(ptr) ((struct sna_damage *)(((uintptr_t)(ptr))&~1))
 
+struct sna_damage *sna_damage_create(void);
+
+struct sna_damage *_sna_damage_combine(struct sna_damage *l,
+				       struct sna_damage *r,
+				       int dx, int dy);
+static inline void sna_damage_combine(struct sna_damage **l,
+				      struct sna_damage *r,
+				      int dx, int dy)
+{
+	*l = _sna_damage_combine(*l, r, dx, dy);
+}
+
 fastcall struct sna_damage *_sna_damage_add(struct sna_damage *damage,
 					    RegionPtr region);
 static inline void sna_damage_add(struct sna_damage **damage,
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 513b489..f9151e0 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1519,14 +1519,39 @@ sna_render_composite_redirect(struct sna *sna,
 	if (!width || !height)
 		return FALSE;
 
-	priv = sna_pixmap(op->dst.pixmap);
-	if (priv->gpu_bo == NULL) {
+	priv = sna_pixmap_force_to_gpu(op->dst.pixmap, MOVE_READ | MOVE_WRITE);
+	if (priv == NULL) {
 		DBG(("%s: fallback -- no GPU bo attached\n", __FUNCTION__));
 		return FALSE;
 	}
 
-	if (!sna_pixmap_move_to_gpu(op->dst.pixmap, MOVE_READ | MOVE_WRITE))
-		return FALSE;
+	if (op->dst.pixmap->drawable.width <= sna->render.max_3d_size) {
+		int y1, y2;
+
+		assert(op->dst.pixmap.drawable.height > sna->render.max_3d_size);
+		y1 =  y + op->dst.y;
+		y2 =  y1 + height;
+		y1 &= y1 & (64 - 1);
+		y2 = ALIGN(y2, 64);
+
+		if (y2 - y1 <= sna->render.max_3d_size) {
+			t->box.x2 = t->box.x1 = op->dst.x;
+			t->box.y2 = t->box.y1 = op->dst.y;
+			t->real_bo = priv->gpu_bo;
+			t->real_damage = op->damage;
+			if (op->damage) {
+				t->damage = sna_damage_create();
+				op->damage = &t->damage;
+			}
+
+			op->dst.bo = kgem_create_proxy(priv->gpu_bo,
+						       y1 * priv->gpu_bo->pitch,
+						       (y2 - y1) * priv->gpu_bo->pitch);
+			op->dst.y += -y1;
+			op->dst.height = y2 - y1;
+			return TRUE;
+		}
+	}
 
 	/* We can process the operation in a single pass,
 	 * but the target is too large for the 3D pipeline.
@@ -1557,12 +1582,17 @@ sna_render_composite_redirect(struct sna *sna,
 	}
 
 	t->real_bo = priv->gpu_bo;
+	t->real_damage = op->damage;
+	if (op->damage) {
+		t->damage = sna_damage_create();
+		op->damage = &t->damage;
+	}
+
 	op->dst.bo = bo;
 	op->dst.x = -x;
 	op->dst.y = -y;
 	op->dst.width  = width;
 	op->dst.height = height;
-	op->damage = NULL;
 	return TRUE;
 }
 
@@ -1573,13 +1603,20 @@ sna_render_composite_redirect_done(struct sna *sna,
 	const struct sna_composite_redirect *t = &op->redirect;
 
 	if (t->real_bo) {
-		DBG(("%s: copying temporary to dst\n", __FUNCTION__));
-
-		sna_blt_copy_boxes(sna, GXcopy,
-				   op->dst.bo, -t->box.x1, -t->box.y1,
-				   t->real_bo, 0, 0,
-				   op->dst.pixmap->drawable.bitsPerPixel,
-				   &t->box, 1);
+		if (t->box.x2 > t->box.x1) {
+			DBG(("%s: copying temporary to dst\n", __FUNCTION__));
+			sna_blt_copy_boxes(sna, GXcopy,
+					   op->dst.bo, -t->box.x1, -t->box.y1,
+					   t->real_bo, 0, 0,
+					   op->dst.pixmap->drawable.bitsPerPixel,
+					   &t->box, 1);
+		}
+		if (t->damage) {
+			sna_damage_combine(t->real_damage, t->damage,
+					   t->box.x1 - op->dst.x,
+					   t->box.y1 - op->dst.y);
+			__sna_damage_destroy(t->damage);
+		}
 
 		kgem_bo_destroy(&sna->kgem, op->dst.bo);
 	}
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index c4711f4..b23a8a7 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -86,6 +86,7 @@ struct sna_composite_op {
 
 	struct sna_composite_redirect {
 		struct kgem_bo *real_bo;
+		struct sna_damage **real_damage, *damage;
 		BoxRec box;
 	} redirect;
 
commit ea433995a37f0a9d1579f74029418f22a63a2bc0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jan 27 19:34:39 2012 +0000

    sna: Experiment with a partial source
    
    If the source is thin enough such that the pitch is within the sampler's
    constraints and the sample size is small enough, just fudge the origin
    of the bo such that it can be sampled.
    
    This avoids having to create a temporary bo and use the BLT to extract
    it and helps, for example, firefox-asteroids which uses an 64x11200
    texture atlas.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 4df29d2..95b67cf 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2967,7 +2967,6 @@ struct kgem_bo *kgem_create_proxy(struct kgem_bo *target,
 	DBG(("%s: target handle=%d, offset=%d, length=%d, io=%d\n",
 	     __FUNCTION__, target->handle, offset, length, target->io));
 	assert(target->proxy == NULL);
-	assert(target->tiling == I915_TILING_NONE);
 
 	bo = __kgem_bo_alloc(target->handle, length);
 	if (bo == NULL)
@@ -2975,9 +2974,11 @@ struct kgem_bo *kgem_create_proxy(struct kgem_bo *target,
 
 	bo->io = target->io;
 	bo->dirty = target->dirty;
-	bo->reusable = false;
+	bo->tiling = target->tiling;
+	bo->pitch = target->pitch;
 	bo->proxy = kgem_bo_reference(target);
 	bo->delta = offset;
+	bo->reusable = false;
 	return bo;
 }
 
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 9d7857c..513b489 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -800,6 +800,103 @@ cleanup_tmp:
 	return ret;
 }
 
+static int
+sna_render_picture_partial(struct sna *sna,
+			   PicturePtr picture,
+			   struct sna_composite_channel *channel,
+			   int16_t x, int16_t y,
+			   int16_t w, int16_t h,
+			   int16_t dst_x, int16_t dst_y)
+{
+	struct kgem_bo *bo = NULL;
+	PixmapPtr pixmap = get_drawable_pixmap(picture->pDrawable);
+	BoxRec box;
+
+	DBG(("%s (%d, %d)x(%d, %d) [dst=(%d, %d)]\n",
+	     __FUNCTION__, x, y, w, h, dst_x, dst_y));
+
+	box.x1 = x;
+	box.y1 = y;
+	box.x2 = x + w;
+	box.y2 = y + h;
+	if (channel->transform)
+		pixman_transform_bounds(channel->transform, &box);
+
+	DBG(("%s sample=(%d, %d), (%d, %d): (%d, %d)/(%d, %d), repeat=%d\n", __FUNCTION__,
+	     box.x1, box.y1, box.x2, box.y2, w, h,
+	     pixmap->drawable.width, pixmap->drawable.height,
+	     channel->repeat));
+
+	if (channel->repeat == RepeatNone || channel->repeat == RepeatPad) {
+		if (box.x1 < 0)
+			box.x1 = 0;
+		if (box.y1 < 0)
+			box.y1 = 0;
+		if (box.x2 > pixmap->drawable.width)
+			box.x2 = pixmap->drawable.width;
+		if (box.y2 > pixmap->drawable.height)
+			box.y2 = pixmap->drawable.height;
+	} else {
+		if (box.x1 < 0 ||
+		    box.y1 < 0 ||
+		    box.x2 > pixmap->drawable.width ||
+		    box.y2 > pixmap->drawable.height) {
+			box.x1 = box.y1 = 0;
+			box.x2 = pixmap->drawable.width;
+			box.y2 = pixmap->drawable.height;
+
+			if (!channel->is_affine)
+				return 0;
+		}
+	}
+
+	/* Presume worst case tile-row alignment for Y-tiling */
+	box.y1 = box.y1 & (64 - 1);
+	box.y2 = ALIGN(box.y2, 64);
+	w = box.x2 - box.x1;
+	h = box.y2 - box.y1;
+	DBG(("%s box=(%d, %d), (%d, %d): (%d, %d)/(%d, %d)\n", __FUNCTION__,
+	     box.x1, box.y1, box.x2, box.y2, w, h,
+	     pixmap->drawable.width, pixmap->drawable.height));
+	if (w <= 0 || h <= 0 || h > sna->render.max_3d_size)
+		return 0;
+
+	memset(&channel->embedded_transform,
+	       0,
+	       sizeof(channel->embedded_transform));
+	channel->embedded_transform.matrix[0][0] = 1 << 16;
+	channel->embedded_transform.matrix[0][2] = 0;
+	channel->embedded_transform.matrix[1][1] = 1 << 16;
+	channel->embedded_transform.matrix[1][2] = -box.y1 << 16;
+	channel->embedded_transform.matrix[2][2] = 1 << 16;
+	if (channel->transform)
+		pixman_transform_multiply(&channel->embedded_transform,
+					  &channel->embedded_transform,
+					  channel->transform);
+	channel->transform = &channel->embedded_transform;
+
+	if (use_cpu_bo(sna, pixmap, &box)) {
+		if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ))
+			return 0;
+
+		bo = sna_pixmap(pixmap)->cpu_bo;
+	} else {
+		if (!sna_pixmap_force_to_gpu(pixmap, MOVE_READ))
+			return 0;
+
+		bo = sna_pixmap(pixmap)->gpu_bo;
+	}
+
+	channel->offset[0] = x - dst_x;
+	channel->offset[1] = y - dst_y;
+	channel->scale[0] = 1.f/pixmap->drawable.width;
+	channel->scale[1] = 1.f/h;
+	channel->width  = pixmap->drawable.width;
+	channel->height = h;
+	channel->bo = kgem_create_proxy(bo, box.y1 * bo->pitch, h * bo->pitch);
+	return channel->bo != NULL;
+}
+
 int
 sna_render_picture_extract(struct sna *sna,
 			   PicturePtr picture,
@@ -825,6 +922,12 @@ sna_render_picture_extract(struct sna *sna,
 		return -1;
 	}
 
+	if (pixmap->drawable.width < sna->render.max_3d_size &&
+	    sna_render_picture_partial(sna, picture, channel,
+				       x, y, w, h,
+				       dst_x, dst_y))
+		return 1;
+
 	ow = w;
 	oh = h;
 


More information about the xorg-commit mailing list