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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <ch...@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 <nbow...@draconx.ca>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64675
    Signed-off-by: Chris Wilson <ch...@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 <ch...@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 <ch...@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 <ch...@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 <zkabe...@redhat.com>
    Signed-off-by: Chris Wilson <ch...@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 <ch...@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 <ch...@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);


-- 
To UNSUBSCRIBE, email to debian-x-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: http://lists.debian.org/e1ufqed-0006kv...@vasks.debian.org

Reply via email to