summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2015-06-11 13:54:49 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2015-06-12 12:09:52 +0100
commitdcb4d323ca19f86fbe0230378ac9035161a70f9e (patch)
tree98d77dda9c7790b0e1b980a7cf75a29a3c6e56ce /src
parent19d1e4ee19a93905d8d2496f856a18eb07bc23d6 (diff)
sna/dri2: Mark the pending backbuffer copy as active
In order to perform swap elision for windows, we defer the blit until the next vblank and then do whatever was the last buffer to be presented by the client. Whilst that copy is pending, in the same manner as a pending flip, we cannot hand that buffer back to the client for use (or else they will render over top of it before we copy from it, or even worse we copy from it in the middle of rendering). Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r--src/sna/sna_dri2.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index e540066a..f1c04916 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -69,7 +69,7 @@ static inline struct kgem_bo *ref(struct kgem_bo *bo)
struct sna_dri2_private {
PixmapPtr pixmap;
- struct kgem_bo *bo;
+ struct kgem_bo *bo, *copy;
DRI2Buffer2Ptr proxy;
bool stale;
uint32_t size;
@@ -298,6 +298,9 @@ sna_dri2_get_back(struct sna *sna,
back->name = name;
back->flags = flags;
+ assert(back->pitch);
+ assert(back->name);
+
get_private(back)->stale = false;
}
@@ -381,7 +384,7 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
__FUNCTION__, get_drawable_pixmap(draw)->drawable.serialNumber,
buffer->attachment, get_private(buffer)->bo->handle, buffer->name));
assert(get_private(buffer)->refcnt);
- assert(get_private(buffer)->bo->refcnt > get_private(buffer)->bo->active_scanout);
+ assert(get_private(buffer)->bo->refcnt >= get_private(buffer)->bo->active_scanout);
assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
if (buffer->attachment == DRI2BufferBackLeft &&
@@ -391,7 +394,9 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
assert(get_private(buffer)->bo->refcnt);
assert(get_private(buffer)->bo->active_scanout == 0);
assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
- DBG(("reusing back buffer, age = %d\n", buffer->flags));
+ DBG(("%s: reusing back buffer handle=%d, name=%d, pitch=%d, age=%d\n",
+ __FUNCTION__, get_private(buffer)->bo->handle,
+ buffer->name, buffer->pitch, buffer->flags));
}
}
@@ -2187,6 +2192,7 @@ static void fake_swap_complete(struct sna *sna, ClientPtr client,
static void chain_swap(struct sna_dri2_event *chain)
{
union drm_wait_vblank vbl;
+ struct kgem_bo *tmp;
if (chain->draw == NULL) {
sna_dri2_event_free(chain);
@@ -2221,6 +2227,24 @@ static void chain_swap(struct sna_dri2_event *chain)
DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
}
+ /* We tracked the most recent completed swap in back->copy,
+ * back->bo holds the buffer we last gave back to the client
+ * i.e. its current render target. To simplify our swap
+ * routines, we do an exchange here to emit the copy, then
+ * exchange back again so that we are consistent with the
+ * client once more.
+ */
+ assert(get_private(chain->back)->copy);
+ DBG(("%s: removing active marker [%d] from handle=%d\n",
+ __FUNCTION__,
+ get_private(chain->back)->copy->active_scanout,
+ get_private(chain->back)->copy->handle));
+ assert(get_private(chain->back)->copy->active_scanout);
+ get_private(chain->back)->copy->active_scanout--;
+
+ tmp = get_private(chain->back)->bo;
+ get_private(chain->back)->bo = get_private(chain->back)->copy;
+
if (can_xchg(chain->sna, chain->draw, chain->front, chain->back)) {
sna_dri2_xchg(chain->draw, chain->front, chain->back);
} else if (can_xchg_crtc(chain->sna, chain->draw, chain->front, chain->back, chain->crtc)) {
@@ -2229,6 +2253,10 @@ static void chain_swap(struct sna_dri2_event *chain)
assert(chain->queued);
__sna_dri2_copy_event(chain, 0);
}
+ get_private(chain->back)->bo = tmp;
+ kgem_bo_destroy(&chain->sna->kgem,
+ get_private(chain->back)->copy);
+ get_private(chain->back)->copy = NULL;
case SWAP:
break;
default:
@@ -2438,6 +2466,21 @@ sna_dri2_immediate_blit(struct sna *sna,
return;
}
+ DBG(("%s: adding active marker [%d] to handle=%d, removing [%d] from handle=%d\n",
+ __FUNCTION__,
+ get_private(info->back)->bo->active_scanout,
+ get_private(info->back)->bo->handle,
+ get_private(info->back)->copy ? get_private(info->back)->copy->active_scanout : 0,
+ get_private(info->back)->copy ? get_private(info->back)->copy->handle : 0));
+ if (get_private(info->back)->copy) {
+ get_private(info->back)->copy->active_scanout--;
+ kgem_bo_destroy(&info->sna->kgem,
+ get_private(info->back)->copy);
+ }
+ get_private(info->back)->copy = ref(get_private(info->back)->bo);
+ assert(get_private(info->back)->bo->active_scanout == 0);
+ get_private(info->back)->bo->active_scanout++;
+
if (chain->chain != info && chain->chain->type == SWAP_THROTTLE) {
struct sna_dri2_event *tmp = chain->chain;