diff options
author | Ilija Hadzic <ilijahadzic@gmail.com> | 2013-05-08 22:39:46 -0400 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2013-05-29 15:27:29 +0200 |
commit | e87b52e6ad41ad7a87e43b818d80e7d522d9c68d (patch) | |
tree | 5fd38e43f658678e8931bc77569855dface9f604 /src | |
parent | f1584152bbeda98cc1907359f1c7954a84c8837d (diff) |
DRI2: make wait_msc and get_msc work on disabled CRTCs
Now that the running CRTC is emulated through DPMS-off
states, wait_msc and get_msc must also work on disabled
CRTCs. When CRTC is disabled, we must extrapolate the
MSC count from present time and last MSC when CRTC was
running and also use timers facility in wait_msc.
v2: CRTC-private now stores frame rate instead of nominal
vblank period.
Signed-off-by: Ilija Hadzic <ihadzic@research.bell-labs.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/radeon_dri2.c | 68 |
1 files changed, 54 insertions, 14 deletions
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index 26201710..9a58219a 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -963,7 +963,7 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) RADEONInfoPtr info = RADEONPTR(scrn); drmVBlank vbl; int ret; - xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, FALSE); + xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); /* Drawable not displayed, make up a value */ if (crtc == NULL) { @@ -971,21 +971,47 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) *msc = 0; return TRUE; } - vbl.request.type = DRM_VBLANK_RELATIVE; - vbl.request.type |= radeon_populate_vbl_request_type(crtc); - vbl.request.sequence = 0; + if (radeon_crtc_is_enabled(crtc)) { + /* CRTC is running, read vblank counter and timestamp */ + vbl.request.type = DRM_VBLANK_RELATIVE; + vbl.request.type |= radeon_populate_vbl_request_type(crtc); + vbl.request.sequence = 0; - ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); - if (ret) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "get vblank counter failed: %s\n", strerror(errno)); - return FALSE; - } + ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "get vblank counter failed: %s\n", strerror(errno)); + return FALSE; + } - *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; - *msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc); - *msc &= 0xffffffff; + *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; + *msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc); + *msc &= 0xffffffff; + } else { + /* CRTC is not running, extrapolate MSC and timestamp */ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + CARD64 now, delta_t, delta_seq; + if (!drmmode_crtc->dpms_last_ust) + return FALSE; + ret = drmmode_get_current_ust(info->dri2.drm_fd, &now); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "%s cannot get current time\n", __func__); + return FALSE; + } + delta_t = now - drmmode_crtc->dpms_last_ust; + delta_seq = delta_t * drmmode_crtc->dpms_last_fps; + delta_seq /= 1000000; + *ust = drmmode_crtc->dpms_last_ust; + delta_t = delta_seq * 1000000; + delta_t /= drmmode_crtc->dpms_last_fps; + *ust += delta_t; + *msc = drmmode_crtc->dpms_last_seq; + *msc += drmmode_crtc->interpolated_vblanks; + *msc += delta_seq; + *msc &= 0xffffffff; + } return TRUE; } @@ -1064,7 +1090,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, ScrnInfoPtr scrn = xf86ScreenToScrn(screen); RADEONInfoPtr info = RADEONPTR(scrn); DRI2FrameEventPtr wait_info = NULL; - xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, FALSE); + xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); drmVBlank vbl; int ret; CARD64 current_msc; @@ -1097,6 +1123,20 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, goto out_complete; } + /* + * CRTC is in DPMS off state, calculate wait time from current time, + * target_msc and last vblank time/sequence when CRTC was turned off + */ + if (!radeon_crtc_is_enabled(crtc)) { + CARD32 delay; + delay = radeon_dri2_extrapolate_msc_delay(crtc, &target_msc, + divisor, remainder); + wait_info->frame = target_msc; + TimerSet(NULL, 0, delay, radeon_dri2_deferred_event, wait_info); + DRI2BlockClient(client, draw); + return TRUE; + } + /* Get current count */ vbl.request.type = DRM_VBLANK_RELATIVE; vbl.request.type |= radeon_populate_vbl_request_type(crtc); |