summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2016-04-30 14:09:05 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2016-04-30 14:10:57 +0100
commite4ef6e9e5b2c8b637356621c60b28d064d40d29c (patch)
treea1bece9f03d6d6f21451bc765cb676f00e94621a
parentbca4e0e35e4ac27f2dcd1a8e5fcbf7ce69cec358 (diff)
sna/dri2: Free the pending back buffer after use
The pending back buffer is only the pending copy, the actual info->back stores the client's view of the current back buffer which may be more recent than the pending copy. So store the current back buffer, swap in the pending to do the normal swap, then free the resultant back (which may have been exchanged with the front), before restoring the client's current back buffer. References: https://bugs.freedesktop.org/show_bug.cgi?id=95200 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_dri2.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 18ff264e..bb7070ed 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -2648,7 +2648,9 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
}
if (info->pending.bo) {
- DBG(("%s: swapping old back handle=%d [name=%d, active=%d] for pending handle=%d [name=%d, active=%d], front handle=%d [name=%d, active=%d]\n",
+ struct copy current_back;
+
+ DBG(("%s: swapping back handle=%d [name=%d, active=%d] for pending handle=%d [name=%d, active=%d], front handle=%d [name=%d, active=%d]\n",
__FUNCTION__,
get_private(info->back)->bo->handle, info->back->name, get_private(info->back)->bo->active_scanout,
info->pending.bo->handle, info->pending.name, info->pending.bo->active_scanout,
@@ -2664,11 +2666,10 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
assert(info->pending.bo->active_scanout > 0);
info->pending.bo->active_scanout--;
- sna_dri2_cache_bo(info->sna, info->draw,
- get_private(info->back)->bo,
- info->back->name,
- get_private(info->back)->size,
- info->back->flags);
+ current_back.bo = get_private(info->back)->bo;
+ current_back.size = get_private(info->back)->size;
+ current_back.name = info->back->name;
+ current_back.flags = info->back->flags;
get_private(info->back)->bo = info->pending.bo;
get_private(info->back)->size = info->pending.size;
@@ -2688,6 +2689,23 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event)
else
__sna_dri2_copy_event(info, info->sync | DRI2_BO);
+ sna_dri2_cache_bo(info->sna, info->draw,
+ get_private(info->back)->bo,
+ info->back->name,
+ get_private(info->back)->size,
+ info->back->flags);
+
+ get_private(info->back)->bo = current_back.bo;
+ get_private(info->back)->size = current_back.size;
+ info->back->name = current_back.name;
+ info->back->pitch = current_back.bo->pitch;
+ info->back->flags = current_back.flags;
+
+ DBG(("%s: restored current back handle=%d [name=%d, active=%d], active=%d], front handle=%d [name=%d, active=%d]\n",
+ __FUNCTION__,
+ get_private(info->back)->bo->handle, info->back->name, get_private(info->back)->bo->active_scanout,
+ get_private(info->front)->bo->handle, info->front->name, get_private(info->front)->bo->active_scanout));
+
assert(info->draw);
info->keepalive++;
info->signal = true;