xf86-video-intel: 2 commits - src/sna/sna_accel.c src/sna/sna_composite.c src/sna/sna_dri.c src/sna/sna.h src/sna/sna_trapezoids.c

Chris Wilson ickle at kemper.freedesktop.org
Fri May 17 03:07:46 PDT 2013


 src/sna/sna.h            |    4 +
 src/sna/sna_accel.c      |  141 +++++++++++++++++++++++++++++++++++------------
 src/sna/sna_composite.c  |    4 -
 src/sna/sna_dri.c        |    4 -
 src/sna/sna_trapezoids.c |    2 
 5 files changed, 113 insertions(+), 42 deletions(-)

New commits:
commit 5d9315873e02d4acc5ddffc698dbf8984cbd5c42
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 17 10:51:44 2013 +0100

    sna: Avoid replacing pinned bo when undoing a clone
    
    Otherwise we end up cloning the scanout only to leave it dangling if the
    client copies the from the front-buffer and then writes to it.
    
    Reported-by: Nick Bowler <nbowler at draconx.ca>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64675
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index e381ce4..c8a954d 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -108,6 +108,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 struct sna_cow {
 	struct kgem_bo *bo;
+	struct list list;
 	int refcnt;
 };
 
@@ -119,7 +120,8 @@ struct sna_pixmap {
 	void *ptr;
 #define PTR(ptr) ((void*)((uintptr_t)(ptr) & ~1))
 
-	struct list list;
+	struct list flush_list;
+	struct list cow_list;
 
 	uint32_t stride;
 	uint32_t clear_color;
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 8125455..1dd8491 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -101,6 +101,10 @@
 #define IS_STATIC_PTR(ptr) ((uintptr_t)(ptr) & 1)
 #define MAKE_STATIC_PTR(ptr) ((void*)((uintptr_t)(ptr) | 1))
 
+#define IS_COW_OWNER(ptr) ((uintptr_t)(ptr) & 1)
+#define MAKE_COW_OWNER(ptr) ((void*)((uintptr_t)(ptr) | 1))
+#define COW(ptr) (void *)((uintptr_t)(ptr) & ~1)
+
 #if 0
 static void __sna_fallback_flush(DrawablePtr d)
 {
@@ -513,7 +517,7 @@ static void __sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
 static void sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
 {
 	assert(priv->cpu_damage == NULL);
-	assert(list_is_empty(&priv->list));
+	assert(list_is_empty(&priv->flush_list));
 
 	if (IS_STATIC_PTR(priv->ptr))
 		return;
@@ -653,7 +657,7 @@ static inline void sna_set_pixmap(PixmapPtr pixmap, struct sna_pixmap *sna)
 static struct sna_pixmap *
 _sna_pixmap_init(struct sna_pixmap *priv, PixmapPtr pixmap)
 {
-	list_init(&priv->list);
+	list_init(&priv->flush_list);
 	priv->source_count = SOURCE_BIAS;
 	priv->pixmap = pixmap;
 
@@ -1304,7 +1308,7 @@ void sna_add_flush_pixmap(struct sna *sna,
 	assert(bo);
 	assert(bo->flush);
 	assert(priv->gpu_damage == NULL || priv->gpu_bo);
-	list_move(&priv->list, &sna->flush_pixmaps);
+	list_move(&priv->flush_list, &sna->flush_pixmaps);
 
 	if (bo->exec == NULL && kgem_is_idle(&sna->kgem)) {
 		DBG(("%s: new flush bo, flushin before\n", __FUNCTION__));
@@ -1316,7 +1320,7 @@ static void __sna_free_pixmap(struct sna *sna,
 			      PixmapPtr pixmap,
 			      struct sna_pixmap *priv)
 {
-	list_del(&priv->list);
+	list_del(&priv->flush_list);
 
 	assert(priv->gpu_damage == NULL);
 	assert(priv->cpu_damage == NULL);
@@ -1361,8 +1365,9 @@ static Bool sna_destroy_pixmap(PixmapPtr pixmap)
 	sna_damage_destroy(&priv->cpu_damage);
 
 	if (priv->cow) {
-		if (!--priv->cow->refcnt)
-			free(priv->cow);
+		struct sna_cow *cow = COW(priv->cow);
+		if (!--cow->refcnt)
+			free(cow);
 		priv->cow = NULL;
 	}
 
@@ -1536,17 +1541,65 @@ static inline bool use_cpu_bo_for_upload(struct sna *sna,
 static bool
 sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 {
+	struct sna_cow *cow = COW(priv->cow);
+
 	DBG(("%s: pixmap=%ld, handle=%ld, flags=%x\n",
 	     __FUNCTION__,
 	     priv->pixmap->drawable.serialNumber,
 	     priv->gpu_bo->handle,
 	     flags));
 
-	assert(priv->gpu_bo == priv->cow->bo);
+	assert(priv->gpu_bo == cow->bo);
 	assert(!priv->mapped);
+	assert(cow->refcnt);
+
+	list_del(&priv->cow_list);
+
+	if (!--cow->refcnt) {
+		free(cow);
+	} else if (IS_COW_OWNER(priv->cow)) {
+		PixmapPtr pixmap = priv->pixmap;
+		struct kgem_bo *bo;
+		BoxRec box;
+
+		DBG(("%s: copying the Holy cow\n", __FUNCTION__));
+
+		box.x1 = box.y1 = 0;
+		box.x2 = pixmap->drawable.width;
+		box.y2 = pixmap->drawable.height;
 
-	if (!--priv->cow->refcnt) {
-		free(priv->cow);
+		bo = kgem_create_2d(&sna->kgem,
+				    box.x2, box.y2,
+				    pixmap->drawable.bitsPerPixel,
+				    sna_pixmap_choose_tiling(pixmap, DEFAULT_TILING),
+				    0);
+		if (bo == NULL) {
+			cow->refcnt++;
+			DBG(("%s: allocation failed\n", __FUNCTION__));
+			return false;
+		}
+
+		if (!sna->render.copy_boxes(sna, GXcopy,
+					    pixmap, priv->gpu_bo, 0, 0,
+					    pixmap, bo, 0, 0,
+					    &box, 1, 0)) {
+			DBG(("%s: copy failed\n", __FUNCTION__));
+			kgem_bo_destroy(&sna->kgem, bo);
+			cow->refcnt++;
+			return false;
+		}
+
+		cow->bo = bo;
+		while (!list_is_empty(&cow->list)) {
+			struct sna_pixmap *clone;
+
+			clone = list_first_entry(&cow->list,
+						 struct sna_pixmap, cow_list);
+			list_del(&clone->cow_list);
+
+			kgem_bo_destroy(&sna->kgem, clone->gpu_bo);
+			clone->gpu_bo = bo;
+		}
 	} else {
 		struct kgem_bo *bo = NULL;
 
@@ -1566,7 +1619,7 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 					    sna_pixmap_choose_tiling(pixmap, DEFAULT_TILING),
 					    0);
 			if (bo == NULL) {
-				priv->cow->refcnt++;
+				cow->refcnt++;
 				DBG(("%s: allocation failed\n", __FUNCTION__));
 				return false;
 			}
@@ -1577,7 +1630,7 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 						    &box, 1, 0)) {
 				DBG(("%s: copy failed\n", __FUNCTION__));
 				kgem_bo_destroy(&sna->kgem, bo);
-				priv->cow->refcnt++;
+				cow->refcnt++;
 				return false;
 			}
 		}
@@ -1607,25 +1660,27 @@ sna_pixmap_make_cow(struct sna *sna,
 	     dst_priv->pixmap->drawable.serialNumber,
 	     src_priv->gpu_bo->handle));
 
-	if (src_priv->pinned & PIN_DRI || dst_priv->pinned) {
-		DBG(("%s: can't cow, src pinned=%x, dst_pinned=%x\n",
-		     __FUNCTION__, src_priv->pinned, dst_priv->pinned));
+	if (dst_priv->pinned) {
+		DBG(("%s: can't cow, dst_pinned=%x\n",
+		     __FUNCTION__, dst_priv->pinned));
 		return false;
 	}
 
-	assert(!src_priv->flush);
 	assert(!dst_priv->flush);
 
-	cow = src_priv->cow;
+	cow = COW(src_priv->cow);
 	if (cow == NULL) {
 		cow = malloc(sizeof(*cow));
 		if (cow == NULL)
 			return false;
 
+		list_init(&cow->list);
+
 		cow->bo = src_priv->gpu_bo;
 		cow->refcnt = 1;
 
-		src_priv->cow = cow;
+		src_priv->cow = MAKE_COW_OWNER(cow);
+		list_init(&src_priv->cow_list);
 
 		if (src_priv->mapped) {
 			src_priv->pixmap->devPrivate.ptr = NULL;
@@ -1634,7 +1689,7 @@ sna_pixmap_make_cow(struct sna *sna,
 	}
 	assert(!src_priv->mapped);
 
-	if (cow == dst_priv->cow)
+	if (cow == COW(dst_priv->cow))
 		return true;
 
 	if (dst_priv->cow)
@@ -1644,6 +1699,7 @@ sna_pixmap_make_cow(struct sna *sna,
 		kgem_bo_destroy(&sna->kgem, dst_priv->gpu_bo);
 	dst_priv->gpu_bo = kgem_bo_reference(cow->bo);
 	dst_priv->cow = cow;
+	list_add(&dst_priv->cow_list, &cow->list);
 	cow->refcnt++;
 
 	if (dst_priv->mapped) {
@@ -1742,7 +1798,7 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
 			sna_damage_destroy(&priv->cpu_damage);
 			priv->clear = false;
 			priv->cpu = false;
-			list_del(&priv->list);
+			list_del(&priv->flush_list);
 
 			assert(!priv->shm);
 			assert(priv->cpu_bo == NULL || !priv->cpu_bo->flush);
@@ -1800,7 +1856,7 @@ skip_inplace_map:
 					       pixmap->drawable.height);
 				sna_damage_destroy(&priv->cpu_damage);
 				sna_pixmap_free_cpu(sna, priv);
-				list_del(&priv->list);
+				list_del(&priv->flush_list);
 				priv->clear = false;
 			}
 			priv->cpu = false;
@@ -1839,7 +1895,7 @@ skip_inplace_map:
 					       pixmap->drawable.height);
 				sna_damage_destroy(&priv->cpu_damage);
 				sna_pixmap_free_cpu(sna, priv);
-				list_del(&priv->list);
+				list_del(&priv->flush_list);
 				priv->clear = false;
 			}
 
@@ -2184,7 +2240,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 						     __FUNCTION__));
 						assert(priv->cpu == false || (priv->mapped && IS_CPU_MAP(priv->gpu_bo->map)));
 						sna_damage_destroy(&priv->cpu_damage);
-						list_del(&priv->list);
+						list_del(&priv->flush_list);
 					} else
 						sna_damage_subtract(&priv->cpu_damage,
 								    region);
@@ -2505,7 +2561,7 @@ out:
 		priv->source_count = SOURCE_BIAS;
 		assert(priv->gpu_bo == NULL || priv->gpu_bo->proxy == NULL);
 		assert(priv->gpu_bo || priv->gpu_damage == NULL);
-		assert(!priv->flush || !list_is_empty(&priv->list));
+		assert(!priv->flush || !list_is_empty(&priv->flush_list));
 	}
 	if ((flags & MOVE_ASYNC_HINT) == 0 && priv->cpu_bo) {
 		DBG(("%s: syncing cpu bo\n", __FUNCTION__));
@@ -2663,7 +2719,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 		assert(priv->gpu_bo->proxy == NULL);
 		assert(priv->cpu == false || (priv->mapped && IS_CPU_MAP(priv->gpu_bo->map)));
 		sna_damage_destroy(&priv->cpu_damage);
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 		goto done;
 	}
 
@@ -2682,7 +2738,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 	assert_pixmap_damage(pixmap);
 
 	if (priv->cpu_damage == NULL) {
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 		return sna_pixmap_move_to_gpu(pixmap, flags);
 	}
 
@@ -2851,7 +2907,7 @@ done:
 			sna_pixmap_free_cpu(sna, priv);
 	}
 	if (priv->cpu_damage == NULL && priv->flush)
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 
 	assert(!priv->gpu_bo->proxy || (flags & MOVE_WRITE) == 0);
 	return sna_pixmap_mark_active(sna, priv) != NULL;
@@ -3012,7 +3068,7 @@ sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
 
 			sna_damage_subtract(&priv->cpu_damage, &region);
 			if (priv->cpu_damage == NULL) {
-				list_del(&priv->list);
+				list_del(&priv->flush_list);
 				priv->cpu = false;
 			}
 		}
@@ -3105,7 +3161,7 @@ done:
 			      pixmap->drawable.width,
 			      pixmap->drawable.height)) {
 		sna_damage_destroy(&priv->cpu_damage);
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 		*damage = NULL;
 	} else
 		*damage = &priv->gpu_damage;
@@ -3357,7 +3413,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 		assert(priv->gpu_bo->proxy == NULL);
 		assert(priv->cpu == false || (priv->mapped && IS_CPU_MAP(priv->gpu_bo->map)));
 		sna_damage_destroy(&priv->cpu_damage);
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 		goto active;
 	}
 
@@ -3508,7 +3564,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 		sna_pixmap_free_cpu(sna, priv);
 	}
 done:
-	list_del(&priv->list);
+	list_del(&priv->flush_list);
 
 	sna_damage_reduce_all(&priv->gpu_damage,
 			      pixmap->drawable.width,
@@ -4545,7 +4601,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 				dst_priv->gpu_bo = NULL;
 			}
 			sna_damage_destroy(&dst_priv->cpu_damage);
-			list_del(&dst_priv->list);
+			list_del(&dst_priv->flush_list);
 			dst_priv->cpu = false;
 		}
 		if (region->data == NULL)
@@ -4619,7 +4675,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 						       dst_pixmap->drawable.width,
 						       dst_pixmap->drawable.height);
 					sna_damage_destroy(&dst_priv->cpu_damage);
-					list_del(&dst_priv->list);
+					list_del(&dst_priv->flush_list);
 					if (dst_priv->shm)
 						sna_add_flush_pixmap(sna, dst_priv, dst_priv->cpu_bo);
 					return;
@@ -4866,7 +4922,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 					sna_damage_all(&dst_priv->gpu_damage,
 						       dst_pixmap->drawable.width,
 						       dst_pixmap->drawable.height);
-					list_del(&dst_priv->list);
+					list_del(&dst_priv->flush_list);
 				} else
 					sna_damage_add(&dst_priv->gpu_damage,
 						       region);
@@ -9652,7 +9708,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
 							       pixmap->drawable.width,
 							       pixmap->drawable.height);
 						sna_damage_destroy(&priv->cpu_damage);
-						list_del(&priv->list);
+						list_del(&priv->flush_list);
 						priv->clear = true;
 						priv->clear_color = gc->alu == GXcopy ? pixel : 0;
 
@@ -12103,7 +12159,7 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
 					priv->gpu_bo = NULL;
 				}
 				sna_damage_destroy(&priv->cpu_damage);
-				list_del(&priv->list);
+				list_del(&priv->flush_list);
 			}
 			hint |= IGNORE_CPU;
 		}
@@ -13965,9 +14021,9 @@ sna_accel_flush_callback(CallbackListPtr *list,
 		bool ret;
 
 		priv = list_first_entry(&sna->flush_pixmaps,
-					struct sna_pixmap, list);
+					struct sna_pixmap, flush_list);
 
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 		if (priv->shm) {
 			DBG(("%s: syncing SHM pixmap=%ld (refcnt=%d)\n",
 			     __FUNCTION__,
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index df2aa1a..ae63e68 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -627,7 +627,7 @@ sna_composite(CARD8 op,
 
 		sna_damage_subtract(&priv->cpu_damage, &region);
 		if (priv->cpu_damage == NULL) {
-			list_del(&priv->list);
+			list_del(&priv->flush_list);
 			priv->cpu = false;
 		}
 
@@ -931,7 +931,7 @@ sna_composite_rectangles(CARD8		 op,
 				priv->gpu_bo = NULL;
 			}
 			sna_damage_destroy(&priv->cpu_damage);
-			list_del(&priv->list);
+			list_del(&priv->flush_list);
 		}
 		if (region_subsumes_drawable(&region, &pixmap->drawable) ||
 		    box_inplace(pixmap, &region.extents)) {
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 77b2e07..99f9d12 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -443,7 +443,7 @@ static void _sna_dri_destroy_buffer(struct sna *sna, DRI2Buffer2Ptr buffer)
 		     pixmap->drawable.serialNumber,
 		     pixmap == sna->front));
 
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 
 		priv->gpu_bo->flush = false;
 		priv->pinned &= ~PIN_DRI;
@@ -524,7 +524,7 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 		       pixmap->drawable.width,
 		       pixmap->drawable.height);
 	sna_damage_destroy(&priv->cpu_damage);
-	list_del(&priv->list);
+	list_del(&priv->flush_list);
 	priv->cpu = false;
 
 	assert(bo->refcnt);
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 7907e8d..5af7d41 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -6712,7 +6712,7 @@ static void mark_damaged(PixmapPtr pixmap, struct sna_pixmap *priv,
 		sna_damage_all(&priv->gpu_damage,
 			       pixmap->drawable.width,
 			       pixmap->drawable.height);
-		list_del(&priv->list);
+		list_del(&priv->flush_list);
 	} else {
 		sna_damage_add_box(&priv->gpu_damage, box);
 		sna_damage_subtract_box(&priv->cpu_damage, box);
commit 3efe143e367acfa2ff38c63388d24a8d06331944
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri May 17 10:30:51 2013 +0100

    sna: Clear mapped hints upon cloning a pair of pixmaps
    
    Once cloned, we do not want to use inplace operations and instead force
    a copy. However, if we do not relinquish the hints when copying across
    the bo, then those hints become stale and lead to corruption.
    
    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 f6246a3..8125455 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1536,14 +1536,15 @@ static inline bool use_cpu_bo_for_upload(struct sna *sna,
 static bool
 sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 {
-	assert(priv->gpu_bo == priv->cow->bo);
-
 	DBG(("%s: pixmap=%ld, handle=%ld, flags=%x\n",
 	     __FUNCTION__,
 	     priv->pixmap->drawable.serialNumber,
 	     priv->gpu_bo->handle,
 	     flags));
 
+	assert(priv->gpu_bo == priv->cow->bo);
+	assert(!priv->mapped);
+
 	if (!--priv->cow->refcnt) {
 		free(priv->cow);
 	} else {
@@ -1612,6 +1613,7 @@ sna_pixmap_make_cow(struct sna *sna,
 		return false;
 	}
 
+	assert(!src_priv->flush);
 	assert(!dst_priv->flush);
 
 	cow = src_priv->cow;
@@ -1624,7 +1626,13 @@ sna_pixmap_make_cow(struct sna *sna,
 		cow->refcnt = 1;
 
 		src_priv->cow = cow;
+
+		if (src_priv->mapped) {
+			src_priv->pixmap->devPrivate.ptr = NULL;
+			src_priv->mapped = false;
+		}
 	}
+	assert(!src_priv->mapped);
 
 	if (cow == dst_priv->cow)
 		return true;
@@ -1638,6 +1646,11 @@ sna_pixmap_make_cow(struct sna *sna,
 	dst_priv->cow = cow;
 	cow->refcnt++;
 
+	if (dst_priv->mapped) {
+		dst_priv->pixmap->devPrivate.ptr = NULL;
+		dst_priv->mapped = false;
+	}
+
 	return true;
 }
 


More information about the xorg-commit mailing list