forked from pool/xorg-x11-server
Stefan Dirsch
6ff43929b0
- Added xorg-xserver-e89edec497ba.patch to fix incompatible pointer type error with GCC 14. If the request is OK, please forward it to Factory soon too so that we can switch the default compiler. Thanks! OBS-URL: https://build.opensuse.org/request/show/1189636 OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xorg-x11-server?expand=0&rev=891
268 lines
8.3 KiB
Diff
268 lines
8.3 KiB
Diff
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
|
|
|