diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2017-08-18 15:12:35 +0900 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2017-08-22 18:32:34 +0900 |
commit | fd5b78b7edff2021111bca37642b8b508f0c3328 (patch) | |
tree | b9763edf0538c30775849936aa3a6809fefd49eb | |
parent | 24b2718992e4bbc859c07e5b29b571f53314045d (diff) |
Create drmmode_wait_vblank helper
Allows cleaning up the code considerably.
(Ported from radeon commit 99f1d7a474af3683fe1a66f50c0bb8935478ff0a)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | src/amdgpu_dri2.c | 97 | ||||
-rw-r--r-- | src/amdgpu_drv.h | 2 | ||||
-rw-r--r-- | src/amdgpu_kms.c | 23 | ||||
-rw-r--r-- | src/amdgpu_present.c | 23 | ||||
-rw-r--r-- | src/drmmode_display.c | 63 | ||||
-rw-r--r-- | src/drmmode_display.h | 5 |
6 files changed, 85 insertions, 128 deletions
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c index 52fac03..bf85dfa 100644 --- a/src/amdgpu_dri2.c +++ b/src/amdgpu_dri2.c @@ -778,20 +778,6 @@ cleanup: amdgpu_dri2_frame_event_abort(crtc, event_data); } -drmVBlankSeqType amdgpu_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) - type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) & - DRM_VBLANK_HIGH_CRTC_MASK; - - 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 @@ -971,13 +957,11 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, { ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); DRI2FrameEventPtr wait_info = NULL; uintptr_t drm_queue_seq = 0; xf86CrtcPtr crtc = amdgpu_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 @@ -1016,17 +1000,13 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, } /* Get current count */ - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; - ret = drmWaitVBlank(pAMDGPUEnt->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 = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT, @@ -1053,12 +1033,9 @@ static int amdgpu_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 |= amdgpu_populate_vbl_request_type(crtc); - vbl.request.sequence = target_msc - msc_delta; - vbl.request.signal = drm_queue_seq; - ret = drmWaitVBlank(pAMDGPUEnt->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)); @@ -1073,11 +1050,7 @@ static int amdgpu_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 |= amdgpu_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, @@ -1086,11 +1059,10 @@ static int amdgpu_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(pAMDGPUEnt->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; @@ -1134,14 +1106,14 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, { ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); xf86CrtcPtr crtc = amdgpu_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; @@ -1204,18 +1176,14 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, } /* Get current count */ - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; - ret = drmWaitVBlank(pAMDGPUEnt->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 */ @@ -1237,14 +1205,13 @@ static int amdgpu_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 |= amdgpu_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 @@ -1253,17 +1220,15 @@ static int amdgpu_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(pAMDGPUEnt->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; *target_msc &= 0xffffffff; swap_info->frame = *target_msc; @@ -1275,13 +1240,11 @@ static int amdgpu_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 |= amdgpu_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 @@ -1294,15 +1257,13 @@ static int amdgpu_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(pAMDGPUEnt->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)); @@ -1310,7 +1271,7 @@ static int amdgpu_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/amdgpu_drv.h b/src/amdgpu_drv.h index 9e088e7..da71ce8 100644 --- a/src/amdgpu_drv.h +++ b/src/amdgpu_drv.h @@ -363,6 +363,4 @@ extern xf86CrtcPtr amdgpu_pick_best_crtc(ScrnInfoPtr pScrn, extern AMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn); -drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc); - #endif /* _AMDGPU_DRV_H_ */ diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c index 20a552b..3e21125 100644 --- a/src/amdgpu_kms.c +++ b/src/amdgpu_kms.c @@ -624,11 +624,9 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty) { ScreenPtr screen = dirty->slave_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); xf86CrtcPtr xf86_crtc = amdgpu_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; @@ -650,13 +648,10 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty) return; } - vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; - vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc); - vbl.request.sequence = 1; - vbl.request.signal = drm_queue_seq; - if (drmWaitVBlank(pAMDGPUEnt->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)); amdgpu_drm_abort_entry(drm_queue_seq); return; @@ -915,8 +910,6 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc) drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; uintptr_t drm_queue_seq; ScrnInfoPtr scrn; - AMDGPUEntPtr pAMDGPUEnt; - drmVBlank vbl; DamagePtr pDamage; RegionPtr pRegion; BoxRec extents; @@ -953,14 +946,10 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc) return; } - pAMDGPUEnt = AMDGPUEntPriv(scrn); - vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; - vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc); - vbl.request.sequence = 1; - vbl.request.signal = drm_queue_seq; - if (drmWaitVBlank(pAMDGPUEnt->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)); amdgpu_drm_abort_entry(drm_queue_seq); return; diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c index 7769e1f..b6792f3 100644 --- a/src/amdgpu_present.c +++ b/src/amdgpu_present.c @@ -55,16 +55,6 @@ struct amdgpu_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 amdgpu_present_get_crtc(WindowPtr window) { @@ -155,13 +145,8 @@ amdgpu_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); - AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); - int crtc_id = drmmode_get_crtc_id(xf86_crtc); struct amdgpu_present_vblank_event *event; uintptr_t drm_queue_seq; - drmVBlank vbl; - int ret; event = calloc(sizeof(struct amdgpu_present_vblank_event), 1); if (!event) @@ -177,12 +162,10 @@ amdgpu_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(pAMDGPUEnt->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 || !amdgpu_present_flush_drm_events(screen)) { amdgpu_drm_abort_entry(drm_queue_seq); diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 93f6d27..1a805b8 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -190,6 +190,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; + AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(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(pAMDGPUEnt->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 @@ -219,23 +254,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; - AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); - drmVBlank vbl; - int ret; - - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= amdgpu_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; + uint32_t seq; - ret = drmWaitVBlank(pAMDGPUEnt->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; } @@ -252,7 +279,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) @@ -262,20 +289,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 |= amdgpu_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; - ret = drmWaitVBlank(pAMDGPUEnt->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 bece0ce..ba7ec68 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -216,4 +216,9 @@ Bool amdgpu_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 |