Package not found: Kernel:stable:Backport/kernel-

File u_xfree86-activate-GPU-screens-on-autobind.patch of Package xorg-x11-server

From 358448649d39b6cf4de49c0f65ce2b5f4c702c65 Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@redhat.com>
Date: Sun, 2 Jan 2022 01:27:31 +0200
Subject: [PATCH xserver] xfree86: activate GPU screens on autobind

Part of the original patch by Dave Airlie has landed
078277e4d92f05a90c4715d61b89b9d9d38d68ea, this contains the remainder of
what was in SUSE before Xorg 21.1.

Signed-off-by: Dave Airlie <airlied@gmail.com>
---
 dix/main.c                   |   4 +
 hw/xfree86/common/xf86Init.c | 185 +++++++++++++++++++++++++++++++++++
 include/dix.h                |   2 +
 3 files changed, 191 insertions(+)

diff --git a/dix/main.c b/dix/main.c
index bfc8addbe..c7b8ed49e 100644
--- a/dix/main.c
+++ b/dix/main.c
@@ -121,6 +121,8 @@ extern void Dispatch(void);
 
 CallbackListPtr RootWindowFinalizeCallback = NULL;
 
+CallbackListPtr RootWindowInitialized = NULL;
+
 int
 dix_main(int argc, char *argv[], char *envp[])
 {
@@ -242,6 +244,8 @@ dix_main(int argc, char *argv[], char *envp[])
         for (i = 0; i < screenInfo.numScreens; i++)
             InitRootWindow(screenInfo.screens[i]->root);
 
+        CallCallbacks(&RootWindowInitialized, NULL);
+
         InitCoreDevices();
         InitInput(argc, argv);
         InitAndStartDevices();
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 380288ca4..9839cb19c 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -204,6 +204,9 @@ xf86HasTTYs(void)
 #endif
 }
 
+static void
+xf86AutoConfigProviderOutputs(CallbackListPtr *pcbl, void *data, void *call_data);
+
 static void
 xf86AutoConfigOutputDevices(void)
 {
@@ -217,6 +220,8 @@ xf86AutoConfigOutputDevices(void)
         RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
                                       xf86ScrnToScreen(xf86Screens[scrnum]));
     }
+
+    AddCallback(&RootWindowInitialized, xf86AutoConfigProviderOutputs, NULL);
 }
 
 static void
@@ -258,6 +263,189 @@ AddVTAtoms(CallbackListPtr *pcbl, void *data, void *screen)
                    "Failed to register VT properties\n");
 }
 
+
+/*
+ * This function activates all outputs of all GPU screens associated with the
+ * given master screen and sets them to their preferred resolution next to
+ * each other left-to-right.
+ */
+static void
+xf86AutoConfigureProviderOutputsForMaster(ScreenPtr pMasterScreen)
+{
+    ScreenPtr pScreen;
+    rrScrPrivPtr pMasterScrPriv, pScrPriv;
+    RROutputPtr pOutput;
+    RRCrtcPtr pCrtc;
+    RRCrtcPtr *pUsedCrtcs;
+    int usedCrtcsCount;
+    int screenWidth, screenHeight, screenWidthMM, screenHeightMM;
+    int i, j, k, l;
+
+    struct OutputConfig {
+        RROutputPtr pOutput;
+        RRCrtcPtr pCrtc;
+
+        int x;
+        int y;
+    } *outputConfigs;
+    int outputConfigsCount = 0, outputConfigsUsed = 0;
+
+    if (!dixPrivateKeyRegistered(rrPrivKey))
+        return;
+
+    pMasterScrPriv = rrGetScrPriv(pMasterScreen);
+    if (!pMasterScrPriv)
+        return;
+
+    // Count the potential maximum of outputs that we will try to auto configure
+    for (i = 0; i < xf86NumGPUScreens; i++) {
+        pScreen = xf86GPUScreens[i]->pScreen;
+        if (pScreen->current_primary != pMasterScreen || !pScreen->is_output_secondary)
+            continue;
+
+        pScrPriv = rrGetScrPriv(pScreen);
+        if (!pScrPriv)
+            continue;
+
+        outputConfigsCount += pScrPriv->numOutputs;
+    }
+
+    if (outputConfigsCount == 0)
+        return;
+
+    outputConfigs = calloc(outputConfigsCount, sizeof(*outputConfigs));
+
+    screenWidth = 0;
+    screenHeight = 0;
+
+    // Consider the master's own outputs/crtcs that were already configured
+    for (i = 0; i < pMasterScrPriv->numCrtcs; i++) {
+        if (!pMasterScrPriv->crtcs[i]->mode)
+            continue;
+
+        screenWidth = max(screenWidth, pMasterScrPriv->crtcs[i]->x + pMasterScrPriv->crtcs[i]->mode->mode.width);
+        screenHeight = max(screenHeight, pMasterScrPriv->crtcs[i]->y + pMasterScrPriv->crtcs[i]->mode->mode.height);
+    }
+
+    // Now add as many outputs from slave GPUs as we can next to it
+    for (i = 0; i < xf86NumGPUScreens; i++) {
+        pScreen = xf86GPUScreens[i]->pScreen;
+        if (pScreen->current_primary != pMasterScreen || !pScreen->is_output_secondary)
+            continue;
+
+        pScrPriv = rrGetScrPriv(pScreen);
+        if (!pScrPriv)
+            continue;
+
+        pUsedCrtcs = calloc(pScrPriv->numCrtcs, sizeof(*pUsedCrtcs));
+        if (!pUsedCrtcs)
+            continue;
+
+        usedCrtcsCount = 0;
+
+        for (j = 0; j < pScrPriv->numOutputs; j++) {
+            pOutput = pScrPriv->outputs[j];
+
+            if (pOutput->connection != RR_Connected ||
+                pOutput->nonDesktop ||
+                pOutput->numModes == 0 ||
+                pOutput->numCrtcs == 0)
+                continue;
+
+            if (screenWidth + pOutput->modes[0]->mode.width > pMasterScrPriv->maxWidth ||
+                screenHeight + pOutput->modes[0]->mode.height > pMasterScrPriv->maxHeight)
+            {
+                // It can't fit into the maximal size, skip
+                continue;
+            }
+
+            for (k = 0; k < pOutput->numCrtcs; k++) {
+                pCrtc = pOutput->crtcs[k];
+                for (l = 0; l < usedCrtcsCount; l++) {
+                    if (pCrtc == pUsedCrtcs[l]) {
+                        pCrtc = NULL;
+                        break;
+                    }
+                }
+                if (pCrtc) {
+                    break;
+                }
+            }
+
+            if (!pCrtc) {
+                // No more free CRTCs to setup this output, skip
+                continue;
+            }
+
+            pUsedCrtcs[usedCrtcsCount] = pCrtc;
+            usedCrtcsCount++;
+
+            assert(outputConfigsUsed < outputConfigsCount);
+            outputConfigs[outputConfigsUsed].pOutput = pOutput;
+            outputConfigs[outputConfigsUsed].pCrtc = pCrtc;
+            outputConfigs[outputConfigsUsed].x = screenWidth;
+            outputConfigs[outputConfigsUsed].y = 0;
+            outputConfigsUsed++;
+
+            screenWidth += pOutput->modes[0]->mode.width;
+            screenHeight += pOutput->modes[0]->mode.height;
+        }
+
+        free(pUsedCrtcs);
+    }
+
+    if (outputConfigsUsed == 0)
+      goto out;
+
+    if (screenWidth < pMasterScrPriv->minWidth)
+        screenWidth = pMasterScrPriv->minWidth;
+    if (screenHeight < pMasterScrPriv->minHeight)
+        screenHeight = pMasterScrPriv->minHeight;
+
+    if (pMasterScrPriv->mmWidth > 0 &&
+        pMasterScrPriv->mmHeight > 0 &&
+        pMasterScrPriv->width > 0 &&
+        pMasterScrPriv->height > 0)
+    {
+      // If the master screen already has some DPI, keep it
+      screenWidthMM = pMasterScrPriv->mmWidth * screenWidth / pMasterScreen->width;
+      screenHeightMM = pMasterScrPriv->mmHeight * screenHeight / pMasterScreen->height;
+    } else {
+      assert(outputConfigsUsed > 0);
+      // Otherwise use DPI of the first output
+      screenWidthMM = outputConfigs[0].pOutput->mmWidth * screenWidth / outputConfigs[0].pOutput->modes[0]->mode.width;
+      screenHeightMM = outputConfigs[0].pOutput->mmHeight * screenHeight / outputConfigs[0].pOutput->modes[0]->mode.height;
+    }
+
+    if (!RRScreenSizeSet(pMasterScreen, screenWidth, screenHeight, screenWidthMM, screenHeightMM))
+        goto out;
+
+    for (i = 0; i < outputConfigsUsed; i++) {
+        RRCrtcSet(
+            outputConfigs[i].pCrtc,
+            outputConfigs[i].pOutput->modes[0],
+            outputConfigs[i].x,
+            outputConfigs[i].y,
+            RR_Rotate_0,
+            1,
+            &outputConfigs[i].pOutput
+        );
+    }
+
+out:
+    free(outputConfigs);
+}
+
+static void
+xf86AutoConfigProviderOutputs(CallbackListPtr *pcbl, void *data, void *call_data)
+{
+    int i;
+
+    for (i = 0; i < xf86NumScreens; i++) {
+        xf86AutoConfigureProviderOutputsForMaster(xf86Screens[i]->pScreen);
+    }
+}
+
 static Bool
 xf86ScreenInit(ScreenPtr pScreen, int argc, char **argv)
 {
diff --git a/include/dix.h b/include/dix.h
index 0dcd09b65..ecc73d1d9 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -620,6 +620,8 @@ typedef struct {
 
 extern _X_EXPORT CallbackListPtr RootWindowFinalizeCallback;
 
+extern _X_EXPORT CallbackListPtr RootWindowInitialized;
+
 extern int
 XItoCoreType(int xi_type);
 extern Bool
-- 
2.25.1

openSUSE Build Service is sponsored by