summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-06-03 12:43:51 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-06-03 13:48:58 +0100
commit1c55d0447dba5bbde5be3903b273e04e3c9d084f (patch)
tree4c4b1c020ae52860e5359e61ac4e727029174802
parenta82bfb033448eb61bf8cc7f5358be019f0cc28e6 (diff)
sna: Allow replacements to cancel operations between both bo under a Pixmap
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c40
-rw-r--r--src/sna/kgem.h1
-rw-r--r--src/sna/sna_accel.c49
3 files changed, 63 insertions, 27 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 3eb63d8f..ea114f4c 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2175,6 +2175,46 @@ void kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo)
assert(bo->exec == NULL);
}
+void kgem_bo_pair_undo(struct kgem *kgem, struct kgem_bo *a, struct kgem_bo *b)
+{
+ if (kgem->nexec > 2)
+ return;
+
+ if (kgem->nexec == 1) {
+ if (a)
+ kgem_bo_undo(kgem, a);
+ if (b)
+ kgem_bo_undo(kgem, b);
+ return;
+ }
+
+ if (a == NULL || b == NULL)
+ return;
+ if (a->exec == NULL || b->exec == NULL)
+ return;
+
+ DBG(("%s: only handles in batch, discarding last operations for handle=%d and handle=%d\n",
+ __FUNCTION__, a->handle, b->handle));
+
+ assert(a->exec == &kgem->exec[0] || a->exec == &kgem->exec[1]);
+ assert(a->handle == kgem->exec[0].handle || a->handle == kgem->exec[1].handle);
+ assert(RQ(a->rq) == kgem->next_request);
+ assert(b->exec == &kgem->exec[0] || b->exec == &kgem->exec[1]);
+ assert(b->handle == kgem->exec[0].handle || b->handle == kgem->exec[1].handle);
+ assert(RQ(b->rq) == kgem->next_request);
+
+ a->refcnt++;
+ b->refcnt++;
+ kgem_reset(kgem);
+ b->refcnt--;
+ a->refcnt--;
+
+ assert(kgem->nreloc == 0);
+ assert(kgem->nexec == 0);
+ assert(a->exec == NULL);
+ assert(b->exec == NULL);
+}
+
static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
{
DBG(("%s: handle=%d, size=%d\n", __FUNCTION__, bo->handle, bytes(bo)));
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 6e61909e..ae258210 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -548,6 +548,7 @@ static inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
}
void kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo);
+void kgem_bo_pair_undo(struct kgem *kgem, struct kgem_bo *a, struct kgem_bo *b);
bool __kgem_busy(struct kgem *kgem, int handle);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index e4fad3b6..20f4583c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -483,12 +483,15 @@ static void sna_pixmap_free_gpu(struct sna *sna, struct sna_pixmap *priv)
sna_damage_destroy(&priv->gpu_damage);
priv->clear = false;
- if (priv->gpu_bo && !priv->pinned) {
- assert(!priv->flush);
- assert(!priv->move_to_gpu);
- sna_pixmap_unmap(priv->pixmap, priv);
- kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
- priv->gpu_bo = NULL;
+ if (priv->gpu_bo) {
+ if (!priv->pinned) {
+ assert(!priv->flush);
+ assert(!priv->move_to_gpu);
+ sna_pixmap_unmap(priv->pixmap, priv);
+ kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
+ priv->gpu_bo = NULL;
+ } else
+ kgem_bo_undo(&sna->kgem, priv->gpu_bo);
}
/* and reset the upload counter */
@@ -1460,6 +1463,7 @@ static Bool sna_destroy_pixmap(PixmapPtr pixmap)
sna_damage_destroy(&priv->gpu_damage);
sna_damage_destroy(&priv->cpu_damage);
+ list_del(&priv->cow_list);
if (priv->cow) {
struct sna_cow *cow = COW(priv->cow);
DBG(("%s: pixmap=%ld discarding cow, refcnt=%d\n",
@@ -1468,8 +1472,8 @@ static Bool sna_destroy_pixmap(PixmapPtr pixmap)
if (!--cow->refcnt)
free(cow);
priv->cow = NULL;
- }
- list_del(&priv->cow_list);
+ } else
+ kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
if (priv->move_to_gpu)
(void)priv->move_to_gpu(sna, priv, 0);
@@ -2075,10 +2079,7 @@ _sna_pixmap_move_to_cpu(PixmapPtr pixmap, unsigned int flags)
assert(priv->gpu_damage == NULL || priv->gpu_bo);
if ((flags & MOVE_READ) == 0 && UNDO) {
- if (priv->gpu_bo)
- kgem_bo_undo(&sna->kgem, priv->gpu_bo);
- if (priv->cpu_bo)
- kgem_bo_undo(&sna->kgem, priv->cpu_bo);
+ kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
if (priv->move_to_gpu)
sna_pixmap_discard_shadow_damage(priv, NULL);
}
@@ -3929,12 +3930,8 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
return NULL;
}
- if ((flags & MOVE_READ) == 0 && UNDO) {
- if (priv->gpu_bo)
- kgem_bo_undo(&sna->kgem, priv->gpu_bo);
- if (priv->cpu_bo)
- kgem_bo_undo(&sna->kgem, priv->cpu_bo);
- }
+ if ((flags & MOVE_READ) == 0 && UNDO)
+ kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
if (priv->cow && (flags & MOVE_WRITE || priv->cpu_damage)) {
if (!sna_pixmap_undo_cow(sna, priv, flags & MOVE_READ))
@@ -4542,8 +4539,7 @@ try_upload_tiled_x(PixmapPtr pixmap, RegionRec *region,
}
if (priv->gpu_bo && replaces) {
- if (UNDO)
- kgem_bo_undo(&sna->kgem, priv->gpu_bo);
+ if (UNDO) kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
if (__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo)) {
DBG(("%s: discarding cached upload proxy\n", __FUNCTION__));
sna_pixmap_free_gpu(sna, priv);
@@ -4560,8 +4556,7 @@ try_upload_tiled_x(PixmapPtr pixmap, RegionRec *region,
if (priv->gpu_damage &&
region_subsumes_damage(region, priv->gpu_damage)) {
- if (UNDO)
- kgem_bo_undo(&sna->kgem, priv->gpu_bo);
+ if (UNDO) kgem_bo_undo(&sna->kgem, priv->gpu_bo);
if (__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo)) {
DBG(("%s: discarding dirty pixmap\n", __FUNCTION__));
sna_pixmap_free_gpu(sna, priv);
@@ -6013,7 +6008,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
if (n == 1) {
if (replaces && UNDO)
- kgem_bo_undo(&sna->kgem, bo);
+ kgem_bo_pair_undo(&sna->kgem, dst_priv->gpu_bo, dst_priv->cpu_bo);
if (!sna->render.fill_one(sna,
dst_pixmap, bo, color,
@@ -6066,7 +6061,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
DBG(("%s: move whole src_pixmap to GPU and copy\n",
__FUNCTION__));
if (replaces && UNDO)
- kgem_bo_undo(&sna->kgem, bo);
+ kgem_bo_pair_undo(&sna->kgem, dst_priv->gpu_bo, dst_priv->cpu_bo);
if (replaces &&
src_pixmap->drawable.width == dst_pixmap->drawable.width &&
@@ -6120,7 +6115,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
}
if (replaces && UNDO)
- kgem_bo_undo(&sna->kgem, bo);
+ kgem_bo_pair_undo(&sna->kgem, dst_priv->gpu_bo, dst_priv->cpu_bo);
if (!sna->render.copy_boxes(sna, alu,
src_pixmap, src_priv->gpu_bo, src_dx, src_dy,
@@ -6158,7 +6153,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
}
if (replaces && UNDO)
- kgem_bo_undo(&sna->kgem, bo);
+ kgem_bo_pair_undo(&sna->kgem, dst_priv->gpu_bo, dst_priv->cpu_bo);
if (src_priv->shm) {
assert(!src_priv->flush);
@@ -14321,7 +14316,7 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
goto fallback;
}
if (hint & REPLACES && (flags & 2) == 0 && UNDO)
- kgem_bo_undo(&sna->kgem, bo);
+ kgem_bo_pair_undo(&sna->kgem, priv->gpu_bo, priv->cpu_bo);
if (gc_is_solid(gc, &color)) {
DBG(("%s: solid fill [%08x], testing for blt\n",