[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-intel: Changes to 'upstream-experimental'



 Makefile.am                  |    2 
 NEWS                         |   32 +++
 configure.ac                 |    7 
 m4/ac_define_dir.m4          |   49 ++++
 src/intel_dri.c              |   15 +
 src/intel_driver.h           |   51 +++-
 src/intel_module.c           |   99 +++++++--
 src/sna/Makefile.am          |    2 
 src/sna/compiler.h           |    2 
 src/sna/gen4_render.c        |   10 
 src/sna/gen4_vertex.c        |    6 
 src/sna/gen5_render.c        |    7 
 src/sna/gen6_render.c        |    2 
 src/sna/gen7_render.c        |   31 ++
 src/sna/kgem.c               |  144 ++++++++++---
 src/sna/kgem.h               |    9 
 src/sna/sna.h                |   18 +
 src/sna/sna_accel.c          |  445 +++++++++++++++++++++++++++++++++++++------
 src/sna/sna_blt.c            |   46 +++-
 src/sna/sna_composite.c      |   20 +
 src/sna/sna_display.c        |   23 +-
 src/sna/sna_dri.c            |   27 ++
 src/sna/sna_driver.c         |   23 +-
 src/sna/sna_render.c         |   13 -
 src/sna/sna_trapezoids.c     |   85 +++++---
 src/sna/sna_video.c          |   10 
 src/sna/sna_video.h          |   19 +
 src/sna/sna_video_hwmc.c     |   75 +++----
 src/sna/sna_video_hwmc.h     |    4 
 src/sna/sna_video_overlay.c  |   53 +++--
 src/sna/sna_video_sprite.c   |   46 +++-
 src/sna/sna_video_textured.c |   57 -----
 32 files changed, 1087 insertions(+), 345 deletions(-)

New commits:
commit e65ee10dfd7155230ac18a6d24a67b68336dc973
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Tue May 21 11:01:50 2013 +0100

    2.21.7 release

diff --git a/NEWS b/NEWS
index 4fc9a6b..3173f21 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,35 @@
+Release 2.21.7 (2013-05-21)
+===========================
+A couple of weeks turned into a month and a couple of weeks... Amidst
+the usual bug fixes, we have added the complete set of Haswell PCI IDs -
+hopefully future proofing ourselves against being surprised by new
+products. We can also now use the correct term for the top of the range
+Haswell variants, GT3.
+
+ * Fix several assertion failures hit by Jiri Slaby.
+
+ * Allow XvMC to also target overlay/sprite planes.
+
+ * Throw in a paranoid MI_FLUSH between BLT and RENDER operations on
+   Ironlake.
+   https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1168066
+
+ * Prevent reuse of old framebuffers after a resize.
+   https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1157678
+
+ * Fix compilation with --enable-valgrind and no --enable-debug
+
+ * Improve partial migration of render sources.
+
+ * Fix origin of trapezoids.
+   https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-video-intel/+bug/1178020
+
+ * Introduce copy-on-write support for cloning pixmaps. The ultimate
+   goal here is to efficiently support the TearFree mode of operation,
+   but this provides immediate benefits with firefox - most importantly
+   because of the inefficient way it now implements scrolling.
+
+
 Release 2.21.6 (2013-04-06)
 ===========================
 A surprising highlight of this release is a little refresh to the KMS
diff --git a/configure.ac b/configure.ac
index d30686f..be1e8d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,7 @@
 # Initialize Autoconf
 AC_PREREQ([2.60])
 AC_INIT([xf86-video-intel],
-        [2.21.6],
+        [2.21.7],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
         [xf86-video-intel])
 AC_CONFIG_SRCDIR([Makefile.am])

commit ef9dc6fae585d5616446eedc1e6e91173f4064c1
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Mon May 20 11:08:51 2013 +0100

    sna: Undo a few more overwritten operations upon a bo
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index aed3e08..ee3f821 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -507,6 +507,7 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling);
 #define FORCE_GPU	0x2
 #define RENDER_GPU	0x4
 #define IGNORE_CPU	0x8
+#define REPLACES	0x10
 struct kgem_bo *
 sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
 		    struct sna_damage ***damage);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 2c78570..6ed9e77 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2946,6 +2946,8 @@ sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
 	     box->x1, box->y1, box->x2, box->y2,
 	     flags));
 
+	assert((hint & REPLACES) == 0 || (hint & IGNORE_CPU));
+
 	assert(box->x2 > box->x1 && box->y2 > box->y1);
 	assert(pixmap->refcnt);
 	assert_pixmap_damage(pixmap);
@@ -3001,7 +3003,7 @@ sna_drawable_use_bo(DrawablePtr drawable, unsigned flags, const BoxRec *box,
 	     __FUNCTION__, priv->flush, priv->shm, priv->cpu, flags));
 
 	if ((flags & PREFER_GPU) == 0 &&
-	    (!priv->gpu_damage || !kgem_bo_is_busy(priv->gpu_bo))) {
+	    (flags & REPLACES || !priv->gpu_damage || !kgem_bo_is_busy(priv->gpu_bo))) {
 		DBG(("%s: try cpu as GPU bo is idle\n", __FUNCTION__));
 		goto use_cpu_bo;
 	}
@@ -12179,18 +12181,20 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
 			}
 			hint |= IGNORE_CPU;
 		}
-		if (priv->cpu_damage == NULL &&
-		    (region_subsumes_drawable(&region, &pixmap->drawable) ||
-		     box_inplace(pixmap, &region.extents))) {
-			DBG(("%s: promoting to full GPU\n", __FUNCTION__));
-			if (priv->gpu_bo) {
-				assert(priv->gpu_bo->proxy == NULL);
-				sna_damage_all(&priv->gpu_damage,
-					       pixmap->drawable.width,
-					       pixmap->drawable.height);
-			}
-		}
+		if (region_subsumes_drawable(&region, &pixmap->drawable))
+			hint |= REPLACES;
 		if (priv->cpu_damage == NULL) {
+			if (hint & REPLACES &&
+			    box_inplace(pixmap, &region.extents)) {
+				DBG(("%s: promoting to full GPU\n",
+				     __FUNCTION__));
+				if (priv->gpu_bo) {
+					assert(priv->gpu_bo->proxy == NULL);
+					sna_damage_all(&priv->gpu_damage,
+						       pixmap->drawable.width,
+						       pixmap->drawable.height);
+				}
+			}
 			DBG(("%s: dropping last-cpu hint\n", __FUNCTION__));
 			priv->cpu = false;
 		}
@@ -12209,6 +12213,8 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
 		DBG(("%s: not using GPU, hint=%x\n", __FUNCTION__, hint));
 		goto fallback;
 	}
+	if (hint & REPLACES)
+		kgem_bo_undo(&sna->kgem, bo);
 
 	if (gc_is_solid(gc, &color)) {
 		DBG(("%s: solid fill [%08x], testing for blt\n",
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index ae63e68..17cc68c 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -933,8 +933,9 @@ sna_composite_rectangles(CARD8		 op,
 			sna_damage_destroy(&priv->cpu_damage);
 			list_del(&priv->flush_list);
 		}
-		if (region_subsumes_drawable(&region, &pixmap->drawable) ||
-		    box_inplace(pixmap, &region.extents)) {
+		if (region_subsumes_drawable(&region, &pixmap->drawable))
+			hint |= REPLACES;
+		if (hint & REPLACES || box_inplace(pixmap, &region.extents)) {
 			DBG(("%s: promoting to full GPU\n", __FUNCTION__));
 			if (priv->gpu_bo && priv->cpu_damage == NULL) {
 				assert(priv->gpu_bo->proxy == NULL);
@@ -958,6 +959,8 @@ sna_composite_rectangles(CARD8		 op,
 		DBG(("%s: fallback due to no GPU bo\n", __FUNCTION__));
 		goto fallback;
 	}
+	if (hint & REPLACES)
+		kgem_bo_undo(&sna->kgem, bo);
 
 	if (!sna->render.fill_boxes(sna, op, dst->format, color,
 				    pixmap, bo, boxes, num_boxes)) {

commit d6c30d1d4df6bcdfa075bd29da7c8aabee20774c
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri May 17 12:11:34 2013 +0100

    sna: Clear the cow_list when discarding the clone upon pixmap destroy
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index a50f4d4..2c78570 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1366,6 +1366,10 @@ static Bool sna_destroy_pixmap(PixmapPtr pixmap)
 
 	if (priv->cow) {
 		struct sna_cow *cow = COW(priv->cow);
+		DBG(("%s: pixmap=%ld discarding cow, refcnt=%d\n",
+		     __FUNCTION__, pixmap->drawable.serialNumber, cow->refcnt));
+		assert(cow->refcnt);
+		list_del(&priv->cow_list);
 		if (!--cow->refcnt)
 			free(cow);
 		priv->cow = NULL;
@@ -1556,8 +1560,9 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 	list_del(&priv->cow_list);
 
 	if (!--cow->refcnt) {
+		assert(list_is_empty(&cow->list));
 		free(cow);
-	} else if (IS_COW_OWNER(priv->cow)) {
+	} else if (IS_COW_OWNER(priv->cow) && priv->pinned) {
 		PixmapPtr pixmap = priv->pixmap;
 		struct kgem_bo *bo;
 		BoxRec box;
@@ -1589,7 +1594,6 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 			return false;
 		}
 
-		cow->bo = bo;
 		assert(!list_is_empty(&cow->list));
 		while (!list_is_empty(&cow->list)) {
 			struct sna_pixmap *clone;
@@ -1598,9 +1602,11 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 						 struct sna_pixmap, cow_list);
 			list_del(&clone->cow_list);
 
+			assert(clone->gpu_bo == cow->bo);
 			kgem_bo_destroy(&sna->kgem, clone->gpu_bo);
 			clone->gpu_bo = kgem_bo_reference(bo);
 		}
+		cow->bo = bo;
 		kgem_bo_destroy(&sna->kgem, bo);
 	} else {
 		struct kgem_bo *bo = NULL;
@@ -1681,6 +1687,9 @@ sna_pixmap_make_cow(struct sna *sna,
 		cow->bo = src_priv->gpu_bo;
 		cow->refcnt = 1;
 
+		DBG(("%s: attaching source cow to pixmap=%ld\n",
+		     __FUNCTION__, src_priv->pixmap->drawable.serialNumber));
+
 		src_priv->cow = MAKE_COW_OWNER(cow);
 		list_init(&src_priv->cow_list);
 
@@ -1691,8 +1700,10 @@ sna_pixmap_make_cow(struct sna *sna,
 	}
 	assert(!src_priv->mapped);
 
-	if (cow == COW(dst_priv->cow))
+	if (cow == COW(dst_priv->cow)) {
+		assert(dst_priv->gpu_bo == cow->bo);
 		return true;
+	}
 
 	if (dst_priv->cow)
 		sna_pixmap_undo_cow(sna, dst_priv, 0);
@@ -1704,6 +1715,9 @@ sna_pixmap_make_cow(struct sna *sna,
 	list_add(&dst_priv->cow_list, &cow->list);
 	cow->refcnt++;
 
+	DBG(("%s: attaching clone to pixmap=%ld\n",
+	     __FUNCTION__, dst_priv->pixmap->drawable.serialNumber));
+
 	if (dst_priv->mapped) {
 		dst_priv->pixmap->devPrivate.ptr = NULL;
 		dst_priv->mapped = false;

commit 21f17455650d52848467290f609c678e85b8ceab
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri May 17 11:46:16 2013 +0100

    sna: Add the missing ref(bo) when undoing the source clone
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 7e3c0bb..a50f4d4 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1599,7 +1599,7 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 			list_del(&clone->cow_list);
 
 			kgem_bo_destroy(&sna->kgem, clone->gpu_bo);
-			clone->gpu_bo = bo;
+			clone->gpu_bo = kgem_bo_reference(bo);
 		}
 		kgem_bo_destroy(&sna->kgem, bo);
 	} else {

commit ee166ca856ac02ca8900b9ff44ed3899add2c72a
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri May 17 11:30:03 2013 +0100

    sna: Undo the clone when replacing the DRI pixmap
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index c8a954d..aed3e08 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -451,6 +451,9 @@ PixmapPtr sna_pixmap_create_unattached(ScreenPtr screen,
 				       int width, int height, int depth);
 void sna_pixmap_destroy(PixmapPtr pixmap);
 
+bool
+sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags);
+
 #define MOVE_WRITE 0x1
 #define MOVE_READ 0x2
 #define MOVE_INPLACE_HINT 0x4
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index b3dca97..7e3c0bb 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1538,7 +1538,7 @@ static inline bool use_cpu_bo_for_upload(struct sna *sna,
 	return kgem_bo_is_busy(priv->gpu_bo) || kgem_bo_is_busy(priv->cpu_bo);
 }
 
-static bool
+bool
 sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 {
 	struct sna_cow *cow = COW(priv->cow);
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 99f9d12..06d1f21 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -505,11 +505,13 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 	assert(pixmap->drawable.height * bo->pitch <= kgem_bo_size(bo));
 	assert(bo->proxy == NULL);
 	assert(bo->flush);
-	assert(priv->cow == NULL);
 	assert(priv->pinned & PIN_DRI);
 	assert((priv->pinned & PIN_PRIME) == 0);
 	assert(priv->flush);
 
+	if (priv->cow)
+		sna_pixmap_undo_cow(sna, priv, 0);
+
 	/* Post damage on the new front buffer so that listeners, such
 	 * as DisplayLink know take a copy and shove it over the USB,
 	 * also for software cursors and the like.
@@ -529,7 +531,8 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 
 	assert(bo->refcnt);
 	if (priv->gpu_bo != bo) {
-		kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
+		if (priv->gpu_bo)
+			kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
 		priv->gpu_bo = ref(bo);
 		if (priv->mapped) {
 			assert(!priv->shm && priv->stride);

commit 8d31fe771b423a3768cbd05db994d49e941369e1
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri May 17 11:14:34 2013 +0100

    sna: Transfer ownership of the cloned bo to the pixmaps
    
    Fix the leak from the previous commit.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 1dd8491..b3dca97 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1590,6 +1590,7 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 		}
 
 		cow->bo = bo;
+		assert(!list_is_empty(&cow->list));
 		while (!list_is_empty(&cow->list)) {
 			struct sna_pixmap *clone;
 
@@ -1600,6 +1601,7 @@ sna_pixmap_undo_cow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
 			kgem_bo_destroy(&sna->kgem, clone->gpu_bo);
 			clone->gpu_bo = bo;
 		}
+		kgem_bo_destroy(&sna->kgem, bo);
 	} else {
 		struct kgem_bo *bo = NULL;
 

commit 5d9315873e02d4acc5ddffc698dbf8984cbd5c42
Author: Chris Wilson <chris@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@draconx.ca>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64675
    Signed-off-by: Chris Wilson <chris@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@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@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;
 }
 

commit f57a65c35268f215c17f1a02b3af50a6678ce3c1
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Tue May 14 16:15:57 2013 +0100

    sna: Correct assertions to allow discarding of cpu hint for inplace ops
    
    Reported-by: Zdenek Kabelac <zkabelac@redhat.com>
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 067e2dd..f6246a3 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1711,6 +1711,7 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
 			DBG(("%s: write inplace\n", __FUNCTION__));
 			assert(!priv->shm);
 			assert(priv->gpu_bo->exec == NULL);
+			assert((flags & MOVE_READ) == 0 || priv->cpu_damage == NULL);
 
 			pixmap->devPrivate.ptr =
 				kgem_bo_map(&sna->kgem, priv->gpu_bo);
@@ -1769,7 +1770,7 @@ skip_inplace_map:
 	    pixmap_inplace(sna, pixmap, priv, (flags & MOVE_READ) == 0) &&
 	     sna_pixmap_create_mappable_gpu(pixmap, (flags & MOVE_READ) == 0)) {
 		DBG(("%s: try to operate inplace (GTT)\n", __FUNCTION__));
-		assert((flags & MOVE_READ) == 0 || priv->cpu == false);
+		assert((flags & MOVE_READ) == 0 || priv->cpu_damage == NULL);
 		/* XXX only sync for writes? */
 		kgem_bo_submit(&sna->kgem, priv->gpu_bo);
 		assert(priv->gpu_bo->exec == NULL);

commit bb0969e6a5c2bddcd0499d81c0c241003f8b07ef
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Tue May 14 15:22:59 2013 +0100

    sna: Assert that the mapping is released before closing the GEM handle
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 8b096c5..ef8f036 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1499,6 +1499,7 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
 	if (bo->map)
 		kgem_bo_release_map(kgem, bo);
 	assert(list_is_empty(&bo->vma));
+	assert(bo->map == NULL);
 
 	_list_del(&bo->list);
 	_list_del(&bo->request);
@@ -2182,6 +2183,7 @@ static void kgem_commit(struct kgem *kgem)
 		kgem_retire(kgem);
 		assert(list_is_empty(&rq->buffers));
 
+		assert(rq->bo->map == NULL);
 		gem_close(kgem->fd, rq->bo->handle);
 		kgem_cleanup_cache(kgem);
 	} else {
@@ -5796,7 +5798,7 @@ kgem_replace_bo(struct kgem *kgem,
 			return NULL;
 
 		dst = __kgem_bo_alloc(handle, size);


Reply to: