summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-10-19 21:09:01 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-10-19 21:09:01 +0100
commit50b980f12e02401cdd4bc21b970d92e7bd1e6459 (patch)
tree80396ea7fb659b770bf33c9c1a157ae3c1dbe9f1
parent972989276dd3f84c1cedca0494d04f907875f8f3 (diff)
sna: Reuse any partial write buffer for readback
Take advantage of any available temporary buffer that we reuse for readback knowing that it is the last operation in the batch. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c34
-rw-r--r--src/sna/kgem.h2
-rw-r--r--src/sna/sna_io.c2
3 files changed, 21 insertions, 17 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 073fed7e..ed0e12ff 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1944,6 +1944,16 @@ struct kgem_bo *kgem_create_buffer(struct kgem *kgem,
__FUNCTION__, size, flags, write, flags & KGEM_BUFFER_LAST));
list_for_each_entry(bo, &kgem->partial, base.list) {
+ if (flags == KGEM_BUFFER_LAST && bo->write) {
+ /* We can reuse any write buffer which we can fit */
+ if (size < bo->alloc) {
+ DBG(("%s: reusing write buffer for read of %d bytes? used=%d, total=%d\n",
+ __FUNCTION__, size, bo->used, bo->alloc));
+ offset = 0;
+ goto done;
+ }
+ }
+
if (bo->write != write) {
DBG(("%s: skip write %d buffer, need %d\n",
__FUNCTION__, bo->write, write));
@@ -2133,31 +2143,25 @@ cleanup_bo:
return NULL;
}
-void kgem_buffer_sync(struct kgem *kgem, struct kgem_bo *_bo)
+void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *_bo)
{
struct kgem_partial_bo *bo;
+ uint32_t offset = _bo->delta, length = _bo->size;
if (_bo->proxy)
_bo = _bo->proxy;
bo = (struct kgem_partial_bo *)_bo;
- DBG(("%s(need_io=%s, sync=%d)\n", __FUNCTION__,
- bo->need_io ? bo->write ? "write" : "read" : "none",
- bo->base.sync));
+ DBG(("%s(offset=%d, length=%d, sync=%d)\n", __FUNCTION__,
+ offset, length, bo->base.sync));
- if (bo->need_io) {
- if (bo->write)
- gem_write(kgem->fd, bo->base.handle,
- 0, bo->used, bo+1);
- else
- gem_read(kgem->fd, bo->base.handle, bo+1, bo->used);
+ if (!bo->base.sync) {
+ gem_read(kgem->fd, bo->base.handle,
+ (char *)(bo+1)+offset, length);
bo->base.needs_flush = false;
if (bo->base.gpu)
kgem_retire(kgem);
- bo->need_io = 0;
- }
-
- if (bo->base.sync)
- kgem_bo_sync(kgem, &bo->base, bo->write);
+ } else
+ kgem_bo_sync(kgem, &bo->base, false);
}
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 60a23def..eb89c633 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -330,7 +330,7 @@ void kgem_bo_sync(struct kgem *kgem, struct kgem_bo *bo, bool for_write);
struct kgem_bo *kgem_create_buffer(struct kgem *kgem,
uint32_t size, uint32_t flags,
void **ret);
-void kgem_buffer_sync(struct kgem *kgem, struct kgem_bo *bo);
+void kgem_buffer_read_sync(struct kgem *kgem, struct kgem_bo *bo);
void kgem_throttle(struct kgem *kgem);
bool kgem_expire_cache(struct kgem *kgem);
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index 321247a2..5a6fdd9b 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -202,7 +202,7 @@ void sna_read_boxes(struct sna *sna,
} while (tmp_nbox);
assert(offset == dst_bo->size);
- kgem_buffer_sync(kgem, dst_bo);
+ kgem_buffer_read_sync(kgem, dst_bo);
src = ptr;
do {