sna/dri: Fix triple buffering to not penalise missed frames

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-12-30 14:50:49 +00:00
parent 736b89504a
commit a7988bf77f
4 changed files with 397 additions and 454 deletions

View File

@ -942,6 +942,7 @@ void kgem_init(struct kgem *kgem, int fd, struct pci_device *dev, unsigned gen)
list_init(&kgem->large);
list_init(&kgem->large_inactive);
list_init(&kgem->snoop);
list_init(&kgem->scanout);
for (i = 0; i < ARRAY_SIZE(kgem->pinned_batches); i++)
list_init(&kgem->pinned_batches[i]);
for (i = 0; i < ARRAY_SIZE(kgem->inactive); i++)
@ -1666,7 +1667,6 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
assert(bo->proxy == NULL);
bo->binding.offset = 0;
kgem_bo_clear_scanout(kgem, bo);
if (DBG_NO_CACHE)
goto destroy;
@ -1708,6 +1708,12 @@ static void __kgem_bo_destroy(struct kgem *kgem, struct kgem_bo *bo)
bo->reusable = false;
}
if (bo->scanout) {
DBG(("%s: handle=%d -> scanout\n", __FUNCTION__, bo->handle));
list_add(&bo->list, &kgem->scanout);
return;
}
if (!bo->reusable) {
DBG(("%s: handle=%d, not reusable\n",
__FUNCTION__, bo->handle));
@ -2705,6 +2711,13 @@ bool kgem_expire_cache(struct kgem *kgem)
}
while (!list_is_empty(&kgem->scanout)) {
bo = list_first_entry(&kgem->scanout, struct kgem_bo, list);
list_del(&bo->list);
kgem_bo_clear_scanout(kgem, bo);
__kgem_bo_destroy(kgem, bo);
}
expire = 0;
list_for_each_entry(bo, &kgem->snoop, list) {
if (bo->delta) {
@ -3393,6 +3406,36 @@ struct kgem_bo *kgem_create_2d(struct kgem *kgem,
size /= PAGE_SIZE;
bucket = cache_bucket(size);
if (flags & CREATE_SCANOUT) {
list_for_each_entry(bo, &kgem->scanout, list) {
assert(bo->scanout);
assert(bo->delta);
assert(!bo->purged);
if (size > num_pages(bo) || num_pages(bo) > 2*size)
continue;
if (bo->tiling != tiling ||
(tiling != I915_TILING_NONE && bo->pitch != pitch)) {
if (!gem_set_tiling(kgem->fd, bo->handle,
tiling, pitch))
continue;
bo->tiling = tiling;
bo->pitch = pitch;
}
list_del(&bo->list);
bo->unique_id = kgem_get_unique_id(kgem);
DBG((" 1:from scanout: 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;
}
}
if (bucket >= NUM_CACHE_BUCKETS) {
DBG(("%s: large bo num pages=%d, bucket=%d\n",
__FUNCTION__, size, bucket));

View File

@ -133,6 +133,7 @@ struct kgem {
struct list inactive[NUM_CACHE_BUCKETS];
struct list pinned_batches[2];
struct list snoop;
struct list scanout;
struct list batch_buffers, active_buffers;
struct list requests[2];

File diff suppressed because it is too large Load Diff

View File

@ -104,8 +104,7 @@ sna_video_buffer(struct sna *sna,
if (video->tiled) {
video->buf = kgem_create_2d(&sna->kgem,
frame->width, frame->height, 32,
I915_TILING_X,
CREATE_EXACT | CREATE_SCANOUT);
I915_TILING_X, CREATE_EXACT);
} else {
video->buf = kgem_create_linear(&sna->kgem, frame->size,
CREATE_GTT_MAP);