diff options
Diffstat (limited to 'src/sna/kgem.c')
-rw-r--r-- | src/sna/kgem.c | 73 |
1 files changed, 63 insertions, 10 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c index d675ebb8..f68b0546 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -858,6 +858,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, int gen) list_init(&kgem->active_buffers); list_init(&kgem->flushing); list_init(&kgem->large); + list_init(&kgem->large_inactive); list_init(&kgem->snoop); for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++) list_init(&kgem->inactive[i]); @@ -1287,8 +1288,10 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem, assert(!bo->needs_flush); assert(list_is_empty(&bo->vma)); + kgem->need_expire = true; + if (bucket(bo) >= NUM_CACHE_BUCKETS) { - kgem_bo_free(kgem, bo); + list_move(&bo->list, &kgem->large_inactive); return; } @@ -1306,8 +1309,6 @@ inline static void kgem_bo_move_to_inactive(struct kgem *kgem, kgem->vma[type].count++; } } - - kgem->need_expire = true; } inline static void kgem_bo_remove_from_inactive(struct kgem *kgem, @@ -2411,6 +2412,13 @@ bool kgem_expire_cache(struct kgem *kgem) free(rq); } + while (!list_is_empty(&kgem->large_inactive)) { + kgem_bo_free(kgem, + list_first_entry(&kgem->large_inactive, + struct kgem_bo, list)); + + } + expire = 0; list_for_each_entry(bo, &kgem->snoop, list) { if (bo->delta) { @@ -3095,9 +3103,9 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, __FUNCTION__, size, bucket)); if (flags & CREATE_INACTIVE) - goto create; + goto large_inactive; - tiled_height = kgem_aligned_height(kgem, height, I915_TILING_Y); + tiled_height = kgem_aligned_height(kgem, height, tiling); untiled_pitch = kgem_untiled_pitch(kgem, width, bpp, flags); list_for_each_entry(bo, &kgem->large, list) { @@ -3105,18 +3113,28 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, assert(bo->refcnt == 0); assert(bo->reusable); - if (bo->tiling) { + if (kgem->gen < 40) { if (bo->pitch < pitch) { DBG(("tiled and pitch too small: tiling=%d, (want %d), pitch=%d, need %d\n", bo->tiling, tiling, bo->pitch, pitch)); continue; } - } else - bo->pitch = untiled_pitch; - if (bo->pitch * tiled_height > bytes(bo)) - continue; + if (bo->pitch * tiled_height > bytes(bo)) + continue; + } else { + if (num_pages(bo) < size) + continue; + + if (bo->pitch != pitch || bo->tiling != tiling) { + if (gem_set_tiling(kgem->fd, bo->handle, + tiling, pitch) != tiling) + continue; + + bo->pitch = pitch; + } + } kgem_bo_remove_from_active(kgem, bo); @@ -3129,6 +3147,39 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem, return bo; } +large_inactive: + list_for_each_entry(bo, &kgem->large_inactive, list) { + assert(bo->refcnt == 0); + assert(bo->reusable); + + if (size > num_pages(bo)) + continue; + + if (bo->tiling != tiling || + (tiling != I915_TILING_NONE && bo->pitch != pitch)) { + if (tiling != gem_set_tiling(kgem->fd, + bo->handle, + tiling, pitch)) + continue; + } + + if (bo->purged && !kgem_bo_clear_purgeable(kgem, bo)) { + kgem_bo_free(kgem, bo); + break; + } + + list_del(&bo->list); + + bo->unique_id = kgem_get_unique_id(kgem); + bo->pitch = pitch; + bo->delta = 0; + DBG((" 1:from large inactive: pitch=%d, tiling=%d, handle=%d, id=%d\n", + bo->pitch, bo->tiling, bo->handle, bo->unique_id)); + assert(bo->pitch*kgem_aligned_height(kgem, height, bo->tiling) <= kgem_bo_size(bo)); + bo->refcnt = 1; + return bo; + } + goto create; } @@ -3407,6 +3458,8 @@ search_inactive: } create: + if (bucket >= NUM_CACHE_BUCKETS) + size = ALIGN(size, 1024); handle = gem_create(kgem->fd, size); if (handle == 0) return NULL; |