On Fri, 18 Mar 2011, Jesse Barnes wrote:
The duplicated code in each function is begging to get pulled out into a separate function...
How about this then ?
diff --git a/src/radeon.h b/src/radeon.h index a6d20d7..1a746c7 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -931,6 +931,9 @@ typedef struct {
RADEONFBLayout CurrentLayout;
+#ifdef RADEON_DRI2 + Bool high_crtc_works; +#endif #ifdef XF86DRI Bool directRenderingEnabled; Bool directRenderingInited; diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index 66df03c..c461469 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -771,6 +771,24 @@ cleanup: free(event); }
+static drmVBlankSeqType populate_vbl_request_type(RADEONInfoPtr info, int crtc) +{ + int high_crtc = 0; + drmVBlankSeqType type = 0; + + if (crtc == 1) + type |= DRM_VBLANK_SECONDARY; + else if (crtc > 1) { + if (info->high_crtc_works) { + high_crtc = (crtc << DRM_VBLANK_HIGH_CRTC_SHIFT) & + DRM_VBLANK_HIGH_CRTC_MASK; + } else + type |= DRM_VBLANK_SECONDARY; + } + type |= high_crtc; + return type; +} + /* * Get current frame count and frame count timestamp, based on drawable's * crtc. @@ -791,8 +809,7 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) return TRUE; } vbl.request.type = DRM_VBLANK_RELATIVE; - if (crtc > 0) - vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.type |= populate_vbl_request_type(info, crtc); vbl.request.sequence = 0;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); @@ -855,8 +872,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
/* Get current count */ vbl.request.type = DRM_VBLANK_RELATIVE; - if (crtc > 0) - vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.type |= populate_vbl_request_type(info, crtc); vbl.request.sequence = 0; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { @@ -882,8 +898,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, if (current_msc >= target_msc) target_msc = current_msc; vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - if (crtc > 0) - vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.type |= populate_vbl_request_type(info, crtc); vbl.request.sequence = target_msc; vbl.request.signal = (unsigned long)wait_info; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); @@ -903,8 +918,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, * so we queue an event that will satisfy the divisor/remainder equation. */ vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; - if (crtc > 0) - vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.type |= populate_vbl_request_type(info, crtc);
vbl.request.sequence = current_msc - (current_msc % divisor) + remainder; @@ -1068,8 +1082,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
/* Get current count */ vbl.request.type = DRM_VBLANK_RELATIVE; - if (crtc > 0) - vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.type |= populate_vbl_request_type(info, crtc); vbl.request.sequence = 0; ret = drmWaitVBlank(info->dri2.drm_fd, &vbl); if (ret) { @@ -1111,8 +1124,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, */ if (flip == 0) vbl.request.type |= DRM_VBLANK_NEXTONMISS; - if (crtc > 0) - vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.type |= populate_vbl_request_type(info, crtc);
/* If target_msc already reached or passed, set it to * current_msc to ensure we return a reasonable value back @@ -1145,8 +1157,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; if (flip == 0) vbl.request.type |= DRM_VBLANK_NEXTONMISS; - if (crtc > 0) - vbl.request.type |= DRM_VBLANK_SECONDARY; + vbl.request.type |= populate_vbl_request_type(info, crtc);
vbl.request.sequence = current_msc - (current_msc % divisor) + remainder; @@ -1217,6 +1228,7 @@ radeon_dri2_screen_init(ScreenPtr pScreen) DRI2InfoRec dri2_info = { 0 }; #ifdef USE_DRI2_SCHEDULING const char *driverNames[1]; + uint64_t cap_value; #endif
if (!info->useEXA) { @@ -1248,6 +1260,7 @@ radeon_dri2_screen_init(ScreenPtr pScreen) #endif dri2_info.CopyRegion = radeon_dri2_copy_region;
+ info->high_crtc_works = FALSE; #ifdef USE_DRI2_SCHEDULING if (info->dri->pKernelDRMVersion->version_minor >= 4) { dri2_info.version = 4; @@ -1261,6 +1274,20 @@ radeon_dri2_screen_init(ScreenPtr pScreen) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for sync extension\n"); }
+ if (info->drmmode.mode_res->count_crtcs > 2) { + if (drmGetCap(info->dri2.drm_fd, DRM_CAP_HIGH_CRTC, &cap_value)) { + info->high_crtc_works = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for VBLANKs on CRTC>1\n"); + } else { + if (cap_value) { + info->high_crtc_works = TRUE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Your kernel does not handle VBLANKs on CRTC>1\n"); + info->high_crtc_works = FALSE; + } + } + } + if (pRADEONEnt->dri2_info_cnt == 0) { #if HAS_DIXREGISTERPRIVATEKEY if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey, PRIVATE_CLIENT, sizeof(DRI2ClientEventsRec))) {