summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-04-01 22:44:13 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-04-01 23:04:29 +0100
commit4af622edfc18af523e1fa9063379f68374e19b04 (patch)
tree2164e8d4088168d509d879293e6e01bace54b6d8
parentef0038d358e613381e03c077e06a87fc49108d87 (diff)
sna: Try to eliminate pending operations to the bo being replaced
When we are replacing a bo with fresh data, we can drop pending operations to it and thereby reduce the complexity of the replacement. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c29
-rw-r--r--src/sna/kgem.h2
-rw-r--r--src/sna/sna_io.c25
3 files changed, 27 insertions, 29 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 231dc8e7..9013e68c 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1732,6 +1732,23 @@ search_snoop_cache(struct kgem *kgem, unsigned int num_pages, unsigned flags)
return NULL;
}
+void kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo)
+{
+ if (kgem->nexec != 1 || bo->exec == NULL)
+ return;
+
+ DBG(("%s: only handle in batch, discarding last operations\n",
+ __FUNCTION__));
+
+ assert(bo->exec == &kgem->exec[0]);
+ assert(kgem->exec[0].handle == bo->handle);
+ assert(RQ(bo->rq) == kgem->next_request);
+
+ bo->refcnt++;
+ kgem_reset(kgem);
+ bo->refcnt--;
+}
+
static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
{
DBG(("%s: handle=%d\n", __FUNCTION__, bo->handle));
@@ -1782,16 +1799,8 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
assert(bo->io == false);
assert(bo->scanout == false);
- if (bo->exec && kgem->nexec == 1) {
- DBG(("%s: only handle in batch, discarding last operations\n",
- __FUNCTION__));
- assert(bo->exec == &kgem->exec[0]);
- assert(kgem->exec[0].handle == bo->handle);
- assert(RQ(bo->rq) == kgem->next_request);
- bo->refcnt = 1;
- kgem_reset(kgem);
- bo->refcnt = 0;
- }
+ kgem_bo_undo(kgem, bo);
+ assert(bo->refcnt == 0);
if (bo->rq && bo->exec == NULL && !__kgem_busy(kgem, bo->handle))
__kgem_bo_clear_busy(bo);
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 82f9b522..f2b1c980 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -573,6 +573,8 @@ static inline bool kgem_bo_is_snoop(struct kgem_bo *bo)
return bo->snoop;
}
+void kgem_bo_undo(struct kgem *kgem, struct kgem_bo *bo);
+
bool __kgem_busy(struct kgem *kgem, int handle);
static inline void kgem_bo_mark_busy(struct kgem_bo *bo, int ring)
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index 540f3a60..14c0d8c7 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -1362,38 +1362,25 @@ bool sna_replace(struct sna *sna,
{
struct kgem_bo *bo = *_bo;
struct kgem *kgem = &sna->kgem;
- bool busy;
void *dst;
- busy = __kgem_bo_is_busy(kgem, bo);
DBG(("%s(handle=%d, %dx%d, bpp=%d, tiling=%d) busy?=%d\n",
__FUNCTION__, bo->handle,
pixmap->drawable.width,
pixmap->drawable.height,
pixmap->drawable.bitsPerPixel,
- bo->tiling, busy));
+ bo->tiling,
+ __kgem_bo_is_busy(kgem, bo)));
assert(!sna_pixmap(pixmap)->pinned);
- if (!busy && upload_inplace__tiled(kgem, bo)) {
- BoxRec box;
+ kgem_bo_undo(kgem, bo);
- box.x1 = box.y1 = 0;
- box.x2 = pixmap->drawable.width;
- box.y2 = pixmap->drawable.height;
+ if (__kgem_bo_is_busy(kgem, bo)) {
+ struct kgem_bo *new_bo;
- if (write_boxes_inplace__tiled(kgem, src,
- stride, pixmap->drawable.bitsPerPixel, 0, 0,
- bo, 0, 0, &box, 1))
+ if (indirect_replace(sna, pixmap, bo, src, stride))
return true;
- }
-
- if ((busy || !kgem_bo_can_map(kgem, bo)) &&
- indirect_replace(sna, pixmap, bo, src, stride))
- return true;
-
- if (busy) {
- struct kgem_bo *new_bo;
new_bo = kgem_create_2d(kgem,
pixmap->drawable.width,