diff options
-rw-r--r-- | src/drmmode_display.c | 63 | ||||
-rw-r--r-- | src/drmmode_display.h | 5 | ||||
-rw-r--r-- | src/radeon.h | 2 | ||||
-rw-r--r-- | src/radeon_dri2.c | 103 | ||||
-rw-r--r-- | src/radeon_kms.c | 22 | ||||
-rw-r--r-- | src/radeon_present.c | 23 |
6 files changed, 85 insertions, 133 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 46a579ff..d86f8300 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -243,6 +243,41 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn, } /* + * Utility helper for drmWaitVBlank + */ +Bool +drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, + uint32_t target_seq, unsigned long signal, uint64_t *ust, + uint32_t *result_seq) +{ + int crtc_id = drmmode_get_crtc_id(crtc); + ScrnInfoPtr scrn = crtc->scrn; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + drmVBlank vbl; + + if (crtc_id == 1) + type |= DRM_VBLANK_SECONDARY; + else if (crtc_id > 1) + type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & + DRM_VBLANK_HIGH_CRTC_MASK; + + vbl.request.type = type; + vbl.request.sequence = target_seq; + vbl.request.signal = signal; + + if (drmWaitVBlank(pRADEONEnt->fd, &vbl) != 0) + return FALSE; + + if (ust) + *ust = (uint64_t)vbl.reply.tval_sec * 1000000 + + vbl.reply.tval_usec; + if (result_seq) + *result_seq = vbl.reply.sequence; + + return TRUE; +} + +/* * Retrieves present time in microseconds that is compatible * with units used by vblank timestamps. Depending on the kernel * version and DRM kernel module configuration, the vblank @@ -272,23 +307,15 @@ int drmmode_get_current_ust(int drm_fd, CARD64 *ust) int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) { ScrnInfoPtr scrn = crtc->scrn; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); - drmVBlank vbl; - int ret; - - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; + uint32_t seq; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, ust, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); - return ret; + return -1; } - *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; - *msc = vbl.reply.sequence; + *msc = seq; return Success; } @@ -305,7 +332,7 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) drmmode_crtc->pending_dpms_mode = mode; if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) { - drmVBlank vbl; + uint32_t seq; /* Wait for any pending flip to finish */ if (drmmode_crtc->flip_pending) @@ -315,20 +342,14 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) * On->Off transition: record the last vblank time, * sequence number and frame period. */ - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, &ust, + &seq)) xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get last vblank counter\n", __func__); else { - CARD64 seq = (CARD64)vbl.reply.sequence; CARD64 nominal_frame_rate, pix_in_frame; - ust = ((CARD64)vbl.reply.tval_sec * 1000000) + - vbl.reply.tval_usec; drmmode_crtc->dpms_last_ust = ust; drmmode_crtc->dpms_last_seq = seq; nominal_frame_rate = crtc->mode.Clock; diff --git a/src/drmmode_display.h b/src/drmmode_display.h index f2104789..71d1c4a4 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -226,5 +226,10 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc); int drmmode_get_current_ust(int drm_fd, CARD64 *ust); +Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, + uint32_t target_seq, unsigned long signal, + uint64_t *ust, uint32_t *result_seq); + + #endif diff --git a/src/radeon.h b/src/radeon.h index d815d3f0..b93e2816 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -693,8 +693,6 @@ extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn, void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size); extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn); -drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc); - static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix) { #ifdef USE_GLAMOR diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index 80b17f1f..a0deb6ba 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -889,26 +889,6 @@ cleanup: radeon_dri2_frame_event_abort(crtc, event_data); } -drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc) -{ - drmVBlankSeqType type = 0; - int crtc_id = drmmode_get_crtc_id(crtc); - - if (crtc_id == 1) - type |= DRM_VBLANK_SECONDARY; - else if (crtc_id > 1) -#ifdef DRM_VBLANK_HIGH_CRTC_SHIFT - type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & - DRM_VBLANK_HIGH_CRTC_MASK; -#else - ErrorF("radeon driver bug: %s called for CRTC %d > 1, but " - "DRM_VBLANK_HIGH_CRTC_MASK not defined at build time\n", - __func__, crtc_id); -#endif - - return type; -} - /* * This function should be called on a disabled CRTC only (i.e., CRTC * in DPMS-off state). It will calculate the delay necessary to reach @@ -1087,13 +1067,11 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, { ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); DRI2FrameEventPtr wait_info = NULL; uintptr_t drm_queue_seq = 0; xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); uint32_t msc_delta; - drmVBlank vbl; - int ret; + uint32_t seq; CARD64 current_msc; /* Truncate to match kernel interfaces; means occasional overflow @@ -1132,17 +1110,13 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, } /* Get current count */ - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); goto out_complete; } - current_msc = vbl.reply.sequence + msc_delta; + current_msc = seq + msc_delta; current_msc &= 0xffffffff; drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, @@ -1169,12 +1143,9 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, */ if (current_msc >= target_msc) target_msc = current_msc; - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - vbl.request.sequence = target_msc - msc_delta; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, + target_msc - msc_delta, drm_queue_seq, NULL, + NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); goto out_complete; @@ -1188,11 +1159,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, * If we get here, target_msc has already passed or we don't have one, * so we queue an event that will satisfy the divisor/remainder equation. */ - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - - vbl.request.sequence = current_msc - (current_msc % divisor) + - remainder - msc_delta; + target_msc = current_msc - (current_msc % divisor) + remainder - msc_delta; /* * If calculated remainder is larger than requested remainder, @@ -1201,11 +1168,10 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, * that will happen. */ if ((current_msc % divisor) >= remainder) - vbl.request.sequence += divisor; + target_msc += divisor; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, + target_msc, drm_queue_seq, NULL, NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "get vblank counter failed: %s\n", strerror(errno)); goto out_complete; @@ -1249,14 +1215,14 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, { ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); uint32_t msc_delta; - drmVBlank vbl; - int ret, flip = 0; + drmVBlankSeqType type; + uint32_t seq; + int flip = 0; DRI2FrameEventPtr swap_info = NULL; uintptr_t drm_queue_seq; - CARD64 current_msc; + CARD64 current_msc, event_msc; BoxRec box; RegionRec region; @@ -1319,18 +1285,14 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, } /* Get current count */ - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "first get vblank counter failed: %s\n", strerror(errno)); goto blit_fallback; } - current_msc = vbl.reply.sequence + msc_delta; + current_msc = seq + msc_delta; current_msc &= 0xffffffff; /* Flips need to be submitted one frame before */ @@ -1352,14 +1314,13 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, * the swap. */ if (divisor == 0 || current_msc < *target_msc) { - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; /* If non-pageflipping, but blitting/exchanging, we need to use * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later * on. */ if (flip == 0) - vbl.request.type |= DRM_VBLANK_NEXTONMISS; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); + type |= DRM_VBLANK_NEXTONMISS; /* If target_msc already reached or passed, set it to * current_msc to ensure we return a reasonable value back @@ -1368,17 +1329,15 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, if (current_msc >= *target_msc) *target_msc = current_msc; - vbl.request.sequence = *target_msc - msc_delta; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, type, *target_msc - msc_delta, + drm_queue_seq, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "divisor 0 get vblank counter failed: %s\n", strerror(errno)); goto blit_fallback; } - *target_msc = vbl.reply.sequence + flip + msc_delta; + *target_msc = seq + flip + msc_delta; swap_info->frame = *target_msc; return TRUE; @@ -1389,13 +1348,11 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, * and we need to queue an event that will satisfy the divisor/remainder * equation. */ - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; if (flip == 0) - vbl.request.type |= DRM_VBLANK_NEXTONMISS; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); + type |= DRM_VBLANK_NEXTONMISS; - vbl.request.sequence = current_msc - (current_msc % divisor) + - remainder - msc_delta; + event_msc = current_msc - (current_msc % divisor) + remainder - msc_delta; /* * If the calculated deadline vbl.request.sequence is smaller than @@ -1408,15 +1365,13 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, * into account, as well as a potential DRM_VBLANK_NEXTONMISS delay * if we are blitting/exchanging instead of flipping. */ - if (vbl.request.sequence <= current_msc) - vbl.request.sequence += divisor; + if (event_msc <= current_msc) + event_msc += divisor; /* Account for 1 frame extra pageflip delay if flip > 0 */ - vbl.request.sequence -= flip; + event_msc -= flip; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (ret) { + if (!drmmode_wait_vblank(crtc, type, event_msc, drm_queue_seq, NULL, &seq)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "final get vblank counter failed: %s\n", strerror(errno)); @@ -1424,7 +1379,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, } /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ - *target_msc = vbl.reply.sequence + flip + msc_delta; + *target_msc = seq + flip + msc_delta; *target_msc &= 0xffffffff; swap_info->frame = *target_msc; diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 5ae94f5c..423d36cb 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -722,11 +722,9 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) { ScreenPtr screen = dirty->slave_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty); drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; - drmVBlank vbl; if (!xf86_crtc || !xf86_crtc->enabled) return; @@ -748,13 +746,10 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) return; } - vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; - vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc); - vbl.request.sequence = 1; - vbl.request.signal = drm_queue_seq; - if (drmWaitVBlank(pRADEONEnt->fd, &vbl)) { + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + 1, drm_queue_seq, NULL, NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmWaitVBlank failed for PRIME update: %s\n", + "drmmode_wait_vblank failed for PRIME update: %s\n", strerror(errno)); radeon_drm_abort_entry(drm_queue_seq); return; @@ -1019,10 +1014,8 @@ static void radeon_scanout_update(xf86CrtcPtr xf86_crtc) { drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(xf86_crtc->scrn); uintptr_t drm_queue_seq; ScrnInfoPtr scrn; - drmVBlank vbl; DamagePtr pDamage; RegionPtr pRegion; BoxRec extents; @@ -1059,13 +1052,10 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc) return; } - vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; - vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc); - vbl.request.sequence = 1; - vbl.request.signal = drm_queue_seq; - if (drmWaitVBlank(pRADEONEnt->fd, &vbl)) { + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + 1, drm_queue_seq, NULL, NULL)) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmWaitVBlank failed for scanout update: %s\n", + "drmmode_wait_vblank failed for scanout update: %s\n", strerror(errno)); radeon_drm_abort_entry(drm_queue_seq); return; diff --git a/src/radeon_present.c b/src/radeon_present.c index c01ba95f..135a0a97 100644 --- a/src/radeon_present.c +++ b/src/radeon_present.c @@ -55,16 +55,6 @@ struct radeon_present_vblank_event { Bool unflip; }; -static uint32_t crtc_select(int crtc_id) -{ - if (crtc_id > 1) - return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT; - else if (crtc_id > 0) - return DRM_VBLANK_SECONDARY; - else - return 0; -} - static RRCrtcPtr radeon_present_get_crtc(WindowPtr window) { @@ -155,13 +145,8 @@ radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) { xf86CrtcPtr xf86_crtc = crtc->devPrivate; ScreenPtr screen = crtc->pScreen; - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); - int crtc_id = drmmode_get_crtc_id(xf86_crtc); struct radeon_present_vblank_event *event; uintptr_t drm_queue_seq; - drmVBlank vbl; - int ret; event = calloc(sizeof(struct radeon_present_vblank_event), 1); if (!event) @@ -177,12 +162,10 @@ radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) return BadAlloc; } - vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id); - vbl.request.sequence = msc; - vbl.request.signal = drm_queue_seq; for (;;) { - ret = drmWaitVBlank(pRADEONEnt->fd, &vbl); - if (!ret) + if (drmmode_wait_vblank(xf86_crtc, + DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, msc, + drm_queue_seq, NULL, NULL)) break; if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) { radeon_drm_abort_entry(drm_queue_seq); |