xf86-video-intel: 11 commits - src/sna/gen6_render.c src/sna/kgem.c src/sna/kgem.h src/sna/sna_accel.c src/sna/sna_blt.c src/sna/sna_display.c src/sna/sna.h src/sna/sna_render.c src/sna/sna_render.h src/sna/sna_render_inline.h src/sna/sna_trapezoids.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Mar 13 11:47:07 PDT 2012


 src/sna/gen6_render.c       |   27 ++----
 src/sna/kgem.c              |   35 +++++++-
 src/sna/kgem.h              |    1 
 src/sna/sna.h               |    7 +
 src/sna/sna_accel.c         |   69 +++++++++-------
 src/sna/sna_blt.c           |   12 ++
 src/sna/sna_display.c       |    6 -
 src/sna/sna_render.c        |  188 +++++++++++++++++---------------------------
 src/sna/sna_render.h        |    1 
 src/sna/sna_render_inline.h |    8 +
 src/sna/sna_trapezoids.c    |   62 +++++++++++---
 11 files changed, 236 insertions(+), 180 deletions(-)

New commits:
commit 015db20287ec90f81ddb7eb2e7ce23b90aacfb2b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 13 16:29:41 2012 +0000

    sna: Refactor source upload-to-gpu
    
    This was originally split between into functions for flexibility that
    nothing used, so merge the duplicated code into a common function.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index b5d314b..8be3e72 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -354,122 +354,88 @@ use_cpu_bo(struct sna *sna, PixmapPtr pixmap, const BoxRec *box)
 	return priv->cpu_bo;
 }
 
-static Bool
+static struct kgem_bo *
 move_to_gpu(PixmapPtr pixmap, const BoxRec *box)
 {
 	struct sna_pixmap *priv;
 	int count, w, h;
+	bool migrate = false;
 
 	if (DBG_FORCE_UPLOAD > 0)
-		return FALSE;
+		return NULL;
+
+	priv = sna_pixmap(pixmap);
+	if (priv == NULL) {
+		DBG(("%s: not migrating unattached pixmap\n",
+		     __FUNCTION__));
+		return NULL;
+	}
+
+	if (priv->gpu_bo) {
+		if (priv->cpu_damage &&
+		    sna_damage_contains_box(priv->cpu_damage,
+					    box) != PIXMAN_REGION_OUT) {
+			if (!sna_pixmap_move_to_gpu(pixmap, MOVE_READ))
+				return NULL;
+		}
+
+		return priv->gpu_bo;
+	}
 
 	if (pixmap->usage_hint) {
 		DBG(("%s: not migrating pixmap due to usage_hint=%d\n",
 		     __FUNCTION__, pixmap->usage_hint));
-		return FALSE;
+		return NULL;
 	}
 
 	if (DBG_FORCE_UPLOAD < 0)
-		return TRUE;
+		migrate = true;
 
 	w = box->x2 - box->x1;
 	h = box->y2 - box->y1;
 	if (w == pixmap->drawable.width && h == pixmap->drawable.height) {
-		bool upload;
-
-		priv = sna_pixmap(pixmap);
-		if (!priv) {
-			DBG(("%s: not migrating unattached pixmap\n",
-			     __FUNCTION__));
-			return false;
-		}
-
-		upload = true;
+		migrate = true;
 		if ((priv->create & KGEM_CAN_CREATE_GPU) == 0 ||
 		    kgem_choose_tiling(&to_sna_from_pixmap(pixmap)->kgem,
 				       I915_TILING_X,
 				       pixmap->drawable.width,
 				       pixmap->drawable.height,
 				       pixmap->drawable.bitsPerPixel) == I915_TILING_NONE)
-			upload = priv->source_count++ > SOURCE_BIAS;
+			migrate = priv->source_count++ > SOURCE_BIAS;
 
 		DBG(("%s: migrating whole pixmap (%dx%d) for source (%d,%d),(%d,%d), count %d? %d\n",
 		     __FUNCTION__,
 		     pixmap->drawable.width, pixmap->drawable.height,
 		     box->x1, box->y1, box->x2, box->y2, priv->source_count,
-		     upload));
-		return upload;
+		     migrate));
+	} else {
+		/* ignore tiny fractions */
+		if (64*w*h > pixmap->drawable.width * pixmap->drawable.height) {
+			count = priv->source_count++;
+			if ((priv->create & KGEM_CAN_CREATE_GPU) == 0 ||
+			    kgem_choose_tiling(&to_sna_from_pixmap(pixmap)->kgem,
+					       I915_TILING_X,
+					       pixmap->drawable.width,
+					       pixmap->drawable.height,
+					       pixmap->drawable.bitsPerPixel) == I915_TILING_NONE)
+				count -= SOURCE_BIAS;
+
+			DBG(("%s: migrate box (%d, %d), (%d, %d)? source count=%d, fraction=%d/%d [%d]\n",
+			     __FUNCTION__,
+			     box->x1, box->y1, box->x2, box->y2,
+			     count, w*h,
+			     pixmap->drawable.width * pixmap->drawable.height,
+			     pixmap->drawable.width * pixmap->drawable.height / (w*h)));
+
+			migrate =  count*w*h > pixmap->drawable.width * pixmap->drawable.height;
+		}
 	}
 
-	/* ignore tiny fractions */
-	if (64*w*h < pixmap->drawable.width * pixmap->drawable.height)
-		return FALSE;
-
-	priv = sna_pixmap(pixmap);
-	if (!priv)
-		return FALSE;
-
-	count = priv->source_count++;
-	if ((priv->create & KGEM_CAN_CREATE_GPU) == 0 ||
-	    kgem_choose_tiling(&to_sna_from_pixmap(pixmap)->kgem,
-			       I915_TILING_X,
-			       pixmap->drawable.width,
-			       pixmap->drawable.height,
-			       pixmap->drawable.bitsPerPixel) == I915_TILING_NONE)
-		count -= SOURCE_BIAS;
-
-	DBG(("%s: migrate box (%d, %d), (%d, %d)? source count=%d, fraction=%d/%d [%d]\n",
-	     __FUNCTION__,
-	     box->x1, box->y1, box->x2, box->y2,
-	     count, w*h,
-	     pixmap->drawable.width * pixmap->drawable.height,
-	     pixmap->drawable.width * pixmap->drawable.height / (w*h)));
-
-	return count*w*h > pixmap->drawable.width * pixmap->drawable.height;
-}
-
-static Bool
-_texture_is_cpu(PixmapPtr pixmap, const BoxRec *box)
-{
-	struct sna_pixmap *priv = sna_pixmap(pixmap);
-
-	if (priv == NULL)
-		return TRUE;
-
-	if (priv->gpu_bo == NULL)
-		return TRUE;
-
-	if (!priv->cpu_damage)
-		return FALSE;
-
-	if (DAMAGE_IS_ALL(priv->cpu_damage))
-		return TRUE;
-
-	if (sna_damage_contains_box__no_reduce(priv->cpu_damage, box))
-		return TRUE;
-
-	if (sna_damage_contains_box(priv->gpu_damage, box) != PIXMAN_REGION_OUT)
-		return FALSE;
-
-	return sna_damage_contains_box(priv->cpu_damage, box) != PIXMAN_REGION_OUT;
-}
+	if (migrate && !sna_pixmap_force_to_gpu(pixmap, MOVE_READ))
+		return NULL;
 
-#if DEBUG_RENDER
-static Bool
-texture_is_cpu(PixmapPtr pixmap, const BoxRec *box)
-{
-	Bool ret = _texture_is_cpu(pixmap, box);
-	ErrorF("%s(pixmap=%p, box=((%d, %d), (%d, %d)) = %d\n",
-	       __FUNCTION__, pixmap, box->x1, box->y1, box->x2, box->y2, ret);
-	return ret;
-}
-#else
-static Bool
-texture_is_cpu(PixmapPtr pixmap, const BoxRec *box)
-{
-	return _texture_is_cpu(pixmap, box);
+	return priv->gpu_bo;
 }
-#endif
 
 static struct kgem_bo *upload(struct sna *sna,
 			      struct sna_composite_channel *channel,
@@ -600,16 +566,13 @@ sna_render_pixmap_bo(struct sna *sna,
 	if (bo) {
 		bo = kgem_bo_reference(bo);
 	} else {
-		if (!texture_is_cpu(pixmap, &box) || move_to_gpu(pixmap, &box)) {
-			priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
-			if (priv)
-				bo = kgem_bo_reference(priv->gpu_bo);
-		}
+		bo = move_to_gpu(pixmap, &box);
 		if (bo == NULL) {
 			DBG(("%s: uploading CPU box (%d, %d), (%d, %d)\n",
 			     __FUNCTION__, box.x1, box.y1, box.x2, box.y2));
 			bo = upload(sna, channel, pixmap, &box);
-		}
+		} else
+			bo = kgem_bo_reference(bo);
 	}
 
 	channel->bo = bo;
@@ -1146,18 +1109,8 @@ sna_render_picture_extract(struct sna *sna,
 		if (!sna_pixmap_move_to_cpu(pixmap, MOVE_READ))
 			return 0;
 	} else {
-		bool upload = true;
-		if (!texture_is_cpu(pixmap, &box) ||
-		    move_to_gpu(pixmap, &box)) {
-			struct sna_pixmap *priv;
-
-			priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
-			if (priv) {
-				src_bo = priv->gpu_bo;
-				upload = false;
-			}
-		}
-		if (upload) {
+		src_bo = move_to_gpu(pixmap, &box);
+		if (src_bo == NULL) {
 			bo = kgem_upload_source_image(&sna->kgem,
 						      pixmap->devPrivate.ptr,
 						      &box,
commit 6dfe28f978b59ab2fc44cdd8ddf3743d6507588b
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 13 15:47:27 2012 +0000

    sna/gen6: Remove the double application of the render offset
    
    Cut'n'paste error from an older generation.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 8a8cdd8..fde0776 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -1466,26 +1466,17 @@ gen6_emit_composite_primitive(struct sna *sna,
 			      const struct sna_composite_rectangles *r)
 {
 	gen6_emit_composite_vertex(sna, op,
-				   r->src.x + r->width,
-				   r->src.y + r->height,
-				   r->mask.x + r->width,
-				   r->mask.y + r->height,
-				   op->dst.x + r->dst.x + r->width,
-				   op->dst.y + r->dst.y + r->height);
+				   r->src.x + r->width,  r->src.y + r->height,
+				   r->mask.x + r->width, r->mask.y + r->height,
+				   r->dst.x + r->width, r->dst.y + r->height);
 	gen6_emit_composite_vertex(sna, op,
-				   r->src.x,
-				   r->src.y + r->height,
-				   r->mask.x,
-				   r->mask.y + r->height,
-				   op->dst.x + r->dst.x,
-				   op->dst.y + r->dst.y + r->height);
+				   r->src.x,  r->src.y + r->height,
+				   r->mask.x, r->mask.y + r->height,
+				   r->dst.x,  r->dst.y + r->height);
 	gen6_emit_composite_vertex(sna, op,
-				   r->src.x,
-				   r->src.y,
-				   r->mask.x,
-				   r->mask.y,
-				   op->dst.x + r->dst.x,
-				   op->dst.y + r->dst.y);
+				   r->src.x,  r->src.y,
+				   r->mask.x, r->mask.y,
+				   r->dst.x,  r->dst.y);
 }
 
 static void gen6_emit_vertex_buffer(struct sna *sna,
commit c751242e245eb168b92616bdcea3421be4e420bc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 13 12:04:04 2012 +0000

    sna: Only use the cpu bo for xfer between CPU and GPU if either is busy
    
    The synchronisation costs overwhelm any benefit from offloading the
    copy, unless we are currently streaming the updates anyway.
    
    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 dc330ca..d5420a3 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -857,6 +857,14 @@ sna_pixmap_create_mappable_gpu(PixmapPtr pixmap)
 	return priv->gpu_bo && kgem_bo_is_mappable(&sna->kgem, priv->gpu_bo);
 }
 
+static bool use_cpu_bo_for_xfer(struct sna_pixmap *priv)
+{
+	if (priv->cpu_bo == NULL)
+		return FALSE;
+
+	return kgem_bo_is_busy(priv->gpu_bo) || kgem_bo_is_busy(priv->cpu_bo);
+}
+
 bool
 _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
 {
@@ -1028,16 +1036,12 @@ skip_inplace_map:
 
 		n = sna_damage_get_boxes(priv->gpu_damage, &box);
 		if (n) {
-			struct kgem_bo *dst_bo;
 			Bool ok = FALSE;
 
-			dst_bo = NULL;
-			if (sna->kgem.gen >= 30)
-				dst_bo = priv->cpu_bo;
-			if (dst_bo)
+			if (sna->kgem.gen >= 30 && use_cpu_bo_for_xfer(priv))
 				ok = sna->render.copy_boxes(sna, GXcopy,
 							    pixmap, priv->gpu_bo, 0, 0,
-							    pixmap, dst_bo, 0, 0,
+							    pixmap, priv->cpu_bo, 0, 0,
 							    box, n);
 			if (!ok)
 				sna_read_boxes(sna,
@@ -1421,7 +1425,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 			assert(pixmap_contains_damage(pixmap, priv->gpu_damage));
 
 			ok = FALSE;
-			if (priv->cpu_bo && sna->kgem.gen >= 30)
+			if (sna->kgem.gen >= 30 && use_cpu_bo_for_xfer(priv))
 				ok = sna->render.copy_boxes(sna, GXcopy,
 							    pixmap, priv->gpu_bo, 0, 0,
 							    pixmap, priv->cpu_bo, 0, 0,
@@ -1496,7 +1500,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 				if (n) {
 					Bool ok = FALSE;
 
-					if (priv->cpu_bo && sna->kgem.gen >= 30)
+					if (sna->kgem.gen >= 30 && use_cpu_bo_for_xfer(priv))
 						ok = sna->render.copy_boxes(sna, GXcopy,
 									    pixmap, priv->gpu_bo, 0, 0,
 									    pixmap, priv->cpu_bo, 0, 0,
@@ -1516,10 +1520,9 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 								      &r->extents)) {
 				BoxPtr box = REGION_RECTS(r);
 				int n = REGION_NUM_RECTS(r);
-				Bool ok;
+				Bool ok = FALSE;
 
-				ok = FALSE;
-				if (priv->cpu_bo && sna->kgem.gen >= 30)
+				if (sna->kgem.gen >= 30 && use_cpu_bo_for_xfer(priv))
 					ok = sna->render.copy_boxes(sna, GXcopy,
 								    pixmap, priv->gpu_bo, 0, 0,
 								    pixmap, priv->cpu_bo, 0, 0,
@@ -1539,10 +1542,9 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 				if (sna_damage_intersect(priv->gpu_damage, r, &need)) {
 					BoxPtr box = REGION_RECTS(&need);
 					int n = REGION_NUM_RECTS(&need);
-					Bool ok;
+					Bool ok = FALSE;
 
-					ok = FALSE;
-					if (priv->cpu_bo && sna->kgem.gen >= 30)
+					if (sna->kgem.gen >= 30 && use_cpu_bo_for_xfer(priv))
 						ok = sna->render.copy_boxes(sna, GXcopy,
 									    pixmap, priv->gpu_bo, 0, 0,
 									    pixmap, priv->cpu_bo, 0, 0,
@@ -1732,10 +1734,9 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box, unsigned int flags)
 
 		n = sna_damage_get_boxes(priv->cpu_damage, &box);
 		if (n) {
-			Bool ok;
+			Bool ok = FALSE;
 
-			ok = FALSE;
-			if (priv->cpu_bo)
+			if (use_cpu_bo_for_xfer(priv))
 				ok = sna->render.copy_boxes(sna, GXcopy,
 							    pixmap, priv->cpu_bo, 0, 0,
 							    pixmap, priv->gpu_bo, 0, 0,
@@ -1768,7 +1769,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box, unsigned int flags)
 	} else if (DAMAGE_IS_ALL(priv->cpu_damage) ||
 		   sna_damage_contains_box__no_reduce(priv->cpu_damage, box)) {
 		Bool ok = FALSE;
-		if (priv->cpu_bo)
+		if (use_cpu_bo_for_xfer(priv))
 			ok = sna->render.copy_boxes(sna, GXcopy,
 						    pixmap, priv->cpu_bo, 0, 0,
 						    pixmap, priv->gpu_bo, 0, 0,
@@ -1791,7 +1792,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box, unsigned int flags)
 
 		box = REGION_RECTS(&i);
 		ok = FALSE;
-		if (priv->cpu_bo)
+		if (use_cpu_bo_for_xfer(priv))
 			ok = sna->render.copy_boxes(sna, GXcopy,
 						    pixmap, priv->cpu_bo, 0, 0,
 						    pixmap, priv->gpu_bo, 0, 0,
@@ -2250,7 +2251,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 		DBG(("%s: uploading %d damage boxes\n", __FUNCTION__, n));
 
 		ok = FALSE;
-		if (priv->cpu_bo)
+		if (use_cpu_bo_for_xfer(priv))
 			ok = sna->render.copy_boxes(sna, GXcopy,
 						    pixmap, priv->cpu_bo, 0, 0,
 						    pixmap, priv->gpu_bo, 0, 0,
commit c9668a772f15ab36d643a9b0616b309856146c89
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 23:28:51 2012 +0000

    sna: Reduce OVER with a clear pixmap to a BLT
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 441b24e..6ec4748 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -460,6 +460,13 @@ 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_drawable_is_clear(DrawablePtr d)
+{
+	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
+	return priv && priv->clear && priv->clear_color == 0;
+}
+
 static inline struct kgem_bo *sna_pixmap_get_bo(PixmapPtr pixmap)
 {
 	return sna_pixmap(pixmap)->gpu_bo;
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index eb8dbf8..e7a6182 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -1556,6 +1556,7 @@ sna_blt_composite(struct sna *sna,
 	struct sna_pixmap *priv;
 	int16_t tx, ty;
 	uint32_t alpha_fixup;
+	bool was_clear;
 	Bool ret;
 
 #if DEBUG_NO_BLT || NO_BLT_COMPOSITE
@@ -1576,6 +1577,7 @@ sna_blt_composite(struct sna *sna,
 		return FALSE;
 	}
 
+	was_clear = sna_drawable_is_clear(dst->pDrawable);
 	tmp->dst.pixmap = get_drawable_pixmap(dst->pDrawable);
 	priv = sna_pixmap_move_to_gpu(tmp->dst.pixmap, MOVE_WRITE | MOVE_READ);
 	if (priv == NULL) {
@@ -1606,16 +1608,22 @@ sna_blt_composite(struct sna *sna,
 		_kgem_set_mode(&sna->kgem, KGEM_BLT);
 	}
 
-	if (op == PictOpClear)
+	if (op == PictOpClear) {
+clear:
+		if (was_clear)
+			return TRUE;
 		return prepare_blt_clear(sna, tmp);
+	}
 
 	if (is_solid(src)) {
 		if (op == PictOpOver && is_opaque_solid(src))
 			op = PictOpSrc;
 		if (op == PictOpAdd && is_white(src))
 			op = PictOpSrc;
+		if (was_clear && (op == PictOpAdd || op == PictOpOver))
+			op = PictOpSrc;
 		if (op == PictOpOutReverse && is_opaque_solid(src))
-			return prepare_blt_clear(sna, tmp);
+			goto clear;
 
 		if (op != PictOpSrc) {
 			DBG(("%s: unsuported op [%d] for blitting\n",
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index d2f16f2..933f580 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -3033,13 +3033,6 @@ choose_span(PicturePtr dst,
 }
 
 static bool
-sna_drawable_is_clear(DrawablePtr d)
-{
-	struct sna_pixmap *priv = sna_pixmap(get_drawable_pixmap(d));
-	return priv && priv->clear && priv->clear_color == 0;
-}
-
-static bool
 mono_trapezoids_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 			       INT16 src_x, INT16 src_y,
 			       int ntrap, xTrapezoid *traps)
commit 2ea58256f5ce6e1c0f48d366ff7a1fbf300600de
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 23:05:17 2012 +0000

    sna: Reuse the same upload buffer for the duration of the batch
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index db579d0..cee4513 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1381,7 +1381,9 @@ static void kgem_commit(struct kgem *kgem)
 {
 	struct kgem_request *rq = kgem->next_request;
 	struct kgem_bo *bo, *next;
+	struct list release;
 
+	list_init(&release);
 	list_for_each_entry_safe(bo, next, &rq->buffers, request) {
 		assert(next->request.prev == &bo->request);
 
@@ -1408,8 +1410,21 @@ static void kgem_commit(struct kgem *kgem)
 			/* proxies are not used for domain tracking */
 			list_del(&bo->request);
 			bo->rq = NULL;
+			bo->exec = &_kgem_dummy_exec;
+			if (bo->map)
+				list_add_tail(&bo->request, &release);
 		}
 	}
+	while (!list_is_empty(&release)) {
+		bo = list_first_entry(&release, struct kgem_bo, request);
+		DBG(("%s: releasing upload cache, handle=%d\n",
+		     __FUNCTION__, bo->handle));
+		list_del(&bo->request);
+		assert(*(struct kgem_bo **)bo->map == bo);
+		*(struct kgem_bo **)bo->map = NULL;
+		bo->map = NULL;
+		kgem_bo_destroy(kgem, bo);
+	}
 
 	if (rq == &_kgem_static_request) {
 		struct drm_i915_gem_set_domain set_domain;
@@ -2842,7 +2857,7 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo)
 	DBG(("%s: size=%d, offset=%d, parent used=%d\n",
 	     __FUNCTION__, bo->size.bytes, bo->delta, io->used));
 
-	if (bo->delta + bo->size.bytes == io->used) {
+	if (ALIGN(bo->delta + bo->size.bytes, 64) == io->used) {
 		io->used = bo->delta;
 		bubble_sort_partial(&kgem->active_partials, io);
 	}
@@ -2850,9 +2865,11 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo)
 
 void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 {
+	DBG(("%s: handle=%d, proxy? %d\n",
+	     __FUNCTION__, bo->handle, bo->proxy != NULL));
+
 	if (bo->proxy) {
-		assert(bo->map == NULL);
-		if (bo->io && bo->exec == NULL)
+		if (bo->io && (bo->exec == NULL || bo->proxy->rq == NULL))
 			_kgem_bo_delete_partial(kgem, bo);
 		kgem_bo_unref(kgem, bo->proxy);
 		kgem_bo_binding_free(kgem, bo);
@@ -3873,6 +3890,15 @@ struct kgem_bo *kgem_upload_source_image(struct kgem *kgem,
 	return bo;
 }
 
+void kgem_proxy_bo_attach(struct kgem_bo *bo,
+			  struct kgem_bo **ptr)
+{
+	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
+	assert(bo->map == NULL);
+	bo->map = ptr;
+	*ptr = kgem_bo_reference(bo);
+}
+
 void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *_bo)
 {
 	struct kgem_partial_bo *bo;
@@ -3880,7 +3906,8 @@ void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *_bo)
 	int domain;
 
 	assert(_bo->io);
-	assert(_bo->exec == NULL);
+	assert(_bo->exec == &_kgem_dummy_exec);
+	assert(_bo->rq == NULL);
 	if (_bo->proxy)
 		_bo = _bo->proxy;
 	assert(_bo->exec == NULL);
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index dff8bb2..52e5e9c 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -200,6 +200,7 @@ struct kgem_bo *kgem_upload_source_image(struct kgem *kgem,
 					 const void *data,
 					 BoxPtr box,
 					 int stride, int bpp);
+void kgem_proxy_bo_attach(struct kgem_bo *bo, struct kgem_bo **ptr);
 
 int kgem_choose_tiling(struct kgem *kgem,
 		       int tiling, int width, int height, int bpp);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 1b0ac3c..dc330ca 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1064,8 +1064,10 @@ skip_inplace_map:
 	}
 
 done:
-	if (flags & MOVE_WRITE)
+	if (flags & MOVE_WRITE) {
 		priv->source_count = SOURCE_BIAS;
+		assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL);
+	}
 
 	if ((flags & MOVE_ASYNC_HINT) == 0 && priv->cpu_bo) {
 		DBG(("%s: syncing CPU bo\n", __FUNCTION__));
@@ -1260,6 +1262,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 
 		if (priv->stride && priv->gpu_bo &&
 		    region_inplace(sna, pixmap, region, priv)) {
+			assert(priv->gpu_bo->proxy == NULL);
 			if (sync_will_stall(priv->gpu_bo) &&
 			    priv->gpu_bo->exec == NULL)
 				kgem_retire(&sna->kgem);
@@ -1371,6 +1374,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 	if (priv->gpu_bo == NULL)
 		goto done;
 
+	assert(priv->gpu_bo->proxy == NULL);
 	if (priv->clear) {
 		int n = REGION_NUM_RECTS(region);
 		BoxPtr box = REGION_RECTS(region);
@@ -1581,8 +1585,10 @@ done:
 		RegionTranslate(region, -dx, -dy);
 
 out:
-	if (flags & MOVE_WRITE)
+	if (flags & MOVE_WRITE) {
 		priv->source_count = SOURCE_BIAS;
+		assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL);
+	}
 	if (priv->cpu_bo) {
 		DBG(("%s: syncing cpu bo\n", __FUNCTION__));
 		kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo);
@@ -1942,6 +1948,7 @@ done:
 
 	DBG(("%s: using GPU bo with damage? %d\n",
 	     __FUNCTION__, *damage != NULL));
+	assert(priv->gpu_bo->proxy == NULL);
 	return priv->gpu_bo;
 
 use_gpu_bo:
@@ -1951,6 +1958,7 @@ use_gpu_bo:
 			  &to_sna_from_pixmap(pixmap)->active_pixmaps);
 	*damage = NULL;
 	DBG(("%s: using whole GPU bo\n", __FUNCTION__));
+	assert(priv->gpu_bo->proxy == NULL);
 	return priv->gpu_bo;
 
 use_cpu_bo:
@@ -2083,6 +2091,7 @@ sna_pixmap_force_to_gpu(PixmapPtr pixmap, unsigned flags)
 
 	if (DAMAGE_IS_ALL(priv->gpu_damage)) {
 		DBG(("%s: GPU all-damaged\n", __FUNCTION__));
+		assert(!priv->gpu_bo->proxy || (flags & MOVE_WRITE) == 0);
 		return sna_pixmap_mark_active(to_sna_from_pixmap(pixmap), priv);
 	}
 
@@ -2285,6 +2294,7 @@ done:
 		}
 	}
 active:
+	assert(!priv->gpu_bo->proxy || (flags & MOVE_WRITE) == 0);
 	return sna_pixmap_mark_active(sna, priv);
 }
 
@@ -2532,6 +2542,8 @@ static bool upload_inplace(struct sna *sna,
 		return false;
 
 	if (priv->gpu_bo) {
+		assert(priv->gpu_bo->proxy == NULL);
+
 		if (!kgem_bo_map_will_stall(&sna->kgem, priv->gpu_bo))
 			return true;
 
@@ -3389,6 +3401,8 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 		dst_priv->clear = false;
 	}
 
+	assert(dst_priv->gpu_bo == NULL || dst_priv->gpu_bo->proxy == NULL);
+
 	/* Try to maintain the data on the GPU */
 	if (dst_priv->gpu_bo == NULL &&
 	    ((dst_priv->cpu_damage == NULL && copy_use_gpu_bo(sna, dst_priv, &region)) ||
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 09a33c1..b5d314b 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -496,6 +496,14 @@ static struct kgem_bo *upload(struct sna *sna,
 		channel->offset[1] -= box->y1;
 		channel->scale[0] = 1.f/channel->width;
 		channel->scale[1] = 1.f/channel->height;
+
+		if (pixmap->usage_hint == 0 &&
+		    channel->width  == pixmap->drawable.width &&
+		    channel->height == pixmap->drawable.height) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv)
+				kgem_proxy_bo_attach(bo, &priv->gpu_bo);
+		}
 	}
 
 	return bo;
@@ -526,7 +534,8 @@ sna_render_pixmap_bo(struct sna *sna,
 	priv = sna_pixmap(pixmap);
 	if (priv) {
 		if (priv->gpu_bo &&
-		    (DAMAGE_IS_ALL(priv->gpu_damage) || !priv->cpu_damage)) {
+		    (DAMAGE_IS_ALL(priv->gpu_damage) || !priv->cpu_damage ||
+		     priv->gpu_bo->proxy)) {
 			channel->bo = kgem_bo_reference(priv->gpu_bo);
 			return 1;
 		}
@@ -1148,12 +1157,20 @@ sna_render_picture_extract(struct sna *sna,
 				upload = false;
 			}
 		}
-		if (upload)
+		if (upload) {
 			bo = kgem_upload_source_image(&sna->kgem,
 						      pixmap->devPrivate.ptr,
 						      &box,
 						      pixmap->devKind,
 						      pixmap->drawable.bitsPerPixel);
+			if (pixmap->usage_hint == 0 &&
+			    box.x2 - box.x1 == pixmap->drawable.width &&
+			    box.y2 - box.y1 == pixmap->drawable.height) {
+				struct sna_pixmap *priv = sna_pixmap(pixmap);
+				if (priv)
+					kgem_proxy_bo_attach(bo, &priv->gpu_bo);
+			}
+		}
 	}
 	if (src_bo) {
 		bo = kgem_create_2d(&sna->kgem, w, h,
commit 8b9abe2be1f54bd8e8593ed155cc4725ac97627a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 21:09:19 2012 +0000

    sna: Prefer to render very thin trapezoids inplace
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index e6015af..8d3d9e4 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -204,6 +204,7 @@ struct sna_render {
 				unsigned flags,
 				struct sna_composite_spans_op *tmp);
 #define COMPOSITE_SPANS_RECTILINEAR 0x1
+#define COMPOSITE_SPANS_INPLACE_HINT 0x2
 
 	Bool (*video)(struct sna *sna,
 		      struct sna_video *video,
diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index a523fed..88d0130 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -85,7 +85,13 @@ static inline Bool
 is_cpu(DrawablePtr drawable)
 {
 	struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable);
-	return !priv || priv->cpu_damage != NULL;
+	if (priv == NULL || priv->clear || DAMAGE_IS_ALL(priv->cpu_damage))
+		return true;
+
+	if (priv->gpu_damage || (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo)))
+		return false;
+
+	return true;
 }
 
 static inline Bool
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 23a65ef..d2f16f2 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -3180,7 +3180,8 @@ mono_trapezoids_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 
 static bool
 trapezoid_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
-			 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+			 PictFormatPtr maskFormat, unsigned int flags,
+			 INT16 src_x, INT16 src_y,
 			 int ntrap, xTrapezoid *traps)
 {
 	struct sna *sna;
@@ -3263,8 +3264,7 @@ trapezoid_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 					 extents.x1,  extents.y1,
 					 extents.x2 - extents.x1,
 					 extents.y2 - extents.y1,
-					 0,
-					 &tmp)) {
+					 flags, &tmp)) {
 		DBG(("%s: fallback -- composite spans render op not supported\n",
 		     __FUNCTION__));
 		return false;
@@ -3776,6 +3776,40 @@ mono_inplace_composite_boxes(struct sna *sna,
 }
 
 static bool
+trapezoid_spans_maybe_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
+			      PictFormatPtr maskFormat)
+{
+	if (NO_SCAN_CONVERTER)
+		return false;
+
+	if (dst->polyMode == PolyModePrecise && !is_mono(dst, maskFormat))
+		return false;
+	if (dst->alphaMap)
+		return false;
+
+	if (is_mono(dst, maskFormat))
+		goto out;
+
+	if (!sna_picture_is_solid(src, NULL))
+		return false;
+
+	if (dst->format != PICT_a8)
+		return false;
+
+	switch (op) {
+	case PictOpIn:
+	case PictOpAdd:
+	case PictOpSrc:
+		break;
+	default:
+		return false;
+	}
+
+out:
+	return is_cpu(dst->pDrawable) ? true : dst->pDrawable->width <= TOR_INPLACE_SIZE;
+}
+
+static bool
 trapezoid_span_mono_inplace(CARD8 op,
 			    PicturePtr src,
 			    PicturePtr dst,
@@ -4304,6 +4338,7 @@ sna_composite_trapezoids(CARD8 op,
 {
 	struct sna *sna = to_sna_from_drawable(dst->pDrawable);
 	bool rectilinear, pixel_aligned;
+	unsigned flags;
 	int n;
 
 	DBG(("%s(op=%d, src=(%d, %d), mask=%08x, ntrap=%d)\n", __FUNCTION__,
@@ -4370,8 +4405,9 @@ sna_composite_trapezoids(CARD8 op,
 		}
 	}
 
-	DBG(("%s: rectlinear? %d, pixel-aligned? %d\n",
+	DBG(("%s: rectilinear? %d, pixel-aligned? %d\n",
 	     __FUNCTION__, rectilinear, pixel_aligned));
+	flags = 0;
 	if (rectilinear) {
 		if (pixel_aligned) {
 			if (composite_aligned_boxes(sna, op, src, dst,
@@ -4386,9 +4422,17 @@ sna_composite_trapezoids(CARD8 op,
 						      ntrap, traps))
 				return;
 		}
+		flags |= COMPOSITE_SPANS_RECTILINEAR;
+	}
+	if (trapezoid_spans_maybe_inplace(op, src, dst, maskFormat)) {
+		flags |= COMPOSITE_SPANS_INPLACE_HINT;
+		if (trapezoid_span_inplace(op, src, dst, maskFormat,
+					   xSrc, ySrc, ntrap, traps,
+					   false))
+			return;
 	}
 
-	if (trapezoid_span_converter(op, src, dst, maskFormat,
+	if (trapezoid_span_converter(op, src, dst, maskFormat, flags,
 				     xSrc, ySrc, ntrap, traps))
 		return;
 
commit 1e2d6ee31a21267ba27e4bebb883aaab08a12f30
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 20:34:42 2012 +0000

    sna: Always reset the source counter after rendering to with the CPU
    
    The goal is to avoid moving to the GPU too early for a frequently
    modified CPU buffer.
    
    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 2e3df8a..1b0ac3c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1061,11 +1061,12 @@ skip_inplace_map:
 
 		if (priv->flush)
 			list_move(&priv->list, &sna->dirty_pixmaps);
-
-		priv->source_count = SOURCE_BIAS;
 	}
 
 done:
+	if (flags & MOVE_WRITE)
+		priv->source_count = SOURCE_BIAS;
+
 	if ((flags & MOVE_ASYNC_HINT) == 0 && priv->cpu_bo) {
 		DBG(("%s: syncing CPU bo\n", __FUNCTION__));
 		kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo);
@@ -1580,6 +1581,8 @@ done:
 		RegionTranslate(region, -dx, -dy);
 
 out:
+	if (flags & MOVE_WRITE)
+		priv->source_count = SOURCE_BIAS;
 	if (priv->cpu_bo) {
 		DBG(("%s: syncing cpu bo\n", __FUNCTION__));
 		kgem_bo_sync__cpu(&sna->kgem, priv->cpu_bo);
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 11549b4..09a33c1 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -393,10 +393,10 @@ move_to_gpu(PixmapPtr pixmap, const BoxRec *box)
 				       pixmap->drawable.bitsPerPixel) == I915_TILING_NONE)
 			upload = priv->source_count++ > SOURCE_BIAS;
 
-		DBG(("%s: migrating whole pixmap (%dx%d) for source (%d,%d),(%d,%d)? %d\n",
+		DBG(("%s: migrating whole pixmap (%dx%d) for source (%d,%d),(%d,%d), count %d? %d\n",
 		     __FUNCTION__,
 		     pixmap->drawable.width, pixmap->drawable.height,
-		     box->x1, box->y1, box->x2, box->y2,
+		     box->x1, box->y1, box->x2, box->y2, priv->source_count,
 		     upload));
 		return upload;
 	}
commit 7bde1f55a1075eefab0f083833508265fc0e91e7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 20:25:50 2012 +0000

    sna: After move-to-gpu signals yes, force the GPU bo creation
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index d1e3500..11549b4 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -591,22 +591,16 @@ sna_render_pixmap_bo(struct sna *sna,
 	if (bo) {
 		bo = kgem_bo_reference(bo);
 	} else {
-		if (texture_is_cpu(pixmap, &box) && !move_to_gpu(pixmap, &box)) {
+		if (!texture_is_cpu(pixmap, &box) || move_to_gpu(pixmap, &box)) {
+			priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
+			if (priv)
+				bo = kgem_bo_reference(priv->gpu_bo);
+		}
+		if (bo == NULL) {
 			DBG(("%s: uploading CPU box (%d, %d), (%d, %d)\n",
 			     __FUNCTION__, box.x1, box.y1, box.x2, box.y2));
 			bo = upload(sna, channel, pixmap, &box);
 		}
-
-		if (bo == NULL) {
-			priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ);
-			if (priv) {
-				bo = kgem_bo_reference(priv->gpu_bo);
-			} else {
-				DBG(("%s: failed to upload pixmap to gpu, uploading CPU box (%d, %d), (%d, %d) instead\n",
-				     __FUNCTION__, box.x1, box.y1, box.x2, box.y2));
-				bo = upload(sna, channel, pixmap, &box);
-			}
-		}
 	}
 
 	channel->bo = bo;
@@ -1148,7 +1142,7 @@ sna_render_picture_extract(struct sna *sna,
 		    move_to_gpu(pixmap, &box)) {
 			struct sna_pixmap *priv;
 
-			priv = sna_pixmap_move_to_gpu(pixmap, MOVE_READ);
+			priv = sna_pixmap_force_to_gpu(pixmap, MOVE_READ);
 			if (priv) {
 				src_bo = priv->gpu_bo;
 				upload = false;
commit 2ee7de1f1711d1058e5812c6aa0d94ecf9af7d8d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 20:09:05 2012 +0000

    sna/trapezoids: Reduce mono ADD/OVER against a clear background to a SRC
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index f936b4b..23a65ef 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -3849,6 +3849,7 @@ trapezoid_span_mono_inplace(CARD8 op,
 
 	if (sna_picture_is_solid(src, &inplace.fill.color) &&
 	    (op == PictOpSrc || op == PictOpClear ||
+	     (was_clear && (op == PictOpOver || op == PictOpAdd)) ||
 	     (op == PictOpOver && inplace.fill.color >> 24 == 0xff))) {
 		PixmapPtr pixmap;
 		int16_t dx, dy;
commit 99c239e380b9f5134afc75bf55bf3f69e5113e38
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 19:49:30 2012 +0000

    sna: Treat backing pixmaps no differently from their forward facing cousins
    
    Another fix for the large buffers overhaul.
    
    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 3619101..2e3df8a 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -395,13 +395,6 @@ static inline uint32_t default_tiling(PixmapPtr pixmap)
 	if (sna->kgem.gen == 21)
 		return I915_TILING_X;
 
-	if (pixmap->usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP) {
-		/* Treat this like a window, and require accelerated
-		 * scrolling i.e. overlapped blits.
-		 */
-		return I915_TILING_X;
-	}
-
 	if (sna_damage_is_all(&priv->cpu_damage,
 			      pixmap->drawable.width,
 			      pixmap->drawable.height)) {
@@ -765,6 +758,8 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 
 	if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE)
 		flags &= ~KGEM_CAN_CREATE_GPU;
+	if (usage == CREATE_PIXMAP_USAGE_BACKING_PIXMAP)
+		usage = 0;
 
 force_create:
 	pad = PixmapBytePad(width, depth);
commit 28792be1f31190171644d911d7b5573186fe2df2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 19:45:35 2012 +0000

    sna/display: Only flush pending output when installing a new scanout
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 676125d..9401ca4 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -634,8 +634,10 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	     sna_mode->fb_pixmap,
 	     sna->front->drawable.serialNumber));
 
-	if (sna_mode->fb_pixmap != sna->front->drawable.serialNumber)
+	if (sna_mode->fb_pixmap != sna->front->drawable.serialNumber) {
+		kgem_submit(&sna->kgem);
 		sna_mode_remove_fb(sna);
+	}
 
 	if (sna_mode->fb_id == 0) {
 		struct kgem_bo *bo = sna_pixmap_pin(sna->front);
@@ -677,8 +679,6 @@ sna_crtc_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 	crtc->y = y;
 	crtc->rotation = rotation;
 
-	kgem_submit(&sna->kgem);
-
 	mode_to_kmode(&sna_crtc->kmode, mode);
 	if (!sna_crtc_apply(crtc)) {
 		crtc->x = saved_x;


More information about the xorg-commit mailing list