summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;