diff options
Diffstat (limited to 'src/amdgpu_video.c')
-rw-r--r-- | src/amdgpu_video.c | 140 |
1 files changed, 133 insertions, 7 deletions
diff --git a/src/amdgpu_video.c b/src/amdgpu_video.c index 94ae170..b4e3fa4 100644 --- a/src/amdgpu_video.c +++ b/src/amdgpu_video.c @@ -39,10 +39,14 @@ static void amdgpu_box_intersect(BoxPtr dest, BoxPtr a, BoxPtr b) { dest->x1 = a->x1 > b->x1 ? a->x1 : b->x1; dest->x2 = a->x2 < b->x2 ? a->x2 : b->x2; + if (dest->x1 >= dest->x2) { + dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; + return; + } + dest->y1 = a->y1 > b->y1 ? a->y1 : b->y1; dest->y2 = a->y2 < b->y2 ? a->y2 : b->y2; - - if (dest->x1 >= dest->x2 || dest->y1 >= dest->y2) + if (dest->y1 >= dest->y2) dest->x1 = dest->x2 = dest->y1 = dest->y2 = 0; } @@ -64,10 +68,12 @@ static int amdgpu_box_area(BoxPtr box) return (int)(box->x2 - box->x1) * (int)(box->y2 - box->y1); } -Bool amdgpu_crtc_is_enabled(xf86CrtcPtr crtc) +Bool +amdgpu_crtc_is_enabled(xf86CrtcPtr crtc) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - return drmmode_crtc->dpms_mode == DPMSModeOn; + + return crtc->enabled && drmmode_crtc->dpms_mode == DPMSModeOn; } xf86CrtcPtr @@ -104,12 +110,12 @@ amdgpu_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled, for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; - if (!cd && !amdgpu_crtc_is_enabled(crtc)) + if (!cd && !xf86_crtc_on(crtc)) continue; amdgpu_crtc_box(crtc, &crtc_box); - amdgpu_box_intersect(&cover_box, &crtc_box, &box); - coverage = amdgpu_box_area(&cover_box); + box_intersect(&cover_box, &crtc_box, &box); + coverage = box_area(&cover_box); if (coverage > best_coverage || (coverage == best_coverage && crtc == primary_crtc)) { @@ -124,6 +130,126 @@ amdgpu_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled, return best_crtc; } +static void amdgpu_crtc_box(RRCrtcPtr crtc, BoxPtr crtc_box) +{ + if (crtc->mode) { + crtc_box->x1 = crtc->x; + crtc_box->y1 = crtc->y; + switch (crtc->rotation) { + case RR_Rotate_0: + case RR_Rotate_180: + default: + crtc_box->x2 = crtc->x + crtc->mode->mode.width; + crtc_box->y2 = crtc->y + crtc->mode->mode.height; + break; + case RR_Rotate_90: + case RR_Rotate_270: + crtc_box->x2 = crtc->x + crtc->mode->mode.height; + crtc_box->y2 = crtc->y + crtc->mode->mode.width; + break; + } + } else + crtc_box->x1 = crtc_box->x2 = crtc_box->y1 = crtc_box->y2 = 0; +} + +static Bool amdgpu_crtc_on(RRCrtcPtr crtc, Bool crtc_is_xf86_hint) +{ + if (!crtc) { + return FALSE; + } + if (crtc_is_xf86_hint && crtc->devPrivate) { + return amdgpu_crtc_is_enabled(crtc->devPrivate); + } else { + return !!crtc->mode; + } +} + +/* + * Return the crtc covering 'box'. If two crtcs cover a portion of + * 'box', then prefer the crtc with greater coverage. + */ +static RRCrtcPtr +amdgpu_crtc_covering_box(ScreenPtr pScreen, BoxPtr box, Bool screen_is_xf86_hint) +{ + rrScrPrivPtr pScrPriv; + RRCrtcPtr crtc, best_crtc; + int coverage, best_coverage; + int c; + BoxRec crtc_box, cover_box; + + best_crtc = NULL; + best_coverage = 0; + + if (!dixPrivateKeyRegistered(rrPrivKey)) + return NULL; + + pScrPriv = rrGetScrPriv(pScreen); + + if (!pScrPriv) + return NULL; + + for (c = 0; c < pScrPriv->numCrtcs; c++) { + crtc = pScrPriv->crtcs[c]; + + /* If the CRTC is off, treat it as not covering */ + if (!amdgpu_crtc_on(crtc, screen_is_xf86_hint)) + continue; + + amdgpu_crtc_box(crtc, &crtc_box); + amdgpu_box_intersect(&cover_box, &crtc_box, box); + coverage = amdgpu_box_area(&cover_box); + if (coverage > best_coverage) { + best_crtc = crtc; + best_coverage = coverage; + } + } + + return best_crtc; +} + +#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) +static RRCrtcPtr +amdgpu_crtc_covering_box_on_secondary(ScreenPtr pScreen, BoxPtr box) +{ + if (!pScreen->isGPU) { + ScreenPtr secondary; + RRCrtcPtr crtc = NULL; + + xorg_list_for_each_entry(secondary, &pScreen->secondary_list, secondary_head) { + if (!secondary->is_output_secondary) + continue; + + crtc = amdgpu_crtc_covering_box(secondary, box, FALSE); + if (crtc) + return crtc; + } + } + + return NULL; +} +#endif + +RRCrtcPtr +amdgpu_randr_crtc_covering_drawable(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + RRCrtcPtr crtc = NULL; + BoxRec box; + + box.x1 = pDraw->x; + box.y1 = pDraw->y; + box.x2 = box.x1 + pDraw->width; + box.y2 = box.y1 + pDraw->height; + + crtc = amdgpu_crtc_covering_box(pScreen, &box, TRUE); +#if ABI_VIDEODRV_VERSION >= SET_ABI_VERSION(23, 0) + if (!crtc) { + crtc = amdgpu_crtc_covering_box_on_secondary(pScreen, &box); + } +#endif + return crtc; +} + void AMDGPUInitVideo(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); |