diff options
-rw-r--r-- | src/sna/kgem.c | 34 |
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; |