summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-01-08 11:45:11 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-01-08 14:34:01 +0000
commit26042b2660d87044e1920a1267d9984c00c9566a (patch)
tree9a398054f22fec0ab7b5afc8477a49ebac485e7f
parent3f7ea44bf19a03ee81b683885c9c2416092254a3 (diff)
sna: Bubble sort the partial buffer list back into order after trimming padding
After reducing the used size in the partial buffer, we need to resort the list to maintain the list in decreasing amount of available space. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/kgem.c34
1 files changed, 33 insertions, 1 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 08d4db70..0c1b2b1d 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2163,6 +2163,9 @@ static void _kgem_bo_delete_partial(struct kgem *kgem, struct kgem_bo *bo)
if (list_is_empty(&io->base.list))
return;
+ DBG(("%s: size=%d, offset=%d, parent used=%d\n",
+ __FUNCTION__, bo->size, bo->delta, io->used));
+
if (bo->size == io->used) {
assert(io->base.exec == NULL);
assert(io->base.refcnt >= 2);
@@ -2976,12 +2979,41 @@ struct kgem_bo *kgem_create_buffer_2d(struct kgem *kgem,
return NULL;
if (height & 1) {
+ struct kgem_partial_bo *io = (struct kgem_partial_bo *)bo->proxy;
+ int remain;
+
/* Having padded this surface to ensure that accesses to
* the last pair of rows is valid, remove the padding so
* that it can be allocated to other pixmaps.
*/
- ((struct kgem_partial_bo *)bo->proxy)->used -= stride;
+ io->used -= stride;
bo->size -= stride;
+
+ /* And bubble-sort the partial back into place */
+ remain = io->alloc - io->used;
+ while (io->base.list.prev != &kgem->partial) {
+ struct kgem_partial_bo *p;
+
+ p = list_entry(io->base.list.prev,
+ struct kgem_partial_bo,
+ base.list);
+ if (remain <= p->alloc - p->used)
+ break;
+
+ assert(p->base.list.next == &io->base.list);
+ io->base.list.prev = p->base.list.prev;
+ p->base.list.prev->next = &io->base.list;
+ p->base.list.prev = &io->base.list;
+
+ p->base.list.next = io->base.list.next;
+ io->base.list.next->prev = &p->base.list;
+ io->base.list.next = &p->base.list;
+
+ assert(p->base.list.next->prev == &p->base.list);
+ assert(io->base.list.prev->next == &io->base.list);
+ }
+
+ assert(validate_partials(kgem));
}
bo->pitch = stride;