summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-05-21 19:16:32 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-05-21 20:12:24 +0100
commit5168a160a1385c23d275d616f2649d5cae7c15d9 (patch)
tree8b0d0cac4c36b971e379a705d9a4703a44bd5c6b /src
parent66e14c96d0ddede90e36084a80a97c3f16c2b386 (diff)
sna/dri2: Decouple queued events
Becareful when reaping a chain on a destroyed window as some events may be queued ahead. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r--src/sna/sna_dri2.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 86ce0dd8..725e2c42 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -906,6 +906,7 @@ struct sna_dri2_frame_event {
xf86CrtcPtr crtc;
int pipe;
int count;
+ bool queued;
/* for swaps & flips only */
DRI2SwapEventPtr event_complete;
@@ -1074,7 +1075,11 @@ void sna_dri2_destroy_window(WindowPtr win)
while ((info = chain)) {
chain = info->chain;
- sna_dri2_frame_event_info_free(sna, NULL, info);
+ if (info->queued) {
+ info->draw = NULL;
+ info->chain = NULL;
+ } else
+ sna_dri2_frame_event_info_free(sna, NULL, info);
}
}
@@ -1120,6 +1125,7 @@ sna_dri2_page_flip(struct sna *sna, struct sna_dri2_frame_event *info)
sna->dri2.flip_pending = info;
+ info->queued = true;
swap_limit(info->draw, 1 + (info->type == FLIP_THROTTLE));
return true;
}
@@ -1336,6 +1342,7 @@ static void chain_swap(struct sna *sna,
vbl.request.sequence = 1;
vbl.request.signal = (unsigned long)chain;
+ chain->queued = true;
if (!sna_wait_vblank(sna, &vbl, chain->pipe))
return;
@@ -1357,6 +1364,7 @@ static void chain_swap(struct sna *sna,
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
vbl.request.signal = (unsigned long)chain;
+ chain->queued = true;
if (sna_wait_vblank(sna, &vbl, chain->pipe)) {
DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__));
DRI2SwapComplete(chain->client, draw,
@@ -1394,7 +1402,7 @@ static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo)
}
static bool sna_dri2_blit_complete(struct sna *sna,
- struct sna_dri2_frame_event *info)
+ struct sna_dri2_frame_event *info)
{
if (rq_is_busy(&sna->kgem, info->bo)) {
union drm_wait_vblank vbl;
@@ -1408,6 +1416,7 @@ static bool sna_dri2_blit_complete(struct sna *sna,
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
vbl.request.signal = (unsigned long)info;
+ assert(info->queued);
if (!sna_wait_vblank(sna, &vbl, info->pipe))
return false;
}
@@ -1425,6 +1434,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
DBG(("%s(type=%d, sequence=%d)\n", __FUNCTION__, info->type, event->sequence));
assert((unsigned)info->pipe < MAX_PIPES);
+ assert(info->queued);
msc = sna_mode_record_event(sna, info->pipe, event);
draw = info->draw;
@@ -1459,6 +1469,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
vbl.request.sequence = 1;
vbl.request.signal = (unsigned long)info;
+ assert(info->queued);
if (!sna_wait_vblank(sna, &vbl, info->pipe))
return;
@@ -1553,8 +1564,10 @@ sna_dri2_immediate_blit(struct sna *sna,
vbl.request.sequence = 1;
vbl.request.signal = (unsigned long)info;
ret = !sna_wait_vblank(sna, &vbl, info->pipe);
- if (ret)
+ if (ret) {
+ info->queued = true;
event = !swap_limit(draw, 2);
+ }
}
if (event) {
DBG(("%s: fake triple bufferring, unblocking client\n", __FUNCTION__));
@@ -1724,8 +1737,10 @@ static void chain_flip(struct sna *sna)
vbl.request.sequence = 1;
vbl.request.signal = (unsigned long)chain;
- if (!sna_wait_vblank(sna, &vbl, chain->pipe))
+ if (!sna_wait_vblank(sna, &vbl, chain->pipe)) {
+ chain->queued = true;
return;
+ }
}
#endif
DBG(("%s: fake triple buffering (or vblank wait failed), unblocking client\n", __FUNCTION__));
@@ -2147,6 +2162,7 @@ out:
return false;
}
+ info->queued = true;
swap_limit(draw, 1);
return true;
}
@@ -2324,6 +2340,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
if (sna_wait_vblank(sna, &vbl, info->pipe))
goto blit;
+ info->queued = true;
swap_limit(draw, 1 + (info->type == SWAP_WAIT));
return TRUE;
@@ -2484,6 +2501,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
if (sna_wait_vblank(sna, &vbl, pipe))
goto out_free_info;
+ info->queued = true;
DRI2BlockClient(client, draw);
return TRUE;