diff options
-rw-r--r-- | src/sna/sna.h | 52 | ||||
-rw-r--r-- | src/sna/sna_display.c | 49 | ||||
-rw-r--r-- | src/sna/sna_dri2.c | 103 |
3 files changed, 111 insertions, 93 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index c3eb248e..f88690c4 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -72,8 +72,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include <signal.h> #include <setjmp.h> -#define MAX_PIPES 4 - #include "compiler.h" #if HAS_DEBUG_FULL @@ -289,17 +287,6 @@ struct sna { unsigned serial; uint32_t *encoders; - - struct { - uint64_t msc; - unsigned int tv_sec; - unsigned int tv_usec; - } last_swap[MAX_PIPES]; - - struct { - uint32_t last; - uint32_t wraps; - } msc[MAX_PIPES]; } mode; struct { @@ -469,43 +456,30 @@ extern xf86CrtcPtr sna_covering_crtc(struct sna *sna, extern bool sna_wait_for_scanline(struct sna *sna, PixmapPtr pixmap, xf86CrtcPtr crtc, const BoxRec *clip); -static inline uint64_t msc64(struct sna *sna, int pipe, uint32_t seq) -{ - assert((unsigned)pipe < MAX_PIPES); - if ((int32_t)(seq - sna->mode.msc[pipe].last) < -0x40000000) { - sna->mode.msc[pipe].wraps++; - DBG(("%s: pipe=%d wrapped was %u, now %u, wraps=%u\n", - __FUNCTION__, pipe, sna->mode.msc[pipe].last, seq, - sna->mode.msc[pipe].wraps)); - } - sna->mode.msc[pipe].last = seq; - return (uint64_t)sna->mode.msc[pipe].wraps << 32 | seq; -} +xf86CrtcPtr sna_mode_first_crtc(struct sna *sna); -static inline uint64_t sna_mode_record_swap(struct sna *sna, int pipe, - int tv_sec, int tv_usec, unsigned seq) -{ - DBG(("%s: recording last swap on pipe=%d, frame %d, time %d.%06d\n", - __FUNCTION__, pipe, seq, tv_sec, tv_usec)); - assert((unsigned)pipe < MAX_PIPES); - sna->mode.last_swap[pipe].tv_sec = tv_sec; - sna->mode.last_swap[pipe].tv_usec = tv_usec; - return sna->mode.last_swap[pipe].msc = msc64(sna, pipe, seq); -} +const struct ust_msc { + uint64_t msc; + int tv_sec; + int tv_usec; +} *sna_crtc_last_swap(xf86CrtcPtr crtc); + +uint64_t sna_crtc_record_swap(xf86CrtcPtr crtc, + int tv_sec, int tv_usec, unsigned seq); -static inline uint64_t sna_mode_record_vblank(struct sna *sna, int pipe, +static inline uint64_t sna_crtc_record_vblank(xf86CrtcPtr crtc, const union drm_wait_vblank *vbl) { - return sna_mode_record_swap(sna, pipe, + return sna_crtc_record_swap(crtc, vbl->reply.tval_sec, vbl->reply.tval_usec, vbl->reply.sequence); } -static inline uint64_t sna_mode_record_event(struct sna *sna, int pipe, +static inline uint64_t sna_crtc_record_event(xf86CrtcPtr crtc, struct drm_event_vblank *event) { - return sna_mode_record_swap(sna, pipe, + return sna_crtc_record_swap(crtc, event->tv_sec, event->tv_usec, event->sequence); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 63631efe..a81ce212 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -119,6 +119,9 @@ struct sna_crtc { uint32_t rotation; struct rotation primary_rotation; struct rotation sprite_rotation; + + uint32_t last_seq, wrap_seq; + struct ust_msc swap; }; struct sna_property { @@ -228,6 +231,52 @@ int sna_crtc_is_on(xf86CrtcPtr crtc) return to_sna_crtc(crtc)->bo != NULL; } +static inline uint64_t msc64(struct sna_crtc *sna_crtc, uint32_t seq) +{ + if ((int32_t)(seq - sna_crtc->last_seq) < -0x40000000) { + sna_crtc->wrap_seq++; + DBG(("%s: pipe=%d wrapped was %u, now %u, wraps=%u\n", + __FUNCTION__, sna_crtc->pipe, + sna_crtc->last_seq, seq, sna_crtc->wrap_seq)); + } + sna_crtc->last_seq = seq; + return (uint64_t)sna_crtc->wrap_seq << 32 | seq; +} + +uint64_t sna_crtc_record_swap(xf86CrtcPtr crtc, + int tv_sec, int tv_usec, unsigned seq) +{ + struct sna_crtc *sna_crtc = to_sna_crtc(crtc); + assert(sna_crtc); + DBG(("%s: recording last swap on pipe=%d, frame %d, time %d.%06d\n", + __FUNCTION__, sna_crtc->pipe, seq, tv_sec, tv_usec)); + sna_crtc->swap.tv_sec = tv_sec; + sna_crtc->swap.tv_usec = tv_usec; + return sna_crtc->swap.msc = msc64(sna_crtc, seq); +} + +const struct ust_msc *sna_crtc_last_swap(xf86CrtcPtr crtc) +{ + static struct ust_msc zero; + + if (crtc == NULL) { + return &zero; + } else { + struct sna_crtc *sna_crtc = to_sna_crtc(crtc); + assert(sna_crtc); + return &sna_crtc->swap; + } +} + +xf86CrtcPtr sna_mode_first_crtc(struct sna *sna) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn); + if (sna->mode.num_real_crtc) + return config->crtc[0]; + else + return NULL; +} + #ifndef NDEBUG static void gem_close(int fd, uint32_t handle); static void assert_scanout(struct kgem *kgem, struct kgem_bo *bo, diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 15957215..43381d23 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1305,18 +1305,19 @@ sna_dri2_exchange_buffers(DrawablePtr draw, back->name = tmp; } -static void fake_swap_complete(struct sna *sna, - ClientPtr client, DrawablePtr draw, int type, - DRI2SwapEventPtr func, void *data) +static void fake_swap_complete(struct sna *sna, ClientPtr client, + DrawablePtr draw, xf86CrtcPtr crtc, + int type, DRI2SwapEventPtr func, void *data) { - DBG(("%s: frame=%lld, tv=%d.%06d\n", __FUNCTION__, - (long long)sna->mode.last_swap[0].msc, - sna->mode.last_swap[0].tv_sec, - sna->mode.last_swap[0].tv_usec)); + const struct ust_msc *swap; + + swap = sna_crtc_last_swap(crtc); + DBG(("%s: pipe=%d, frame=%lld, tv=%d.%06d\n", + __FUNCTION__, crtc ? sna_crtc_to_pipe(crtc) : -1, + (long long)swap->msc, swap->tv_sec, swap->tv_usec)); + DRI2SwapComplete(client, draw, - sna->mode.last_swap[0].msc, - sna->mode.last_swap[0].tv_sec, - sna->mode.last_swap[0].tv_usec, + swap->msc, swap->tv_sec, swap->tv_usec, type, func, data); } @@ -1433,9 +1434,8 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event) uint64_t msc; 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); + msc = sna_crtc_record_event(info->crtc, event); draw = info->draw; if (draw == NULL) { @@ -1571,7 +1571,8 @@ sna_dri2_immediate_blit(struct sna *sna, } if (event) { DBG(("%s: fake triple bufferring, unblocking client\n", __FUNCTION__)); - fake_swap_complete(sna, info->client, draw, + fake_swap_complete(sna, info->client, + draw, info->crtc, DRI2_BLIT_COMPLETE, info->event_complete, info->event_data); @@ -1690,7 +1691,7 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info) sna_dri2_flip_get_back(sna, info); #if !XORG_CAN_TRIPLE_BUFFER DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); - fake_swap_complete(sna, info->client, info->draw, + fake_swap_complete(sna, info->client, info->draw, info->crtc, DRI2_FLIP_COMPLETE, info->event_complete, info->event_data); #endif @@ -1745,7 +1746,7 @@ static void chain_flip(struct sna *sna) #endif DBG(("%s: fake triple buffering (or vblank wait failed), unblocking client\n", __FUNCTION__)); fake_swap_complete(sna, chain->client, chain->draw, - DRI2_BLIT_COMPLETE, + chain->crtc, DRI2_BLIT_COMPLETE, chain->event_complete, chain->event_data); sna_dri2_frame_event_info_free(sna, chain->draw, chain); } @@ -1880,7 +1881,7 @@ sna_dri2_page_flip_handler(struct sna *sna, /* Is this the event whose info shall be delivered to higher level? */ if (event->user_data & 1) { - info->fe_frame = sna_mode_record_event(sna, info->pipe, event); + info->fe_frame = sna_crtc_record_event(info->crtc, event); info->fe_tv_sec = event->tv_sec; info->fe_tv_usec = event->tv_usec; } @@ -1893,16 +1894,16 @@ sna_dri2_page_flip_handler(struct sna *sna, } static CARD64 -get_current_msc(struct sna *sna, int pipe) +get_current_msc(struct sna *sna, xf86CrtcPtr crtc) { union drm_wait_vblank vbl; CARD64 ret = -1; VG_CLEAR(vbl); - vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe); + vbl.request.type = DRM_VBLANK_RELATIVE; vbl.request.sequence = 0; - if (sna_wait_vblank(sna, &vbl, pipe) == 0) - ret = sna_mode_record_vblank(sna, pipe, &vbl); + if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0) + ret = sna_crtc_record_vblank(crtc, &vbl); return ret; } @@ -1952,7 +1953,7 @@ static int use_triple_buffer(struct sna *sna, ClientPtr client, bool async) static bool immediate_swap(struct sna *sna, uint64_t target_msc, uint64_t divisor, - int pipe, + xf86CrtcPtr crtc, uint64_t *current_msc) { if (divisor == 0) { @@ -1964,7 +1965,7 @@ static bool immediate_swap(struct sna *sna, } if (target_msc) - *current_msc = get_current_msc(sna, pipe); + *current_msc = get_current_msc(sna, crtc); DBG(("%s: current_msc=%ld, target_msc=%ld -- %s\n", __FUNCTION__, (long)*current_msc, (long)target_msc, @@ -1974,7 +1975,7 @@ static bool immediate_swap(struct sna *sna, DBG(("%s: explicit waits requests, divisor=%ld\n", __FUNCTION__, (long)divisor)); - *current_msc = get_current_msc(sna, pipe); + *current_msc = get_current_msc(sna, crtc); return false; } @@ -1990,7 +1991,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc, union drm_wait_vblank vbl; CARD64 current_msc; - if (immediate_swap(sna, *target_msc, divisor, pipe, ¤t_msc)) { + if (immediate_swap(sna, *target_msc, divisor, crtc, ¤t_msc)) { int type; info = sna->dri2.flip_pending; @@ -2067,7 +2068,8 @@ new_back: sna_dri2_flip_get_back(sna, info); if (type == FLIP_COMPLETE) { DBG(("%s: fake triple bufferring, unblocking client\n", __FUNCTION__)); - fake_swap_complete(sna, client, draw, DRI2_EXCHANGE_COMPLETE, func, data); + fake_swap_complete(sna, client, draw, info->crtc, + DRI2_EXCHANGE_COMPLETE, func, data); } } out: @@ -2194,7 +2196,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, { struct sna *sna = to_sna_from_drawable(draw); union drm_wait_vblank vbl; - xf86CrtcPtr crtc; + xf86CrtcPtr crtc = NULL; struct sna_dri2_frame_event *info = NULL; CARD64 current_msc; @@ -2231,7 +2233,6 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, assert(sna_pixmap_from_drawable(draw)->flush); /* Drawable not displayed... just complete the swap */ - crtc = NULL; if ((sna->flags & SNA_NO_WAIT) == 0) crtc = sna_dri2_get_crtc(draw); if (crtc == NULL) { @@ -2267,7 +2268,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, info->type = SWAP; - if (immediate_swap(sna, *target_msc, divisor, info->pipe, ¤t_msc)) { + if (immediate_swap(sna, *target_msc, divisor, info->crtc, ¤t_msc)) { bool sync = current_msc < *target_msc; if (!sna_dri2_immediate_blit(sna, info, sync, true)) sna_dri2_frame_event_info_free(sna, draw, info); @@ -2353,20 +2354,13 @@ blit: sna_dri2_frame_event_info_free(sna, draw, info); skip: DBG(("%s: unable to show frame, unblocking client\n", __FUNCTION__)); - fake_swap_complete(sna, client, draw, DRI2_BLIT_COMPLETE, func, data); + if (crtc == NULL) + crtc = sna_mode_first_crtc(sna); + fake_swap_complete(sna, client, draw, crtc, DRI2_BLIT_COMPLETE, func, data); *target_msc = 0; /* offscreen, so zero out target vblank count */ return TRUE; } -static int sna_dri2_get_pipe(DrawablePtr draw) -{ - int pipe = -1; - xf86CrtcPtr crtc = sna_dri2_get_crtc(draw); - if (crtc) - pipe = sna_crtc_to_pipe(crtc); - return pipe; -} - /* * Get current frame count and frame count timestamp, based on drawable's * crtc. @@ -2376,28 +2370,27 @@ sna_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) { struct sna *sna = to_sna_from_drawable(draw); union drm_wait_vblank vbl; - int pipe; + xf86CrtcPtr crtc = sna_dri2_get_crtc(draw); - pipe = sna_dri2_get_pipe(draw); - DBG(("%s(pipe=%d)\n", __FUNCTION__, pipe)); - if (pipe == -1) { + DBG(("%s(pipe=%d)\n", __FUNCTION__, crtc ? sna_crtc_to_pipe(crtc) : -1)); + if (crtc == NULL) { + const struct ust_msc *swap; + + crtc = sna_mode_first_crtc(sna); fail: /* Drawable not displayed, make up a *monotonic* value */ - assert(pipe < MAX_PIPES); - if (pipe < 0) - pipe = 0; - *msc = sna->mode.last_swap[pipe].msc; - *ust = ust64(sna->mode.last_swap[pipe].tv_sec, - sna->mode.last_swap[pipe].tv_usec); + swap = sna_crtc_last_swap(crtc); + *msc = swap->msc; + *ust = ust64(swap->tv_sec, swap->tv_usec); return TRUE; } VG_CLEAR(vbl); vbl.request.type = DRM_VBLANK_RELATIVE; vbl.request.sequence = 0; - if (sna_wait_vblank(sna, &vbl, pipe) == 0) { + if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(crtc)) == 0) { *ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec); - *msc = sna_mode_record_vblank(sna, pipe, &vbl); + *msc = sna_crtc_record_vblank(crtc, &vbl); DBG(("%s: msc=%llu, ust=%llu\n", __FUNCTION__, (long long)*msc, (long long)*ust)); } else { @@ -2424,6 +2417,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc xf86CrtcPtr crtc; CARD64 current_msc; union drm_wait_vblank vbl; + const struct ust_msc *swap; int pipe = 0; crtc = sna_dri2_get_crtc(draw); @@ -2447,7 +2441,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc if (sna_wait_vblank(sna, &vbl, pipe)) goto out_complete; - current_msc = sna_mode_record_vblank(sna, pipe, &vbl); + current_msc = sna_crtc_record_vblank(crtc, &vbl); /* If target_msc already reached or passed, set it to * current_msc to ensure we return a reasonable value back @@ -2497,10 +2491,11 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc out_free_info: sna_dri2_frame_event_info_free(sna, draw, info); out_complete: + if (crtc == NULL) + crtc = sna_mode_first_crtc(sna); + swap = sna_crtc_last_swap(crtc); DRI2WaitMSCComplete(client, draw, - sna->mode.last_swap[pipe].msc, - sna->mode.last_swap[pipe].tv_sec, - sna->mode.last_swap[pipe].tv_usec); + swap->msc, swap->tv_sec, swap->tv_usec); return TRUE; } #else |