summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-05-30 21:09:34 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-06-02 08:32:11 +0100
commit8a02886a24c8699374a39a9363e72bec0e7bbe30 (patch)
treec9d3327fd9ec6357bf6829f8accdb3d2a40ca499
parentc17d704a5baa0c902994f035d3da39d77d31fef3 (diff)
sna/dri2: Use real async flips
Presuming that we have both kernel support and Xorg support, of course. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna_dri2.c119
1 files changed, 70 insertions, 49 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 4bfa8e14..27840140 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -91,6 +91,7 @@ enum frame_event_type {
FLIP,
FLIP_THROTTLE,
FLIP_COMPLETE,
+ FLIP_ASYNC,
};
struct dri_bo {
@@ -1251,7 +1252,7 @@ void sna_dri2_destroy_window(WindowPtr win)
}
static void
-update_scanout(struct sna *sna, struct sna_dri2_frame_event *info, struct kgem_bo *bo, int name)
+update_scanout(struct sna *sna, struct kgem_bo *bo, int name)
{
assert(sna->dri2.scanout[1].bo == NULL);
assert(sna->dri2.scanout[0].bo->scanout);
@@ -1264,9 +1265,52 @@ update_scanout(struct sna *sna, struct sna_dri2_frame_event *info, struct kgem_b
DBG(("%s: pending scanout handle=%d, active scanout handle=%d\n",
__FUNCTION__, sna->dri2.scanout[0].bo->handle, sna->dri2.scanout[1].bo->handle));
assert(sna->dri2.scanout[0].bo->handle != sna->dri2.scanout[1].bo->handle);
+}
- assert(sna->dri2.flip_pending == NULL || sna->dri2.flip_pending == info);
- sna->dri2.flip_pending = info;
+static void
+retire_scanout(struct sna *sna,
+ struct sna_dri2_frame_event *flip)
+{
+ struct dri_bo *c = NULL;
+
+ if (sna->dri2.scanout[1].bo == NULL)
+ return;
+
+ DBG(("%s: retiring previous scanout handle=%d, name=%d, refcnt=%d (current scanout handle=%d)\n",
+ __FUNCTION__,
+ sna->dri2.scanout[1].bo->handle,
+ sna->dri2.scanout[1].name,
+ sna->dri2.scanout[1].bo->refcnt,
+ sna->dri2.scanout[0].bo->handle));
+
+ if (flip &&
+ sna->dri2.scanout[1].bo != sna->dri2.scanout[0].bo &&
+ sna->dri2.scanout[1].bo->refcnt == 1) {
+ DBG(("%s: adding old scanout to flip cache\n", __FUNCTION__));
+ if (!list_is_empty(&flip->cache))
+ c = list_last_entry(&flip->cache, struct dri_bo, link);
+ if (c) {
+ if (c->bo == NULL)
+ _list_del(&c->link);
+ else
+ c = NULL;
+ }
+ if (c == NULL)
+ c = malloc(sizeof(*c));
+ if (c != NULL) {
+ c->bo = sna->dri2.scanout[1].bo;
+ c->name = sna->dri2.scanout[1].name;
+ list_add(&c->link, &flip->cache);
+ }
+ }
+
+ if (c == NULL) {
+ DBG(("%s: not caching old scanout handle=%d, still busy\n",
+ __FUNCTION__, sna->dri2.scanout[1].bo->handle));
+ kgem_bo_destroy(&sna->kgem, sna->dri2.scanout[1].bo);
+ }
+
+ sna->dri2.scanout[1].bo = NULL;
}
static bool
@@ -1284,11 +1328,20 @@ sna_dri2_page_flip(struct sna *sna, struct sna_dri2_frame_event *info)
assert(sna->dri2.scanout[1].bo == NULL);
assert(bo->refcnt);
- info->count = sna_page_flip(sna, bo, info, info->pipe);
+ if (info->type == FLIP_ASYNC)
+ info->count = sna_page_flip(sna, bo, NULL, -1);
+ else
+ info->count = sna_page_flip(sna, bo, info, info->pipe);
if (!info->count)
return false;
- update_scanout(sna, info, bo, info->back->name);
+ update_scanout(sna, bo, info->back->name);
+
+ assert(sna->dri2.flip_pending == NULL || sna->dri2.flip_pending == info);
+ if (info->type == FLIP_ASYNC)
+ retire_scanout(sna, NULL);
+ else
+ sna->dri2.flip_pending = info;
DBG(("%s: marked handle=%d as scanout, swap front (handle=%d, name=%d) and back (handle=%d, name=%d)\n",
__FUNCTION__, bo->handle,
@@ -1802,7 +1855,10 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info)
if (!info->count)
return false;
- update_scanout(sna, info, bo, info->front->name);
+ update_scanout(sna, bo, info->front->name);
+
+ assert(sna->dri2.flip_pending == NULL || sna->dri2.flip_pending == info);
+ sna->dri2.flip_pending = info;
}
} else {
info->type = -info->mode;
@@ -1884,45 +1940,7 @@ static void sna_dri2_flip_event(struct sna *sna,
assert(!sna->mode.shadow_flip);
- if (sna->dri2.scanout[1].bo) {
- struct dri_bo *c = NULL;
-
- DBG(("%s: retiring previous scanout handle=%d, name=%d, refcnt=%d (current scanout handle=%d)\n",
- __FUNCTION__,
- sna->dri2.scanout[1].bo->handle,
- sna->dri2.scanout[1].name,
- sna->dri2.scanout[1].bo->refcnt,
- sna->dri2.scanout[0].bo->handle));
-
- if (sna->dri2.scanout[1].bo != sna->dri2.scanout[0].bo &&
- sna->dri2.scanout[1].bo->refcnt == 1) {
- DBG(("%s: adding old scanout to flip cache\n", __FUNCTION__));
- if (!list_is_empty(&flip->cache))
- c = list_last_entry(&flip->cache, struct dri_bo, link);
- if (c) {
- if (c->bo == NULL)
- _list_del(&c->link);
- else
- c = NULL;
- }
- if (c == NULL)
- c = malloc(sizeof(*c));
- if (c != NULL) {
- c->bo = sna->dri2.scanout[1].bo;
- c->name = sna->dri2.scanout[1].name;
- list_add(&c->link, &flip->cache);
- }
- }
-
- if (c == NULL) {
- DBG(("%s: not caching old scanout handle=%d, still busy\n",
- __FUNCTION__, sna->dri2.scanout[1].bo->handle));
- kgem_bo_destroy(&sna->kgem, sna->dri2.scanout[1].bo);
- }
-
- sna->dri2.scanout[1].bo = NULL;
- }
-
+ retire_scanout(sna, flip);
if (sna->dri2.flip_pending == flip)
sna->dri2.flip_pending = NULL;
@@ -2022,8 +2040,9 @@ static int use_triple_buffer(struct sna *sna, ClientPtr client, bool async)
}
if (async) {
- DBG(("%s: running async, using FLIP_COMPLETE\n", __FUNCTION__));
- return FLIP_COMPLETE;
+ DBG(("%s: running async, using %s\n", __FUNCTION__,
+ sna->flags & SNA_HAS_ASYNC_FLIP ? "FLIP_ASYNC" : "FLIP_COMPLETE"));
+ return sna->flags & SNA_HAS_ASYNC_FLIP ? FLIP_ASYNC : FLIP_COMPLETE;
}
#if XORG_CAN_TRIPLE_BUFFER
@@ -2154,18 +2173,21 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
} else {
info->type = type = use_triple_buffer(sna, client, *target_msc == 0);
if (!sna_dri2_page_flip(sna, info)) {
+ DBG(("%s: flip failed, falling back\n", __FUNCTION__));
sna_dri2_frame_event_info_free(sna, draw, info);
return false;
}
}
swap_limit(draw, 1 + (type == FLIP_THROTTLE));
- if (type == FLIP_COMPLETE) {
+ if (type >= FLIP_COMPLETE) {
new_back:
if (!XORG_CAN_TRIPLE_BUFFER)
sna_dri2_get_back(sna, info);
DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
frame_swap_complete(sna, info, DRI2_EXCHANGE_COMPLETE);
+ if (info->type == FLIP_ASYNC)
+ sna_dri2_frame_event_info_free(sna, draw, info);
}
out:
DBG(("%s: target_msc=%llu\n", __FUNCTION__, current_msc + 1));
@@ -2624,7 +2646,6 @@ static const char *dri_driver_name(struct sna *sna)
return s;
}
-
bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
{
DRI2InfoRec info;