diff options
-rw-r--r-- | src/drmmode_display.c | 56 | ||||
-rw-r--r-- | src/drmmode_display.h | 4 |
2 files changed, 60 insertions, 0 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 658747c6..cd276f35 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -49,6 +49,8 @@ #include <X11/extensions/dpms.h> #endif +#define DEFAULT_NOMINAL_FRAME_RATE 60 + static Bool RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name) { @@ -245,7 +247,61 @@ static void drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + ScrnInfoPtr scrn = crtc->scrn; + RADEONInfoPtr info = RADEONPTR(scrn); + CARD64 ust; + int ret; + + if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) { + drmVBlank vbl; + + /* + * 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(info->dri2.drm_fd, &vbl); + if (ret) + 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; + nominal_frame_rate *= 1000; + pix_in_frame = crtc->mode.HTotal * crtc->mode.VTotal; + if (nominal_frame_rate == 0 || pix_in_frame == 0) + nominal_frame_rate = DEFAULT_NOMINAL_FRAME_RATE; + else + nominal_frame_rate /= pix_in_frame; + drmmode_crtc->dpms_last_fps = nominal_frame_rate; + } + } else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) { + /* + * Off->On transition: calculate and accumulate the + * number of interpolated vblanks while we were in Off state + */ + ret = drmmode_get_current_ust(info->dri2.drm_fd, &ust); + if (ret) + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "%s cannot get current time\n", __func__); + else if (drmmode_crtc->dpms_last_ust) { + CARD64 time_elapsed, delta_seq; + time_elapsed = ust - drmmode_crtc->dpms_last_ust; + delta_seq = time_elapsed * drmmode_crtc->dpms_last_fps; + delta_seq /= 1000000; + drmmode_crtc->interpolated_vblanks += delta_seq; + } + } drmmode_crtc->dpms_mode = mode; } diff --git a/src/drmmode_display.h b/src/drmmode_display.h index add2ee48..2fccfda7 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -76,6 +76,10 @@ typedef struct { struct radeon_bo *rotate_bo; unsigned rotate_fb_id; int dpms_mode; + CARD64 dpms_last_ust; + uint32_t dpms_last_seq; + int dpms_last_fps; + uint32_t interpolated_vblanks; uint16_t lut_r[256], lut_g[256], lut_b[256]; } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; |