summaryrefslogtreecommitdiff
path: root/src/sna
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-08-08 22:03:16 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2013-08-08 23:18:13 +0100
commitbd7e653e1ee009e225b0bbf60dcaebc9b0fa2788 (patch)
treeddb7852cca6739726920f1fc7233e8400e7668b3 /src/sna
parent097669cd728e612bf3e3c531b83892e37481ee7b (diff)
sna: Avoid leaking stolen framebuffer bo
Framebuffers created from stolen bo were not being released and so the kernel would keep the fb and bo alive, causing the memory to be remain unreusable whilst X lived and us to leak all available stolen memory. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna')
-rw-r--r--src/sna/kgem.c51
1 files changed, 23 insertions, 28 deletions
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 498c2000..ed905889 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1795,30 +1795,6 @@ static void _kgem_bo_delete_buffer(struct kgem *kgem, struct kgem_bo *bo)
io->used = bo->delta;
}
-static void kgem_bo_clear_scanout(struct kgem *kgem, struct kgem_bo *bo)
-{
- assert(bo->scanout);
- assert(!bo->refcnt);
- assert(bo->exec == NULL);
- assert(bo->proxy == NULL);
-
- DBG(("%s: handle=%d, fb=%d (reusable=%d)\n",
- __FUNCTION__, bo->handle, bo->delta, bo->reusable));
- if (bo->delta) {
- /* XXX will leak if we are not DRM_MASTER. *shrug* */
- drmIoctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
- bo->delta = 0;
- }
-
- bo->scanout = false;
- bo->flush = false;
- bo->reusable = true;
-
- if (kgem->has_llc &&
- !gem_set_cacheing(kgem->fd, bo->handle, SNOOPED))
- bo->reusable = false;
-}
-
static bool check_scanout_size(struct kgem *kgem,
struct kgem_bo *bo,
int width, int height)
@@ -3029,15 +3005,34 @@ void kgem_clean_scanout_cache(struct kgem *kgem)
struct kgem_bo *bo;
bo = list_first_entry(&kgem->scanout, struct kgem_bo, list);
+
+ assert(bo->scanout);
+ assert(bo->delta);
+ assert(!bo->refcnt);
+ assert(bo->exec == NULL);
+ assert(bo->proxy == NULL);
+
if (bo->exec || __kgem_busy(kgem, bo->handle))
break;
+ DBG(("%s: handle=%d, fb=%d (reusable=%d)\n",
+ __FUNCTION__, bo->handle, bo->delta, bo->reusable));
list_del(&bo->list);
+
+ /* XXX will leak if we are not DRM_MASTER. *shrug* */
+ drmIoctl(kgem->fd, DRM_IOCTL_MODE_RMFB, &bo->delta);
+ bo->delta = 0;
+ bo->scanout = false;
+
if (!bo->purged) {
- kgem_bo_clear_scanout(kgem, bo);
- __kgem_bo_destroy(kgem, bo);
- } else
- kgem_bo_free(kgem, bo);
+ bo->reusable = true;
+ if (kgem->has_llc &&
+ !gem_set_cacheing(kgem->fd, bo->handle, SNOOPED))
+ bo->reusable = false;
+
+ }
+
+ __kgem_bo_destroy(kgem, bo);
}
}