xf86-video-intel: 7 commits - src/sna/kgem.c src/sna/kgem.h src/sna/sna_accel.c src/sna/sna_display.c src/sna/sna_io.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Jun 18 05:39:00 PDT 2013


 src/sna/kgem.c        |   53 +++++++++++++++++++-----
 src/sna/kgem.h        |   28 ++++--------
 src/sna/sna_accel.c   |  108 +++++++++++++++++++++++++++++++++++++++++++-------
 src/sna/sna_display.c |    2 
 src/sna/sna_io.c      |   69 +++++++++++++++----------------
 5 files changed, 179 insertions(+), 81 deletions(-)

New commits:
commit c3695c3c6b7bc13b5e642c9d92648e8228411bed
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 18 09:41:20 2013 +0100

    sna: Specialise mi calls to PolyFillRect
    
    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 21130de..21427fa 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -207,6 +207,9 @@ static GCOps sna_gc_ops__tmp;
 static const GCFuncs sna_gc_funcs;
 static const GCFuncs sna_gc_funcs__cpu;
 
+static void
+sna_poly_fill_rect__gpu(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect);
+
 static inline void region_set(RegionRec *r, const BoxRec *b)
 {
 	r->extents = *b;
@@ -8042,6 +8045,7 @@ spans_fallback:
 			 * cannot use the fill fast paths.
 			 */
 			sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu;
+			sna_gc_ops__tmp.PolyFillRect = sna_poly_fill_rect__gpu;
 			gc->ops = &sna_gc_ops__tmp;
 
 			switch (gc->lineStyle) {
@@ -12365,6 +12369,45 @@ out:
 }
 
 static void
+sna_poly_fill_rect__gpu(DrawablePtr draw, GCPtr gc, int n, xRectangle *r)
+{
+	struct sna_fill_spans *data = sna_gc(gc)->priv;
+	uint32_t color;
+
+	DBG(("%s(n=%d, PlaneMask: %lx (solid %d), solid fill: %d [style=%d, tileIsPixel=%d], alu=%d)\n", __FUNCTION__,
+	     n, gc->planemask, !!PM_IS_SOLID(draw, gc->planemask),
+	     (gc->fillStyle == FillSolid ||
+	      (gc->fillStyle == FillTiled && gc->tileIsPixel)),
+	     gc->fillStyle, gc->tileIsPixel,
+	     gc->alu));
+
+	assert(PM_IS_SOLID(draw, gc->planemask));
+	if (n == 0)
+		return;
+
+	/* The mi routines do not attempt to keep the spans it generates
+	 * within the clip, so we must run them through the clipper.
+	 */
+
+	if (gc_is_solid(gc, &color)) {
+		(void)sna_poly_fill_rect_blt(draw,
+					     data->bo, data->damage,
+					     gc, color, n, r,
+					     &data->region.extents, true);
+	} else if (gc->fillStyle == FillTiled) {
+		(void)sna_poly_fill_rect_tiled_blt(draw,
+						   data->bo, data->damage,
+						   gc, n, r,
+						   &data->region.extents, true);
+	} else {
+		(void)sna_poly_fill_rect_stippled_blt(draw,
+						    data->bo, data->damage,
+						    gc, n, r,
+						    &data->region.extents, true);
+	}
+}
+
+static void
 sna_poly_fill_arc(DrawablePtr draw, GCPtr gc, int n, xArc *arc)
 {
 	struct sna_fill_spans data;
commit 40329e34b9ac65d930757d53283b7d8f4066c3a2
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Jun 15 13:25:39 2013 +0100

    sna: Add extra assertions to sanity check CPU access is coherent
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 65d1205..66dce47 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -104,7 +104,6 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags);
 #define MAX_CPU_VMA_CACHE INT16_MAX
 #define MAP_PRESERVE_TIME 10
 
-#define MAP(ptr) ((void*)((uintptr_t)(ptr) & ~3))
 #define MAKE_CPU_MAP(ptr) ((void*)((uintptr_t)(ptr) | 1))
 #define MAKE_USER_MAP(ptr) ((void*)((uintptr_t)(ptr) | 3))
 #define IS_USER_MAP(ptr) ((uintptr_t)(ptr) & 2)
@@ -5659,6 +5658,7 @@ struct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem,
 		bo->size.bytes -= stride;
 	}
 
+	bo->map = MAKE_CPU_MAP(*ret);
 	bo->pitch = stride;
 	bo->unique_id = kgem_get_unique_id(kgem);
 	return bo;
@@ -5703,7 +5703,7 @@ 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);
+	assert(bo->map == NULL || IS_CPU_MAP(bo->map));
 	assert(bo->proxy);
 	list_add(&bo->vma, &bo->proxy->vma);
 	bo->map = ptr;
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index ae5aafa..33a4db0 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -58,6 +58,7 @@ struct kgem_bo {
 	void *map;
 #define IS_CPU_MAP(ptr) ((uintptr_t)(ptr) & 1)
 #define IS_GTT_MAP(ptr) (ptr && ((uintptr_t)(ptr) & 1) == 0)
+#define MAP(ptr) ((void*)((uintptr_t)(ptr) & ~3))
 
 	struct kgem_bo_binding {
 		struct kgem_bo_binding *next;
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index b848ac0..21130de 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1412,6 +1412,24 @@ static inline bool has_coherent_map(struct sna *sna,
 	return bo->domain == DOMAIN_CPU || sna->kgem.has_llc;
 }
 
+static inline bool has_coherent_ptr(struct sna_pixmap *priv)
+{
+	if (priv == NULL)
+		return true;
+
+	if (!priv->mapped) {
+		if (!priv->cpu_bo)
+			return true;
+
+		return priv->pixmap->devPrivate.ptr == MAP(priv->cpu_bo->map);
+	}
+
+	if (priv->cpu && !IS_CPU_MAP(priv->gpu_bo->map))
+		return false;
+
+	return priv->pixmap->devPrivate.ptr == MAP(priv->gpu_bo->map);
+}
+
 static inline bool pixmap_inplace(struct sna *sna,
 				  PixmapPtr pixmap,
 				  struct sna_pixmap *priv,
@@ -2006,11 +2024,13 @@ skip_inplace_map:
 							    pixmap, priv->cpu_bo, 0, 0,
 							    box, n, COPY_LAST);
 			}
-			if (!ok)
+			if (!ok) {
+				assert(has_coherent_ptr(sna_pixmap(pixmap)));
 				sna_read_boxes(sna,
 					       priv->gpu_bo, 0, 0,
 					       pixmap, 0, 0,
 					       box, n);
+			}
 		}
 
 		__sna_damage_destroy(DAMAGE_PTR(priv->gpu_damage));
@@ -2068,6 +2088,7 @@ done:
 	assert(pixmap->devPrivate.ptr);
 	assert(pixmap->devKind);
 	assert_pixmap_damage(pixmap);
+	assert(has_coherent_ptr(sna_pixmap(pixmap)));
 	return true;
 }
 
@@ -2389,11 +2410,13 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 							    pixmap, priv->cpu_bo, 0, 0,
 							    box, n, COPY_LAST);
 			}
-			if (!ok)
+			if (!ok) {
+				assert(has_coherent_ptr(sna_pixmap(pixmap)));
 				sna_read_boxes(sna,
 					       priv->gpu_bo, 0, 0,
 					       pixmap, 0, 0,
 					       box, n);
+			}
 		}
 		sna_damage_destroy(&priv->gpu_damage);
 	}
@@ -2504,11 +2527,13 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 									    box, n, COPY_LAST);
 					}
 
-					if (!ok)
+					if (!ok) {
+						assert(has_coherent_ptr(sna_pixmap(pixmap)));
 						sna_read_boxes(sna,
 							       priv->gpu_bo, 0, 0,
 							       pixmap, 0, 0,
 							       box, n);
+					}
 				}
 
 				sna_damage_destroy(&priv->gpu_damage);
@@ -2529,11 +2554,13 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 								    pixmap, priv->cpu_bo, 0, 0,
 								    box, n, COPY_LAST);
 				}
-				if (!ok)
+				if (!ok) {
+					assert(has_coherent_ptr(sna_pixmap(pixmap)));
 					sna_read_boxes(sna,
 						       priv->gpu_bo, 0, 0,
 						       pixmap, 0, 0,
 						       box, n);
+				}
 
 				sna_damage_subtract(&priv->gpu_damage, r);
 			} else {
@@ -2555,11 +2582,13 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 									    pixmap, priv->cpu_bo, 0, 0,
 									    box, n, COPY_LAST);
 					}
-					if (!ok)
+					if (!ok) {
+						assert(has_coherent_ptr(sna_pixmap(pixmap)));
 						sna_read_boxes(sna,
 							       priv->gpu_bo, 0, 0,
 							       pixmap, 0, 0,
 							       box, n);
+					}
 
 					sna_damage_subtract(&priv->gpu_damage, r);
 					RegionUninit(&need);
@@ -2617,6 +2646,7 @@ out:
 	assert(pixmap->devPrivate.ptr);
 	assert(pixmap->devKind);
 	assert_pixmap_damage(pixmap);
+	assert(has_coherent_ptr(sna_pixmap(pixmap)));
 	return true;
 }
 
@@ -3380,6 +3410,7 @@ sna_pixmap_create_upload(ScreenPtr screen,
 		FreePixmap(pixmap);
 		return NullPixmap;
 	}
+	priv->mapped = true;
 
 	/* Marking both the shadow and the GPU bo is a little dubious,
 	 * but will work so long as we always check before doing the
@@ -3881,6 +3912,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
 		assert(box->x2 - x <= w);
 		assert(box->y2 - y <= h);
 
+		assert(has_coherent_ptr(sna_pixmap(pixmap)));
 		memcpy_blt(bits, pixmap->devPrivate.ptr,
 			   pixmap->drawable.bitsPerPixel,
 			   stride, pixmap->devKind,
@@ -4922,6 +4954,8 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 				assert(box[i].x2 + dx <= tmp->drawable.width);
 				assert(box[i].y2 + dy <= tmp->drawable.height);
 
+				assert(has_coherent_ptr(sna_pixmap(src_pixmap)));
+				assert(has_coherent_ptr(sna_pixmap(tmp)));
 				memcpy_blt(src_pixmap->devPrivate.ptr,
 					   tmp->devPrivate.ptr,
 					   src_pixmap->drawable.bitsPerPixel,
@@ -5093,7 +5127,8 @@ fallback:
 				assert(box->y1 + src_dy >= 0);
 				assert(box->x2 + src_dx <= src_pixmap->drawable.width);
 				assert(box->y2 + src_dy <= src_pixmap->drawable.height);
-
+				assert(has_coherent_ptr(sna_pixmap(src_pixmap)));
+				assert(has_coherent_ptr(sna_pixmap(dst_pixmap)));
 				memcpy_blt(src_bits, dst_bits, bpp,
 					   src_stride, dst_stride,
 					   box->x1, box->y1,
@@ -10092,6 +10127,7 @@ sna_pixmap_get_source_bo(PixmapPtr pixmap)
 		if (upload == NULL)
 			return NULL;
 
+		assert(has_coherent_ptr(sna_pixmap(pixmap)));
 		memcpy_blt(pixmap->devPrivate.ptr, ptr,
 			   pixmap->drawable.bitsPerPixel,
 			   pixmap->devKind, upload->pitch,
@@ -10443,6 +10479,7 @@ sna_poly_fill_rect_tiled_nxm_blt(DrawablePtr drawable,
 
 	assert(tile->drawable.height && tile->drawable.height <= 8);
 	assert(tile->drawable.width && tile->drawable.width <= 8);
+	assert(has_coherent_ptr(sna_pixmap(tile)));
 
 	cpp = tile->drawable.bitsPerPixel/8;
 	for (h = 0; h < tile->drawable.height; h++) {
@@ -13993,6 +14030,7 @@ sna_get_image(DrawablePtr drawable,
 		     region.extents.x1, region.extents.y1,
 		     region.extents.x2, region.extents.y2));
 		get_drawable_deltas(drawable, pixmap, &dx, &dy);
+		assert(has_coherent_ptr(sna_pixmap(pixmap)));
 		memcpy_blt(pixmap->devPrivate.ptr, dst, drawable->bitsPerPixel,
 			   pixmap->devKind, PixmapBytePad(w, drawable->depth),
 			   region.extents.x1 + dx,
@@ -14391,6 +14429,8 @@ fallback:
 				assert(box->x2 <= src->drawable.width);
 				assert(box->y2 <= src->drawable.height);
 
+				assert(has_coherent_ptr(sna_pixmap(src)));
+				assert(has_coherent_ptr(sna_pixmap(dst)));
 				memcpy_blt(src->devPrivate.ptr,
 					   dst->devPrivate.ptr,
 					   src->drawable.bitsPerPixel,
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index 3febc27..1ec1a60 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -74,6 +74,7 @@ static void read_boxes_inplace(struct kgem *kgem,
 	if (src == NULL)
 		return;
 
+	assert(src != dst);
 	do {
 		DBG(("%s: copying box (%d, %d), (%d, %d)\n",
 		     __FUNCTION__, box->x1, box->y1, box->x2, box->y2));
commit abb522e07a2c3bf39e2587ddedc4bb8ac955c536
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 18 09:01:49 2013 +0100

    sna: Do not sync after a failed mapping
    
    The domain update should be a redundant operation, causing needless
    extra transitions.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 41ed27d..65d1205 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -4607,7 +4607,8 @@ void *kgem_bo_map(struct kgem *kgem, struct kgem_bo *bo)
 		DBG(("%s: converting request for GTT map into CPU map\n",
 		     __FUNCTION__));
 		ptr = kgem_bo_map__cpu(kgem, bo);
-		kgem_bo_sync__cpu(kgem, bo);
+		if (ptr)
+			kgem_bo_sync__cpu(kgem, bo);
 		return ptr;
 	}
 
commit 6086abca13efdeaf9b24c9fbe425546cbe2cfb12
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 17 22:44:58 2013 +0100

    sna: Try falling back through an upload if inplace mapping fails
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 6ef9f18..41ed27d 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1484,6 +1484,7 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
 {
 	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
 	assert(bo->refcnt == 0);
+	assert(bo->proxy == NULL);
 	assert(bo->exec == NULL);
 	assert(!bo->snoop || bo->rq == NULL);
 
@@ -5635,6 +5636,7 @@ struct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem,
 		return NULL;
 	}
 	assert(*ret != NULL);
+	assert(bo->proxy != NULL);
 
 	if (height & 1) {
 		struct kgem_buffer *io = (struct kgem_buffer *)bo->proxy;
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index 14c0d8c..3febc27 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -1392,48 +1392,44 @@ bool sna_replace(struct sna *sna,
 			bo = new_bo;
 	}
 
-	if (bo->tiling == I915_TILING_NONE && bo->pitch == stride) {
-		if (!kgem_bo_write(kgem, bo, src,
-				   (pixmap->drawable.height-1)*stride + pixmap->drawable.width*pixmap->drawable.bitsPerPixel/8))
-			goto err;
-	} else {
-		if (upload_inplace__tiled(kgem, bo)) {
-			BoxRec box;
+	if (bo->tiling == I915_TILING_NONE && bo->pitch == stride &&
+	    kgem_bo_write(kgem, bo, src,
+			  (pixmap->drawable.height-1)*stride + pixmap->drawable.width*pixmap->drawable.bitsPerPixel/8))
+			goto done;
 
-			box.x1 = box.y1 = 0;
-			box.x2 = pixmap->drawable.width;
-			box.y2 = pixmap->drawable.height;
+	if (upload_inplace__tiled(kgem, bo)) {
+		BoxRec box;
 
-			if (write_boxes_inplace__tiled(kgem, src,
-						       stride, pixmap->drawable.bitsPerPixel, 0, 0,
-						       bo, 0, 0, &box, 1))
-				goto done;
-		}
+		box.x1 = box.y1 = 0;
+		box.x2 = pixmap->drawable.width;
+		box.y2 = pixmap->drawable.height;
 
-		if (kgem_bo_is_mappable(kgem, bo)) {
-			dst = kgem_bo_map(kgem, bo);
-			if (!dst)
-				goto err;
+		if (write_boxes_inplace__tiled(kgem, src,
+					       stride, pixmap->drawable.bitsPerPixel, 0, 0,
+					       bo, 0, 0, &box, 1))
+			goto done;
+	}
 
-			memcpy_blt(src, dst, pixmap->drawable.bitsPerPixel,
-				   stride, bo->pitch,
-				   0, 0,
-				   0, 0,
-				   pixmap->drawable.width,
-				   pixmap->drawable.height);
-		} else {
-			BoxRec box;
+	if (kgem_bo_is_mappable(kgem, bo) &&
+	    (dst = kgem_bo_map(kgem, bo)) != NULL) {
+		memcpy_blt(src, dst, pixmap->drawable.bitsPerPixel,
+			   stride, bo->pitch,
+			   0, 0,
+			   0, 0,
+			   pixmap->drawable.width,
+			   pixmap->drawable.height);
+	} else {
+		BoxRec box;
 
-			box.x1 = 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 (!sna_write_boxes(sna, pixmap,
-					     bo, 0, 0,
-					     src, stride, 0, 0,
-					     &box, 1))
-				goto err;
-		}
+		if (!sna_write_boxes(sna, pixmap,
+				     bo, 0, 0,
+				     src, stride, 0, 0,
+				     &box, 1))
+			goto err;
 	}
 
 done:
commit a86b217934a9a16843ac17b38cd5b61393f65aa0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jun 18 09:45:08 2013 +0100

    sna: Mark the base bo as unreusable for temporary mappings
    
    Update required after forcing unaligned userptr to use proxies.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index cdd4d03..ae5aafa 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -606,6 +606,13 @@ static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
 	return kgem_bo_is_busy(bo);
 }
 
+static inline void kgem_bo_mark_unreusable(struct kgem_bo *bo)
+{
+	while (bo->proxy)
+		bo = bo->proxy;
+	bo->reusable = false;
+}
+
 static inline bool kgem_bo_is_dirty(struct kgem_bo *bo)
 {
 	if (bo == NULL)
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index cb75dda..b848ac0 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -4853,7 +4853,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 			if (src_bo) {
 				src_bo->flush = true;
 				src_bo->pitch = src_pixmap->devKind;
-				src_bo->reusable = false;
+				kgem_bo_mark_unreusable(src_bo);
 
 				ok = sna->render.copy_boxes(sna, alu,
 							    src_pixmap, src_bo, src_dx, src_dy,
@@ -13927,7 +13927,7 @@ sna_get_image_blt(DrawablePtr drawable,
 
 		dst_bo->flush = true;
 		dst_bo->pitch = pitch;
-		dst_bo->reusable = false;
+		kgem_bo_mark_unreusable(dst_bo);
 
 		get_drawable_deltas(drawable, pixmap, &dx, &dy);
 
commit ca913e8f1e4b113af3a30cca50679436df23bef1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 17 22:44:20 2013 +0100

    sna: Unwrap proxies for subpage offset SHM pixmaps during sync
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 214487c..6ef9f18 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -4897,9 +4897,12 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem,
 void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 {
 	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
-	assert(bo->proxy == NULL);
 	kgem_bo_submit(kgem, bo);
 
+	/* SHM pixmaps use proxies for subpage offsets */
+	while (bo->proxy)
+		bo = bo->proxy;
+
 	if (bo->domain != DOMAIN_CPU) {
 		struct drm_i915_gem_set_domain set_domain;
 
@@ -4923,11 +4926,14 @@ void kgem_bo_sync__cpu(struct kgem *kgem, struct kgem_bo *bo)
 void kgem_bo_sync__cpu_full(struct kgem *kgem, struct kgem_bo *bo, bool write)
 {
 	DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
-	assert(bo->proxy == NULL);
 
 	if (write || bo->needs_flush)
 		kgem_bo_submit(kgem, bo);
 
+	/* SHM pixmaps use proxies for subpage offsets */
+	while (bo->proxy)
+		bo = bo->proxy;
+
 	if (bo->domain != DOMAIN_CPU) {
 		struct drm_i915_gem_set_domain set_domain;
 
commit d54049808daafed12cf99ff6a1a7395136ab1dc6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 12 19:13:12 2013 +0100

    sna: Refactor scanout flushing
    
    In preparation for extending the kernel interface to be more explicit
    about when we need to flush a direct write to the scanout.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 47c5c12..214487c 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1638,7 +1638,7 @@ static void kgem_bo_clear_scanout(struct kgem *kgem, struct kgem_bo *bo)
 	     __FUNCTION__, bo->handle, bo->delta, bo->reusable));
 	if (bo->delta) {
 		/* XXX will leak if we are not DRM_MASTER. *shrug* */
-		drmModeRmFB(kgem->fd, bo->delta);
+		drmIoctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
 		bo->delta = 0;
 	}
 
@@ -4184,16 +4184,40 @@ void _kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
 	__kgem_bo_destroy(kgem, bo);
 }
 
-void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo)
+static void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo)
 {
+	assert(bo->rq);
+	assert(bo->exec == NULL);
 	assert(bo->needs_flush);
 
 	/* The kernel will emit a flush *and* update its own flushing lists. */
-	if (bo->exec == NULL && !__kgem_busy(kgem, bo->handle))
+	if (!__kgem_busy(kgem, bo->handle))
 		__kgem_bo_clear_busy(bo);
 
-	DBG(("%s: handle=%d, busy?=%d, flushed?=%d\n",
-	     __FUNCTION__, bo->handle, bo->rq != NULL, bo->exec == NULL));
+	DBG(("%s: handle=%d, busy?=%d\n",
+	     __FUNCTION__, bo->handle, bo->rq != NULL));
+}
+
+void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo)
+{
+	kgem_bo_submit(kgem, bo);
+	if (!bo->needs_flush)
+		return;
+
+	/* If the kernel fails to emit the flush, then it will be forced when
+	 * we assume direct access. And as the usual failure is EIO, we do
+	 * not actually care.
+	 */
+	assert(bo->exec == NULL);
+	if (bo->rq)
+		__kgem_flush(kgem, bo);
+
+	/* Whatever actually happens, we can regard the GTT write domain
+	 * as being flushed.
+	 */
+	bo->gtt_dirty = false;
+	bo->needs_flush = false;
+	bo->domain = DOMAIN_NONE;
 }
 
 inline static bool needs_semaphore(struct kgem *kgem, struct kgem_bo *bo)
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index aa8097a..cdd4d03 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -329,25 +329,7 @@ static inline void kgem_bo_submit(struct kgem *kgem, struct kgem_bo *bo)
 		_kgem_submit(kgem);
 }
 
-void __kgem_flush(struct kgem *kgem, struct kgem_bo *bo);
-static inline void kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo)
-{
-	kgem_bo_submit(kgem, bo);
-
-	if (!bo->needs_flush)
-		return;
-
-	/* If the kernel fails to emit the flush, then it will be forced when
-	 * we assume direct access. And as the usual failure is EIO, we do
-	 * not actually care.
-	 */
-	__kgem_flush(kgem, bo);
-
-	/* Whatever actually happens, we can regard the GTT write domain
-	 * as being flushed.
-	 */
-	bo->gtt_dirty = false;
-}
+void kgem_scanout_flush(struct kgem *kgem, struct kgem_bo *bo);
 
 static inline struct kgem_bo *kgem_bo_reference(struct kgem_bo *bo)
 {
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 203d40f..cb75dda 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -14247,11 +14247,6 @@ static void timer_enable(struct sna *sna, int whom, int interval)
 	DBG(("%s (time=%ld), starting timer %d\n", __FUNCTION__, (long)TIME, whom));
 }
 
-static void sna_pixmap_flush(struct sna *sna, struct sna_pixmap *priv)
-{
-	kgem_bo_flush(&sna->kgem, priv->gpu_bo);
-}
-
 static bool sna_accel_do_flush(struct sna *sna)
 {
 	struct sna_pixmap *priv;
@@ -14277,7 +14272,7 @@ static bool sna_accel_do_flush(struct sna *sna)
 	} else if (!start_flush(sna, priv)) {
 		DBG(("%s -- no pending write to scanout\n", __FUNCTION__));
 		if (priv)
-			sna_pixmap_flush(sna, priv);
+			kgem_scanout_flush(&sna->kgem, priv->gpu_bo);
 	} else
 		timer_enable(sna, FLUSH_TIMER, interval/2);
 
@@ -14454,7 +14449,7 @@ static void sna_accel_flush(struct sna *sna)
 	if (priv) {
 		sna_pixmap_force_to_gpu(priv->pixmap,
 					MOVE_READ | MOVE_ASYNC_HINT);
-		sna_pixmap_flush(sna, priv);
+		kgem_scanout_flush(&sna->kgem, priv->gpu_bo);
 		assert(!priv->cpu);
 	}
 
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 3a5b6e3..bca3b57 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3651,7 +3651,7 @@ void sna_mode_redisplay(struct sna *sna)
 		RegionIntersect(&damage, &damage, region);
 		if (RegionNotEmpty(&damage)) {
 			sna_crtc_redisplay(crtc, &damage);
-			kgem_bo_flush(&sna->kgem, sna_crtc->bo);
+			kgem_scanout_flush(&sna->kgem, sna_crtc->bo);
 		}
 		RegionUninit(&damage);
 	}


More information about the xorg-commit mailing list