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
346 lines
11 KiB
Diff
346 lines
11 KiB
Diff
From 3216e0c618cc330f053ed36a749c8d8cfeb87a2f Mon Sep 17 00:00:00 2001
|
|
From: Dave Airlie <airlied@redhat.com>
|
|
Date: Fri, 17 Aug 2012 09:49:24 +1000
|
|
Subject: [PATCH] autobind GPUs to the screen, (v5)
|
|
|
|
this is racy and really not what we want for hotplug going forward,
|
|
but until DE support is in GNOME its probably for the best.
|
|
|
|
v2: fix if config or slave config is NULL
|
|
v3: fix multi useful slaves
|
|
|
|
v4: do not unbound GPUs before attaching them
|
|
compatibility fix for 5c7af02b10
|
|
-- Michal Srb <msrb@suse.com>
|
|
|
|
v5: Do not use xf86CrtcConfig, it is not filled by nvidia proprietary driver,
|
|
only use randr structures.
|
|
Auto configure outputs of additional GPUs on start, just like the outputs
|
|
of the main GPU are configured.
|
|
-- Michal Srb <msrb@suse.com>
|
|
|
|
DO NOT UPSTREAM.
|
|
|
|
Signed-off-by: Dave Airlie <airlied@gmail.com>
|
|
---
|
|
hw/xfree86/common/xf86Init.c | 12 ++++++++++++
|
|
hw/xfree86/common/xf86platformBus.c | 3 +++
|
|
hw/xfree86/modes/xf86Crtc.c | 32 ++++++++++++++++++++++++++++++++
|
|
3 files changed, 47 insertions(+)
|
|
|
|
Index: xorg-server-1.20.5/dix/main.c
|
|
===================================================================
|
|
--- xorg-server-1.20.5.orig/dix/main.c
|
|
+++ xorg-server-1.20.5/dix/main.c
|
|
@@ -122,6 +122,8 @@ extern void Dispatch(void);
|
|
|
|
CallbackListPtr RootWindowFinalizeCallback = NULL;
|
|
|
|
+CallbackListPtr RootWindowInitialized = NULL;
|
|
+
|
|
int
|
|
dix_main(int argc, char *argv[], char *envp[])
|
|
{
|
|
@@ -246,6 +248,8 @@ dix_main(int argc, char *argv[], char *e
|
|
for (i = 0; i < screenInfo.numScreens; i++)
|
|
InitRootWindow(screenInfo.screens[i]->root);
|
|
|
|
+ CallCallbacks(&RootWindowInitialized, NULL);
|
|
+
|
|
InitCoreDevices();
|
|
InitInput(argc, argv);
|
|
InitAndStartDevices();
|
|
Index: xorg-server-1.20.5/hw/xfree86/common/xf86Init.c
|
|
===================================================================
|
|
--- xorg-server-1.20.5.orig/hw/xfree86/common/xf86Init.c
|
|
+++ xorg-server-1.20.5/hw/xfree86/common/xf86Init.c
|
|
@@ -76,6 +76,7 @@
|
|
#include "xf86DDC.h"
|
|
#include "xf86Xinput.h"
|
|
#include "xf86InPriv.h"
|
|
+#include "xf86Crtc.h"
|
|
#include "picturestr.h"
|
|
#include "randrstr.h"
|
|
#include "glxvndabi.h"
|
|
@@ -294,6 +295,237 @@ AddVTAtoms(CallbackListPtr *pcbl, void *
|
|
"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_master != pMasterScreen || !pScreen->is_output_slave)
|
|
+ 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_master != pMasterScreen || !pScreen->is_output_slave)
|
|
+ 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);
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+xf86AutoConfigOutputDevice(ScreenPtr slave, ScreenPtr master)
|
|
+{
|
|
+ RRProviderPtr master_provider;
|
|
+ RRProviderPtr slave_provider;
|
|
+ rrScrPrivPtr master_rp;
|
|
+ rrScrPrivPtr slave_rp;
|
|
+
|
|
+ if (!dixPrivateKeyRegistered(rrPrivKey))
|
|
+ return;
|
|
+
|
|
+ master_rp = rrGetScrPriv(master);
|
|
+ slave_rp = rrGetScrPriv(slave);
|
|
+
|
|
+ if (!master_rp || !slave_rp)
|
|
+ return;
|
|
+
|
|
+ master_provider = master_rp->provider;
|
|
+ slave_provider = slave_rp->provider;
|
|
+
|
|
+ if (!master_provider || !slave_provider)
|
|
+ return;
|
|
+
|
|
+ if ((master_provider->capabilities & RR_Capability_SinkOffload) &&
|
|
+ (slave_provider->capabilities & RR_Capability_SourceOffload)) {
|
|
+ /* source offload */
|
|
+ AttachOffloadGPU(master, slave);
|
|
+ slave_provider->offload_sink = master_provider;
|
|
+ }
|
|
+ if ((master_provider->capabilities & RR_Capability_SourceOutput) &&
|
|
+ (slave_provider->capabilities & RR_Capability_SinkOutput)) {
|
|
+ /* sink offload */
|
|
+ AttachOutputGPU(master, slave);
|
|
+ slave_provider->output_source = master_provider;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+xf86AutoConfigOutputDevices(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < xf86NumGPUScreens; i++) {
|
|
+ xf86AutoConfigOutputDevice(xf86GPUScreens[i]->pScreen, xf86Screens[0]->pScreen);
|
|
+ }
|
|
+
|
|
+ AddCallback(&RootWindowInitialized, xf86AutoConfigProviderOutputs, NULL);
|
|
+}
|
|
+
|
|
static Bool
|
|
xf86ScreenInit(ScreenPtr pScreen, int argc, char **argv)
|
|
{
|
|
@@ -770,6 +996,8 @@ InitOutput(ScreenInfo * pScreenInfo, int
|
|
for (i = 0; i < xf86NumGPUScreens; i++)
|
|
AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
|
|
|
|
+ xf86AutoConfigOutputDevices();
|
|
+
|
|
xf86VGAarbiterWrapFunctions();
|
|
if (sigio_blocked)
|
|
input_unlock();
|
|
Index: xorg-server-1.20.5/hw/xfree86/common/xf86platformBus.c
|
|
===================================================================
|
|
--- xorg-server-1.20.5.orig/hw/xfree86/common/xf86platformBus.c
|
|
+++ xorg-server-1.20.5/hw/xfree86/common/xf86platformBus.c
|
|
@@ -594,6 +594,8 @@ xf86platformAddGPUDevices(DriverPtr drvp
|
|
return foundScreen;
|
|
}
|
|
|
|
+extern void xf86AutoConfigOutputDevice(ScreenPtr slave, ScreenPtr master);
|
|
+
|
|
int
|
|
xf86platformAddDevice(int index)
|
|
{
|
|
@@ -665,6 +667,7 @@ xf86platformAddDevice(int index)
|
|
}
|
|
/* attach unbound to 0 protocol screen */
|
|
AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
|
|
+ xf86AutoConfigOutputDevice(xf86GPUScreens[i]->pScreen, xf86Screens[0]->pScreen);
|
|
|
|
RRResourcesChanged(xf86Screens[0]->pScreen);
|
|
RRTellChanged(xf86Screens[0]->pScreen);
|
|
Index: xorg-server-1.20.5/include/dix.h
|
|
===================================================================
|
|
--- xorg-server-1.20.5.orig/include/dix.h
|
|
+++ xorg-server-1.20.5/include/dix.h
|
|
@@ -599,6 +599,8 @@ typedef struct {
|
|
|
|
extern _X_EXPORT CallbackListPtr RootWindowFinalizeCallback;
|
|
|
|
+extern _X_EXPORT CallbackListPtr RootWindowInitialized;
|
|
+
|
|
extern int
|
|
XItoCoreType(int xi_type);
|
|
extern Bool
|