diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-06-11 13:54:49 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-06-12 12:09:52 +0100 |
commit | dcb4d323ca19f86fbe0230378ac9035161a70f9e (patch) | |
tree | 98d77dda9c7790b0e1b980a7cf75a29a3c6e56ce /src | |
parent | 19d1e4ee19a93905d8d2496f856a18eb07bc23d6 (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.c | 49 |
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; |