xf86-video-intel: src/sna/sna_display.c src/sna/sna_dri2.c
Chris Wilson
ickle at kemper.freedesktop.org
Thu Jan 29 08:51:37 PST 2015
src/sna/sna_display.c | 12 ++
src/sna/sna_dri2.c | 201 +++++++++++++++++++++++++++-----------------------
2 files changed, 121 insertions(+), 92 deletions(-)
New commits:
commit 58fe4089789278a80e422a1e2ab45af4bcdcf34e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Jan 29 11:45:50 2015 +0000
sna/dri2: Keep the per-drawable swap cache alive for 50ms
The purpose is to keep the recent history of buffers for a DRI client
for tracking the relevant age.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index f1bab9e..74de375 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1486,6 +1486,8 @@ static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
if (crtc->client_bo == NULL)
return;
+ assert(crtc->client_bo->refcnt > crtc->client_bo->active_scanout);
+
if (!crtc->transform) {
DrawableRec tmp;
@@ -7022,10 +7024,13 @@ void sna_shadow_set_crtc(struct sna *sna,
assert(!sna_crtc->transform);
if (sna_crtc->client_bo != bo) {
- if (sna_crtc->client_bo)
+ if (sna_crtc->client_bo) {
+ assert(sna_crtc->client_bo->refcnt > sna_crtc->client_bo->active_scanout);
kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
+ }
sna_crtc->client_bo = kgem_bo_reference(bo);
+ assert(sna_crtc->client_bo->refcnt > sna_crtc->client_bo->active_scanout);
sna_crtc_damage(crtc);
}
@@ -7080,6 +7085,7 @@ void sna_shadow_unset_crtc(struct sna *sna,
if (sna_crtc->client_bo == NULL)
return;
+ assert(sna_crtc->client_bo->refcnt > sna_crtc->client_bo->active_scanout);
kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
sna_crtc->client_bo = NULL;
list_del(&sna_crtc->shadow_link);
@@ -7515,8 +7521,10 @@ fixup_shadow:
y = crtc->base->y;
}
- if (crtc->bo == flip_bo)
+ if (crtc->bo == flip_bo) {
+ assert(crtc->bo->refcnt >= crtc->bo->active_scanout);
continue;
+ }
if (flip_bo->pitch != crtc->bo->pitch || (y << 16 | x) != crtc->offset) {
DBG(("%s: changing pitch (new %d =?= old %d) or offset (new %x =?= old %x)\n",
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index bfe84ad..6bb506e 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -134,14 +134,23 @@ struct sna_dri2_event {
struct list cache;
struct list link;
- int mode;
+ int flip_continue;
+ int keepalive;
};
static void sna_dri2_flip_event(struct sna_dri2_event *flip);
+inline static DRI2BufferPtr dri2_window_get_front(WindowPtr win);
static int front_pitch(DrawablePtr draw)
{
- DRI2BufferPtr buffer = sna_pixmap_get_buffer(get_drawable_pixmap(draw));
+ DRI2BufferPtr buffer;
+
+ buffer = NULL;
+ if (draw->type != DRAWABLE_PIXMAP)
+ buffer = dri2_window_get_front((WindowPtr)draw);
+ if (buffer == NULL)
+ buffer = sna_pixmap_get_buffer(get_drawable_pixmap(draw));
+
return buffer ? buffer->pitch : 0;
}
@@ -156,14 +165,16 @@ sna_dri2_get_back(struct sna *sna,
int flags;
bool reuse;
- DBG(("%s: draw size=%dx%d, buffer size=%dx%d, is-scanout? %d, pitch=%d, front pitch=%d\n",
+ DBG(("%s: draw size=%dx%d, back buffer handle=%d size=%dx%d, is-scanout? %d, pitch=%d, front pitch=%d, has-cache?=%d\n",
__FUNCTION__, draw->width, draw->height,
+ get_private(back)->bo->handle,
get_private(back)->size & 0xffff, get_private(back)->size >> 16,
get_private(back)->bo->scanout,
- back->pitch, front_pitch(draw)));
+ back->pitch, front_pitch(draw), info!=NULL));
reuse = (draw->height << 16 | draw->width) == get_private(back)->size;
if (reuse && get_private(back)->bo->scanout)
reuse = front_pitch(draw) == back->pitch;
+ DBG(("%s: reuse backbuffer? %d\n", __FUNCTION__, reuse));
if (reuse) {
bo = get_private(back)->bo;
assert(bo->refcnt);
@@ -180,6 +191,8 @@ sna_dri2_get_back(struct sna *sna,
if (info) {
struct dri_bo *c;
list_for_each_entry(c, &info->cache, link) {
+ DBG(("%s: cache: handle=%d, active=%d\n",
+ __FUNCTION__, c->bo ? c->bo->handle : 0, c->bo ? c->bo->active_scanout : -1));
if (c->bo && c->bo->active_scanout == 0) {
bo = c->bo;
name = c->name;
@@ -189,8 +202,6 @@ sna_dri2_get_back(struct sna *sna,
c->bo = NULL;
break;
}
- DBG(("%s: cache: handle=%d, active=%d\n",
- __FUNCTION__, c->bo ? c->bo->handle : 0, c->bo ? c->bo->active_scanout : -1));
}
}
if (bo == NULL) {
@@ -306,6 +317,8 @@ mark_stale(DRI2BufferPtr back)
* stale frame. (This is mostly useful for tracking down
* driver bugs!)
*/
+ DBG(("%s(handle=%d) => %d\n", __FUNCTION__,
+ get_private(back)->bo->handle, xorg_can_triple_buffer()));
get_private(back)->stale = xorg_can_triple_buffer();
}
@@ -327,7 +340,7 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
if (buffer->attachment == DRI2BufferBackLeft &&
draw->type != DRAWABLE_PIXMAP) {
- DBG(("%s: replacing back buffer\n", __FUNCTION__));
+ DBG(("%s: replacing back buffer on window %ld\n", __FUNCTION__, draw->id));
sna_dri2_get_back(to_sna_from_drawable(draw), draw, buffer, dri2_chain(draw));
assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
@@ -335,7 +348,6 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
assert(get_private(buffer)->bo->active_scanout == 0);
DBG(("reusing back buffer, age = %d\n", buffer->flags));
}
-
}
static bool swap_limit(DrawablePtr draw, int limit)
@@ -354,6 +366,12 @@ static bool swap_limit(DrawablePtr draw, int limit)
#define USE_ASYNC_SWAP 0
#endif
+#if USE_ASYNC_SWAP
+#define KEEPALIVE 4 /* wait ~50ms before discarding swap caches */
+#else
+#define KEEPALIVE 1
+#endif
+
#define COLOR_PREFER_TILING_Y 0
/* Prefer to enable TILING_Y if this buffer will never be a
@@ -1555,6 +1573,7 @@ sna_dri2_flip(struct sna_dri2_event *info)
assert(get_private(info->back)->bo->refcnt);
assert(get_private(info->front)->bo != get_private(info->back)->bo);
+ info->keepalive = KEEPALIVE;
info->queued = true;
return true;
}
@@ -1911,10 +1930,10 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
pixmap->drawable.width,
pixmap->drawable.height));
- DBG(("%s: back_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
- __FUNCTION__, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
- DBG(("%s: front_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
- __FUNCTION__, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
+ DBG(("%s: back_bo handle=%d, pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
+ __FUNCTION__, back_bo->handle, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
+ DBG(("%s: front_bo handle=%d, pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
+ __FUNCTION__, front_bo->handle, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
assert(front_bo->refcnt);
assert(back_bo->refcnt);
@@ -1972,8 +1991,8 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr
if (tmp == NULL) {
back->attachment = -1;
if (get_private(back)->proxy == NULL) {
- get_private(back)->pixmap = get_window_pixmap(win);
- get_private(back)->proxy = sna_dri2_reference_buffer(sna_pixmap_get_buffer(get_private(back)->pixmap));
+ get_private(back)->pixmap = get_private(front)->pixmap;
+ get_private(back)->proxy = sna_dri2_reference_buffer(get_private(front)->proxy ?: front);
}
dri2_window(win)->front = sna_dri2_reference_buffer(back);
return;
@@ -1985,27 +2004,35 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr
get_private(tmp)->refcnt = 1;
get_private(tmp)->bo = get_private(back)->bo;
get_private(tmp)->size = get_private(back)->size;
- get_private(tmp)->pixmap = get_window_pixmap(win);
- get_private(tmp)->proxy = sna_dri2_reference_buffer(sna_pixmap_get_buffer(get_private(tmp)->pixmap));
+ get_private(tmp)->pixmap = get_private(front)->pixmap;
+ get_private(tmp)->proxy = sna_dri2_reference_buffer(get_private(front)->proxy ?: front);
+
dri2_window(win)->front = tmp;
- DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
- back->name = 0;
- back->flags = 0;
- bo = kgem_create_2d(&sna->kgem,
- draw->width, draw->height, draw->bitsPerPixel,
- get_private(back)->bo->tiling,
- CREATE_SCANOUT);
- if (bo != NULL) {
- get_private(back)->bo = bo;
- back->pitch = bo->pitch;
- back->name = kgem_bo_flink(&sna->kgem, bo);
- }
- if (back->name == 0) {
- if (bo != NULL)
- kgem_bo_destroy(&sna->kgem, bo);
- get_private(back)->bo = NULL;
+ if (get_private(front)->proxy) {
+ DBG(("%s: reusing current proxy frontbuffer\n", __FUNCTION__));
+ front->attachment = DRI2BufferBackLeft;
+ ref(get_private(tmp)->bo);
back->attachment = -1;
+ } else {
+ DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
+ back->name = 0;
+ back->flags = 0;
+ bo = kgem_create_2d(&sna->kgem,
+ draw->width, draw->height, draw->bitsPerPixel,
+ get_private(back)->bo->tiling,
+ CREATE_SCANOUT);
+ if (bo != NULL) {
+ get_private(back)->bo = bo;
+ back->pitch = bo->pitch;
+ back->name = kgem_bo_flink(&sna->kgem, bo);
+ }
+ if (back->name == 0) {
+ if (bo != NULL)
+ kgem_bo_destroy(&sna->kgem, bo);
+ get_private(back)->bo = NULL;
+ back->attachment = -1;
+ }
}
}
@@ -2326,45 +2353,38 @@ sna_dri2_immediate_blit(struct sna *sna,
static bool
sna_dri2_flip_continue(struct sna_dri2_event *info)
{
- DBG(("%s(mode=%d)\n", __FUNCTION__, info->mode));
+ struct kgem_bo *bo = get_private(info->front)->bo;
- if (info->mode > 0){
- struct kgem_bo *bo = get_private(info->front)->bo;
+ DBG(("%s(mode=%d)\n", __FUNCTION__, info->flip_continue));
+ assert(info->flip_continue > 0);
- info->type = info->mode;
+ info->type = info->flip_continue;
- if (bo != sna_pixmap(info->sna->front)->gpu_bo)
- return false;
-
- if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info))
- return false;
-
- assert(info->sna->dri2.flip_pending == NULL ||
- info->sna->dri2.flip_pending == info);
- info->sna->dri2.flip_pending = info;
- assert(info->queued);
- } else {
- info->type = -info->mode;
+ if (bo != sna_pixmap(info->sna->front)->gpu_bo)
+ return false;
- if (!info->draw)
- return false;
+ if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info))
+ return false;
- if (!can_flip(info->sna, info->draw, info->front, info->back, info->crtc))
- return false;
+ assert(info->sna->dri2.flip_pending == NULL ||
+ info->sna->dri2.flip_pending == info);
+ info->sna->dri2.flip_pending = info;
+ assert(info->queued);
- assert(sna_pixmap_get_buffer(get_drawable_pixmap(info->draw)) == info->front);
- if (!sna_dri2_flip(info))
- return false;
+ info->flip_continue = 0;
+ return true;
+}
- if (!xorg_can_triple_buffer()) {
- sna_dri2_get_back(info->sna, info->draw, info->back, info);
- DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
- frame_swap_complete(info, DRI2_FLIP_COMPLETE);
- }
- }
+static bool
+sna_dri2_flip_keepalive(struct sna_dri2_event *info)
+{
+ DBG(("%s(keepalive?=%d)\n", __FUNCTION__, info->keepalive-1));
+ assert(info->keepalive > 0);
+ if (!--info->keepalive)
+ return false;
- info->mode = 0;
- return true;
+ info->flip_continue = FLIP_COMPLETE;
+ return sna_dri2_flip_continue(info);
}
static void chain_flip(struct sna *sna)
@@ -2443,22 +2463,24 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip)
frame_swap_complete(flip, DRI2_FLIP_COMPLETE);
case FLIP_COMPLETE:
if (sna->dri2.flip_pending) {
+ DBG(("%s: pending flip\n", __FUNCTION__));
sna_dri2_event_free(flip);
chain_flip(sna);
- } else if (!flip->mode) {
+ } else if (!flip->flip_continue) {
DBG(("%s: flip chain complete\n", __FUNCTION__));
+ if (!sna_dri2_flip_keepalive(flip)) {
+ if (flip->chain) {
+ sna_dri2_remove_event((WindowPtr)flip->draw,
+ flip);
+ chain_swap(flip->chain);
+ flip->draw = NULL;
+ }
- if (flip->chain) {
- sna_dri2_remove_event((WindowPtr)flip->draw,
- flip);
- chain_swap(flip->chain);
- flip->draw = NULL;
+ sna_dri2_event_free(flip);
}
-
- sna_dri2_event_free(flip);
} else if (!sna_dri2_flip_continue(flip)) {
DBG(("%s: no longer able to flip\n", __FUNCTION__));
- if (flip->draw == NULL || !sna_dri2_immediate_blit(sna, flip, false, flip->mode < 0))
+ if (flip->draw == NULL || !sna_dri2_immediate_blit(sna, flip, false, flip->flip_continue == FLIP_COMPLETE))
sna_dri2_event_free(flip);
}
break;
@@ -2579,7 +2601,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
info = sna->dri2.flip_pending;
DBG(("%s: performing immediate swap on pipe %d, pending? %d, mode: %d, continuation? %d\n",
__FUNCTION__, sna_crtc_to_pipe(crtc),
- info != NULL, info ? info->mode : 0,
+ info != NULL, info ? info->flip_continue : 0,
info && info->draw == draw));
if (info && info->draw == draw) {
@@ -2589,21 +2611,16 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
_sna_dri2_destroy_buffer(sna, info->back);
info->back = sna_dri2_reference_buffer(back);
}
- if (info->mode || current_msc >= *target_msc) {
- DBG(("%s: executing xchg of pending flip\n",
- __FUNCTION__));
- sna_dri2_xchg(draw, front, back);
- info->mode = type = FLIP_COMPLETE;
- goto new_back;
- } else {
+ DBG(("%s: executing xchg of pending flip\n", __FUNCTION__));
+ sna_dri2_xchg(draw, front, back);
+ if (!info->flip_continue && current_msc < *target_msc) {
DBG(("%s: chaining flip\n", __FUNCTION__));
- type = FLIP_THROTTLE;
+ info->flip_continue = FLIP_THROTTLE;
+ info->keepalive++;
if (xorg_can_triple_buffer())
- info->mode = -type;
- else
- info->mode = -FLIP_COMPLETE;
- goto out;
+ goto out;
}
+ goto new_back;
}
info = sna_dri2_add_event(sna, draw, client);
@@ -2626,7 +2643,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
__FUNCTION__));
info->type = type = FLIP;
sna->dri2.flip_pending = info;
- assert(info->queued);
+ assert(!info->queued);
current_msc++;
} else {
info->type = type = use_triple_buffer(sna, client, *target_msc == 0);
@@ -2727,8 +2744,9 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, ¤t_msc))
return false;
- sync = current_msc < *target_msc;
+ sync = current_msc < *target_msc && xorg_can_triple_buffer();
event = dri2_chain(draw) == NULL;
+ DBG(("%s: synchronous?=%d, send-event?=%d\n", __FUNCTION__, sync, event));
if (!sync || event) {
DBG(("%s: performing immediate xchg on pipe %d\n",
__FUNCTION__, sna_crtc_to_pipe(crtc)));
@@ -2760,6 +2778,7 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
info->queued = true;
if (sna_wait_vblank(sna, &vbl, info->pipe)) {
+ DBG(("%s: vblank queue failed, unblocking client\n", __FUNCTION__));
sna_dri2_event_free(info);
goto complete;
}
@@ -2788,8 +2807,9 @@ sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc
if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, ¤t_msc))
return false;
- sync = current_msc < *target_msc;
+ sync = current_msc < *target_msc && xorg_can_triple_buffer();
event = dri2_chain(draw) == NULL;
+ DBG(("%s: synchronous?=%d, send-event?=%d\n", __FUNCTION__, sync, event));
if (!sync || event) {
DBG(("%s: performing immediate xchg only on pipe %d\n",
__FUNCTION__, sna_crtc_to_pipe(crtc)));
@@ -2821,6 +2841,7 @@ sna_dri2_schedule_xchg_crtc(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc
info->queued = true;
if (sna_wait_vblank(sna, &vbl, info->pipe)) {
+ DBG(("%s: vblank queue failed, unblocking client\n", __FUNCTION__));
sna_dri2_event_free(info);
goto complete;
}
@@ -3089,8 +3110,8 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
swap = sna_crtc_last_swap(crtc);
*msc = draw_current_msc(draw, crtc, swap->msc);
*ust = ust64(swap->tv_sec, swap->tv_usec);
- DBG(("%s: msc=%llu, ust=%llu\n", __FUNCTION__,
- (long long)*msc, (long long)*ust));
+ DBG(("%s: msc=%llu [raw=%llu], ust=%llu\n", __FUNCTION__,
+ (long long)*msc, swap->msc, (long long)*ust));
return TRUE;
}
More information about the xorg-commit
mailing list