diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-09-13 11:39:39 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-09-13 12:20:17 +0100 |
commit | 343b99d2a85c520c81d1408534b2531fcbedfaae (patch) | |
tree | bb64f9d8f2a1e1a4fbe9bfd69735efba51f57e07 | |
parent | 90071454d24e7230d00c49f5a897296298fc1f22 (diff) |
sna: Reuse the smallest bo that fits the request
When scanning the active list, pick the smallest that we can reuse.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/kgem.c | 62 |
1 files changed, 32 insertions, 30 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c index b60f777d..615e3c5c 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -1364,11 +1364,10 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, uint32_t flags) { struct list *cache; - struct kgem_bo *bo, *next; - uint32_t pitch, tiled_height[3], size; + struct kgem_bo *bo, *next, *best; + uint32_t pitch, tiled_height[3], size, best_size; uint32_t handle; int exact = flags & CREATE_EXACT; - int search; int i; if (tiling < 0) @@ -1386,12 +1385,14 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, for (i = 0; i <= I915_TILING_Y; i++) tiled_height[i] = kgem_aligned_height(kgem, height, i); - search = 0; - /* Best active match first */ +search_active: /* Best active match first */ + best = NULL; + best_size = -1; list_for_each_entry_safe(bo, next, &kgem->active, list) { uint32_t s; - search++; + if (bo->size > best_size) + continue; if (exact) { if (bo->tiling != tiling) @@ -1412,40 +1413,39 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, bo->pitch = pitch; s = bo->pitch * tiled_height[bo->tiling]; - if (s > bo->size) { - DBG(("size too small: %d < %d\n", - bo->size, s)); - continue; + if (s <= bo->size) { + best_size = s; + best = bo; } + } + if (best) { + list_del(&best->list); + if (best->rq == NULL) + list_del(&best->request); - list_del(&bo->list); - if (bo->rq == NULL) - list_del(&bo->request); - - if (bo->deleted) { - if (!gem_madvise(kgem->fd, bo->handle, + if (best->deleted) { + if (!gem_madvise(kgem->fd, best->handle, I915_MADV_WILLNEED)) { - kgem->need_purge |= bo->gpu; - gem_close(kgem->fd, bo->handle); - list_del(&bo->request); - free(bo); - continue; + kgem->need_purge |= best->gpu; + gem_close(kgem->fd, best->handle); + list_del(&best->request); + free(best); + best = NULL; + goto search_active; } - bo->deleted = 0; + best->deleted = 0; } - bo->unique_id = kgem_get_unique_id(kgem); - bo->delta = 0; + best->unique_id = kgem_get_unique_id(kgem); + best->delta = 0; DBG((" from active: pitch=%d, tiling=%d, handle=%d, id=%d\n", - bo->pitch, bo->tiling, bo->handle, bo->unique_id)); - assert(bo->refcnt == 0); - assert(bo->reusable); - return kgem_bo_reference(bo); + best->pitch, best->tiling, best->handle, best->unique_id)); + assert(best->refcnt == 0); + assert(best->reusable); + return kgem_bo_reference(best); } - DBG(("searched %d active, no match\n", search)); - skip_active_search: /* Now just look for a close match and prefer any currently active */ cache = inactive(kgem, size); @@ -1511,6 +1511,8 @@ next_bo: if (tiling != I915_TILING_NONE) bo->tiling = gem_set_tiling(kgem->fd, handle, tiling, pitch); + assert (bo->size >= bo->pitch * kgem_aligned_height(kgem, height, bo->tiling)); + DBG((" new pitch=%d, tiling=%d, handle=%d, id=%d\n", bo->pitch, bo->tiling, bo->handle, bo->unique_id)); return bo; |