summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlija Hadzic <ilijahadzic@gmail.com>2013-05-08 22:39:46 -0400
committerMichel Dänzer <michel@daenzer.net>2013-05-29 15:27:29 +0200
commite87b52e6ad41ad7a87e43b818d80e7d522d9c68d (patch)
tree5fd38e43f658678e8931bc77569855dface9f604
parentf1584152bbeda98cc1907359f1c7954a84c8837d (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>
-rw-r--r--src/radeon_dri2.c68
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);