From 80ae2291d082b57c70d27a80182f00d760fb3d3a Mon Sep 17 00:00:00 2001 From: Ilija Hadzic Date: Wed, 8 May 2013 22:39:41 -0400 Subject: DRI2: adjust MSC by the number of interpolated vblanks Normally, MSC value equals the vblank count of the CRTC on which the drawable resides. However, we are now interpolating vblanks through DPMS-off state, so if the CRTC is turned off at some point, the vlbank count does not change, but MSC does change by the amount that equals the cumulative number of interpolated vblanks. So each time we interact with the CRTC's vblank facility, we have to adjust the vblank counter: in the request, we have to subtract the number of interpolated vblanks from MSC and in the reply we have to add the number of interpolated vblanks to the MSC. This patch only makes the MSC correct when CRTC is on. The subsequent patch will construct the MSC when CRTC is not running. Signed-off-by: Ilija Hadzic Reviewed-by: Alex Deucher --- src/radeon_dri2.c | 17 ++++++++++++++--- src/radeon_video.c | 6 ++++++ src/radeon_video.h | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index 10ea0f7e..cd2be2bd 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -905,7 +905,8 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) } *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec; - *msc = vbl.reply.sequence; + *msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc); + *msc &= 0xffffffff; return TRUE; } @@ -967,7 +968,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, goto out_complete; } - current_msc = vbl.reply.sequence; + current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc); + current_msc &= 0xffffffff; /* * If divisor is zero, or current_msc is smaller than target_msc, @@ -986,6 +988,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; vbl.request.type |= radeon_populate_vbl_request_type(crtc); vbl.request.sequence = target_msc; + vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc); vbl.request.signal = (unsigned long)wait_info; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { @@ -995,6 +998,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, } wait_info->frame = vbl.reply.sequence; + wait_info->frame += radeon_get_interpolated_vblanks(crtc); DRI2BlockClient(client, draw); return TRUE; } @@ -1017,6 +1021,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, */ if ((current_msc % divisor) >= remainder) vbl.request.sequence += divisor; + vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc); vbl.request.signal = (unsigned long)wait_info; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); @@ -1027,6 +1032,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, } wait_info->frame = vbl.reply.sequence; + wait_info->frame += radeon_get_interpolated_vblanks(crtc); DRI2BlockClient(client, draw); return TRUE; @@ -1202,7 +1208,8 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, return TRUE; } - current_msc = vbl.reply.sequence; + current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc); + current_msc &= 0xffffffff; /* Flips need to be submitted one frame before */ if (can_flip(scrn, draw, front, back)) { @@ -1242,6 +1249,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, *target_msc = current_msc; vbl.request.sequence = *target_msc; + vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc); vbl.request.signal = (unsigned long)swap_info; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { @@ -1255,6 +1263,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, } *target_msc = vbl.reply.sequence + flip; + *target_msc += radeon_get_interpolated_vblanks(crtc); swap_info->frame = *target_msc; return TRUE; @@ -1286,6 +1295,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, */ if (vbl.request.sequence <= current_msc) vbl.request.sequence += divisor; + vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc); /* Account for 1 frame extra pageflip delay if flip > 0 */ vbl.request.sequence -= flip; @@ -1304,6 +1314,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, /* Adjust returned value for 1 fame pageflip offset of flip > 0 */ *target_msc = vbl.reply.sequence + flip; + *target_msc += radeon_get_interpolated_vblanks(crtc); swap_info->frame = *target_msc; return TRUE; diff --git a/src/radeon_video.c b/src/radeon_video.c index c0505282..56cd9abd 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -73,6 +73,12 @@ Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc) return drmmode_crtc->dpms_mode == DPMSModeOn; } +uint32_t radeon_get_interpolated_vblanks(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + return drmmode_crtc->interpolated_vblanks; +} + xf86CrtcPtr radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled, int x1, int x2, int y1, int y2) diff --git a/src/radeon_video.h b/src/radeon_video.h index e6068e86..2a092954 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -101,5 +101,6 @@ RADEONCopyMungedData(ScrnInfoPtr pScrn, unsigned int dstPitch, unsigned int h, unsigned int w); Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc); +uint32_t radeon_get_interpolated_vblanks(xf86CrtcPtr crtc); #endif -- cgit v1.2.3