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(®ion, &pixmap->drawable) ||
- box_inplace(pixmap, ®ion.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(®ion, &pixmap->drawable))
+ hint |= REPLACES;
if (priv->cpu_damage == NULL) {
+ if (hint & REPLACES &&
+ box_inplace(pixmap, ®ion.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(®ion, &pixmap->drawable) ||
- box_inplace(pixmap, ®ion.extents)) {
+ if (region_subsumes_drawable(®ion, &pixmap->drawable))
+ hint |= REPLACES;
+ if (hint & REPLACES || box_inplace(pixmap, ®ion.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, ®ion);
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, ®ion);
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(®ion, &pixmap->drawable) ||
box_inplace(pixmap, ®ion.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: