[PATCH 10/11] DRI2: make wait_msc and get_msc work on disabled CRTCs

Ilija Hadzic ilijahadzic at gmail.com
Sun Apr 28 13:07:55 PDT 2013


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.

Signed-off-by: Ilija Hadzic <ihadzic at research.bell-labs.com>
---
 src/radeon_dri2.c | 66 +++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 52 insertions(+), 14 deletions(-)

diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 02ccc55..fc8f328 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -954,7 +954,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) {
@@ -962,21 +962,45 @@ 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;
+	uint64_t 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_nvp;
+	*ust = drmmode_crtc->dpms_last_ust;
+	*ust += delta_seq * drmmode_crtc->dpms_last_nvp;
+	*msc = drmmode_crtc->dpms_last_seq;
+	*msc += drmmode_crtc->interpolated_vblanks;
+	*msc += delta_seq;
+	*msc &= 0xffffffff;
+    }
     return TRUE;
 }
 
@@ -1039,7 +1063,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;
@@ -1071,6 +1095,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);
-- 
1.8.1.5



More information about the xorg-driver-ati mailing list