summaryrefslogtreecommitdiff
path: root/src/amdgpu_video.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/amdgpu_video.c')
-rw-r--r--src/amdgpu_video.c140
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);