diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2015-08-19 19:59:56 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2015-08-19 20:06:15 +0100 |
commit | 6f3e81d430dc80d892d3ffe8b101ff991040237a (patch) | |
tree | ff1644adc966847c00cacd50fb95167c294233c5 /src/sna/sna_dri2.c | |
parent | e29dc33e3588035ce790e1d534e85a521b2955ce (diff) |
sna/dri2: Consolidate vblank queueing into a couple of helpers
With the rigamorale of assertions, using the vblank is no longer
trivial.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna/sna_dri2.c')
-rw-r--r-- | src/sna/sna_dri2.c | 257 |
1 files changed, 91 insertions, 166 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 41354e83..177b921d 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1413,15 +1413,53 @@ inline static uint32_t pipe_select(int pipe) return 0; } -static inline int sna_wait_vblank(struct sna *sna, union drm_wait_vblank *vbl, int pipe) +static inline bool sna_next_vblank(struct sna_dri2_event *info) { - DBG(("%s(pipe=%d, waiting until seq=%u%s)\n", - __FUNCTION__, pipe, vbl->request.sequence, - vbl->request.type & DRM_VBLANK_RELATIVE ? " [relative]" : "")); - assert(pipe != -1); + union drm_wait_vblank vbl; - vbl->request.type |= pipe_select(pipe); - return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl); + DBG(("%s(pipe=%d, waiting until next vblank)\n", + __FUNCTION__, info->pipe)); + assert(info->pipe != -1); + + VG_CLEAR(vbl); + vbl.request.type = + DRM_VBLANK_RELATIVE | + DRM_VBLANK_EVENT | + pipe_select(info->pipe); + vbl.request.sequence = 1; + vbl.request.signal = (uintptr_t)info; + + assert(!info->queued); + if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl)) + return false; + + info->queued = true; + return true; +} + +static inline bool sna_wait_vblank(struct sna_dri2_event *info, + unsigned seq) +{ + union drm_wait_vblank vbl; + + DBG(("%s(pipe=%d, waiting until vblank %u)\n", + __FUNCTION__, info->pipe, seq)); + assert(info->pipe != -1); + + VG_CLEAR(vbl); + vbl.request.type = + DRM_VBLANK_ABSOLUTE | + DRM_VBLANK_EVENT | + pipe_select(info->pipe); + vbl.request.sequence = seq; + vbl.request.signal = (uintptr_t)info; + + assert(!info->queued); + if (drmIoctl(info->sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, &vbl)) + return false; + + info->queued = true; + return true; } #if DRI2INFOREC_VERSION >= 4 @@ -2376,8 +2414,6 @@ static void sna_dri2_xchg_crtc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr cr static void chain_swap(struct sna_dri2_event *chain) { - union drm_wait_vblank vbl; - DBG(("%s: draw=%ld, queued?=%d, type=%d\n", __FUNCTION__, (long)chain->draw->id, chain->queued, chain->type)); @@ -2399,18 +2435,8 @@ static void chain_swap(struct sna_dri2_event *chain) !chain->sna->mode.shadow_damage) { /* recursed from wait_for_shadow(), simply requeue */ DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__)); - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)chain; - - assert(!chain->queued); - if (!sna_wait_vblank(chain->sna, &vbl, chain->pipe)) { - chain->queued = true; + if (sna_next_vblank(chain)) return; - } DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno)); } @@ -2431,23 +2457,14 @@ static void chain_swap(struct sna_dri2_event *chain) return; } - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)chain; - - assert(!chain->queued); if ((chain->type == SWAP_COMPLETE && !swap_limit(chain->draw, 2 + !chain->sync) && !chain->sync) || - sna_wait_vblank(chain->sna, &vbl, chain->pipe)) { + !sna_next_vblank(chain)) { DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__)); frame_swap_complete(chain, DRI2_BLIT_COMPLETE); sna_dri2_event_free(chain); - } else - chain->queued = true; + } } static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo) @@ -2468,27 +2485,13 @@ static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo) return __kgem_busy(kgem, bo->handle); } -static bool sna_dri2_blit_complete(struct sna *sna, - struct sna_dri2_event *info) +static bool sna_dri2_blit_complete(struct sna_dri2_event *info) { - if (rq_is_busy(&sna->kgem, info->bo)) { - union drm_wait_vblank vbl; - + if (rq_is_busy(&info->sna->kgem, info->bo)) { DBG(("%s: vsync'ed blit is still busy, postponing\n", __FUNCTION__)); - - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)info; - - assert(!info->queued); - if (!sna_wait_vblank(sna, &vbl, info->pipe)) { - info->queued = true; + if (sna_next_vblank(info)) return false; - } } DBG(("%s: blit finished\n", __FUNCTION__)); @@ -2501,7 +2504,6 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event) struct sna_dri2_event *info = (void *)(uintptr_t)event->user_data; struct sna *sna = info->sna; DrawablePtr draw; - union drm_wait_vblank vbl; uint64_t msc; DBG(("%s(type=%d, sequence=%d, draw=%ld)\n", __FUNCTION__, info->type, event->sequence, info->draw ? info->draw->serialNumber : 0)); @@ -2543,18 +2545,8 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event) info->type = SWAP_COMPLETE; } - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)info; - - assert(!info->queued); - if (!sna_wait_vblank(sna, &vbl, info->pipe)) { - info->queued = true; + if (sna_next_vblank(info)) return; - } DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno)); assert(info->pending.bo == NULL); @@ -2566,7 +2558,7 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event) event->sequence, event->tv_sec, event->tv_usec)); if (info->signal) { - if (!sna_dri2_blit_complete(sna, info)) + if (!sna_dri2_blit_complete(info)) return; DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__, @@ -2607,18 +2599,8 @@ void sna_dri2_vblank_handler(struct drm_event_vblank *event) } if (--info->keepalive) { - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)info; - - assert(!info->queued); - if (!sna_wait_vblank(sna, &vbl, info->pipe)) { - info->queued = true; + if (sna_next_vblank(info)) return; - } if (info->signal) { DBG(("%s: triple buffer swap complete, unblocking client (frame=%d, tv=%d.%06d)\n", __FUNCTION__, @@ -2672,8 +2654,6 @@ sna_dri2_immediate_blit(struct sna *sna, info->keepalive = KEEPALIVE; if (chain == info) { - union drm_wait_vblank vbl; - DBG(("%s: no pending blit, starting chain\n", __FUNCTION__)); if (can_xchg(info->sna, info->draw, info->front, info->back)) { @@ -2687,21 +2667,12 @@ sna_dri2_immediate_blit(struct sna *sna, assert(info->signal); - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)info; - - assert(!info->queued); if ((!swap_limit(draw, 2 + !sync) && !sync) || - sna_wait_vblank(sna, &vbl, info->pipe)) { + !sna_next_vblank(info)) { DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); frame_swap_complete(info, DRI2_BLIT_COMPLETE); sna_dri2_event_free(info); } - info->queued = true; return; } @@ -2822,24 +2793,10 @@ static void chain_flip(struct sna *sna) __sna_dri2_copy_event(chain, DRI2_SYNC); if (xorg_can_triple_buffer()) { - union drm_wait_vblank vbl; - - VG_CLEAR(vbl); - chain->type = SWAP_COMPLETE; assert(chain->signal); - - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; - vbl.request.signal = (uintptr_t)chain; - - assert(!chain->queued); - if (!sna_wait_vblank(sna, &vbl, chain->pipe)) { - chain->queued = true; + if (sna_next_vblank(chain)) return; - } } DBG(("%s: fake triple buffering (or vblank wait failed), unblocking client\n", __FUNCTION__)); @@ -2913,16 +2870,24 @@ static void sna_dri2_flip_event(struct sna_dri2_event *flip) } } +static int +sna_query_vblank(struct sna *sna, xf86CrtcPtr crtc, union drm_wait_vblank *vbl) +{ + VG_CLEAR(*vbl); + vbl->request.type = + _DRM_VBLANK_RELATIVE | pipe_select(sna_crtc_pipe(crtc)); + vbl->request.sequence = 0; + + return drmIoctl(sna->kgem.fd, DRM_IOCTL_WAIT_VBLANK, vbl); +} + static uint64_t get_current_msc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc) { union drm_wait_vblank vbl; uint64_t ret; - VG_CLEAR(vbl); - vbl.request.type = _DRM_VBLANK_RELATIVE; - vbl.request.sequence = 0; - if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc)) == 0) + if (sna_query_vblank(sna, crtc, &vbl) == 0) ret = sna_crtc_record_vblank(crtc, &vbl); else ret = sna_crtc_last_swap(crtc)->msc; @@ -3142,25 +3107,12 @@ queue: if (*target_msc <= current_msc + 1 && sna_dri2_flip(info)) { *target_msc = current_msc + 1; } else { - union drm_wait_vblank vbl; - - VG_CLEAR(vbl); - - vbl.request.type = - DRM_VBLANK_ABSOLUTE | - DRM_VBLANK_EVENT; - /* Account for 1 frame extra pageflip delay */ - vbl.reply.sequence = draw_target_seq(draw, *target_msc - 1); - vbl.request.signal = (uintptr_t)info; - - assert(!info->queued); - if (sna_wait_vblank(sna, &vbl, info->pipe)) { + if (!sna_wait_vblank(info, + draw_target_seq(draw, *target_msc - 1))) { sna_dri2_event_free(info); return false; } - - info->queued = true; } DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc)); @@ -3202,7 +3154,6 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, CARD64 remainder, DRI2SwapEventPtr func, void *data) { struct sna *sna = to_sna_from_drawable(draw); - union drm_wait_vblank vbl; xf86CrtcPtr crtc = NULL; struct sna_dri2_event *info = NULL; int type = DRI2_EXCHANGE_COMPLETE; @@ -3296,8 +3247,6 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, func, data)) return TRUE; - VG_CLEAR(vbl); - info = sna_dri2_add_event(sna, draw, client, crtc); if (!info) goto blit; @@ -3319,32 +3268,28 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, return TRUE; } - vbl.request.type = - DRM_VBLANK_ABSOLUTE | - DRM_VBLANK_EVENT; - vbl.request.signal = (uintptr_t)info; - info->type = SWAP; - vbl.request.sequence = draw_target_seq(draw, *target_msc - 1); if (*target_msc <= current_msc + 1) { DBG(("%s: performing blit before queueing\n", __FUNCTION__)); __sna_dri2_copy_event(info, DRI2_SYNC); info->type = SWAP_COMPLETE; + if (!sna_next_vblank(info)) + goto fake; - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.sequence = 1; + DBG(("%s: reported target_msc=%llu\n", + __FUNCTION__, *target_msc)); *target_msc = current_msc + 1; - } + swap_limit(draw, 2); + } else { + if (!sna_wait_vblank(info, + draw_target_seq(draw, *target_msc - 1))) + goto blit; - assert(!info->queued); - if (sna_wait_vblank(sna, &vbl, info->pipe)) - goto blit; - info->queued = true; + DBG(("%s: reported target_msc=%llu (in)\n", + __FUNCTION__, *target_msc)); + swap_limit(draw, 1); + } - DBG(("%s: reported target_msc=%llu\n", __FUNCTION__, *target_msc)); - swap_limit(draw, 1 + (info->type == SWAP_COMPLETE)); return TRUE; blit: @@ -3366,7 +3311,7 @@ skip: if (info != dri2_chain(draw)) goto fake; - assert(info->crtc == crtc); + assert(info->crtc == crtc); info->type = SWAP_COMPLETE; info->event_complete = func; @@ -3376,18 +3321,9 @@ skip: info->front = sna_dri2_reference_buffer(front); info->back = sna_dri2_reference_buffer(back); - VG_CLEAR(vbl); - vbl.request.type = - DRM_VBLANK_RELATIVE | - DRM_VBLANK_EVENT; - vbl.request.signal = (uintptr_t)info; - vbl.request.sequence = 1; - - assert(!info->queued); - if (sna_wait_vblank(sna, &vbl, info->pipe)) + if (!sna_next_vblank(info)) goto fake; - info->queued = true; swap_limit(draw, 2); } else { fake: @@ -3412,21 +3348,16 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) struct sna *sna = to_sna_from_drawable(draw); xf86CrtcPtr crtc = sna_dri2_get_crtc(draw); const struct ust_msc *swap; + union drm_wait_vblank vbl; DBG(("%s(draw=%ld, pipe=%d)\n", __FUNCTION__, draw->id, crtc ? sna_crtc_pipe(crtc) : -1)); - if (crtc != NULL) { - union drm_wait_vblank vbl; - - VG_CLEAR(vbl); - vbl.request.type = _DRM_VBLANK_RELATIVE; - vbl.request.sequence = 0; - if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc)) == 0) - sna_crtc_record_vblank(crtc, &vbl); - } else - /* Drawable not displayed, make up a *monotonic* value */ + /* Drawable not displayed, make up a *monotonic* value */ + if (crtc == NULL) crtc = sna_primary_crtc(sna); + if (sna_query_vblank(sna, crtc, &vbl) == 0) + sna_crtc_record_vblank(crtc, &vbl); swap = sna_crtc_last_swap(crtc); *msc = draw_current_msc(draw, crtc, swap->msc); @@ -3450,7 +3381,6 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc struct sna_dri2_event *info = NULL; xf86CrtcPtr crtc; CARD64 current_msc; - union drm_wait_vblank vbl; const struct ust_msc *swap; crtc = sna_dri2_get_crtc(draw); @@ -3484,8 +3414,6 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc assert(info->crtc == crtc); info->type = WAITMSC; - vbl.request.signal = (uintptr_t)info; - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; /* * If divisor is zero, or current_msc is smaller than target_msc, * we just need to make sure target_msc passes before waking up the @@ -3502,13 +3430,10 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc if (target_msc <= current_msc) target_msc += divisor; } - vbl.request.sequence = draw_target_seq(draw, target_msc); - assert(!info->queued); - if (sna_wait_vblank(sna, &vbl, info->pipe)) + if (!sna_wait_vblank(info, draw_target_seq(draw, target_msc))) goto out_free_info; - info->queued = true; DRI2BlockClient(client, draw); return TRUE; |