From 9567960c4b75a90ddc6db190074fcd57ec32fa93533a0dcf1e1b348b26d87899 Mon Sep 17 00:00:00 2001 From: Stefan Dirsch Date: Mon, 3 Jan 2022 21:11:20 +0000 Subject: [PATCH] - u_xfree86-activate-GPU-screens-on-autobind.patch * Part of the original patch by Dave Airlie has landed 078277e4d92f05a90c4715d61b89b9d9d38d68ea, this contains the remainder of what was in SUSE before Xorg 21.1. (github issue#1254, boo#1192751) OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xorg-x11-server?expand=0&rev=816 --- ...e86-activate-GPU-screens-on-autobind.patch | 264 ++++++++++++++++++ xorg-x11-server.changes | 9 + xorg-x11-server.spec | 3 + 3 files changed, 276 insertions(+) create mode 100644 u_xfree86-activate-GPU-screens-on-autobind.patch diff --git a/u_xfree86-activate-GPU-screens-on-autobind.patch b/u_xfree86-activate-GPU-screens-on-autobind.patch new file mode 100644 index 0000000..5962e7c --- /dev/null +++ b/u_xfree86-activate-GPU-screens-on-autobind.patch @@ -0,0 +1,264 @@ +From 358448649d39b6cf4de49c0f65ce2b5f4c702c65 Mon Sep 17 00:00:00 2001 +From: Dave Airlie +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 +--- + 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,186 @@ 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; ++ ++ 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 + diff --git a/xorg-x11-server.changes b/xorg-x11-server.changes index e4d714e..aae0fc5 100644 --- a/xorg-x11-server.changes +++ b/xorg-x11-server.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Mon Jan 3 21:03:34 UTC 2022 - Stefan Dirsch + +- u_xfree86-activate-GPU-screens-on-autobind.patch + * Part of the original patch by Dave Airlie has landed + 078277e4d92f05a90c4715d61b89b9d9d38d68ea, this contains the + remainder of what was in SUSE before Xorg 21.1. + (github issue#1254, boo#1192751) + ------------------------------------------------------------------- Mon Jan 3 18:29:59 UTC 2022 - Stefan Dirsch diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 3098118..0849e10 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -240,6 +240,8 @@ Patch1910: u_modesetting-Fix-dirty-updates-for-sw-rotation.patch Patch1920: u_xf86-Accept-devices-with-the-hyperv_drm-driver.patch +Patch1930: u_xfree86-activate-GPU-screens-on-autobind.patch + %description This package contains the X.Org Server. @@ -393,6 +395,7 @@ sh %{SOURCE92} --verify . %{SOURCE91} %patch1900 -p1 %patch1910 -p1 %patch1920 -p1 +%patch1930 -p1 %build %global _lto_cflags %{?_lto_cflags} -ffat-lto-objects