Blame SOURCES/0001-autobind-GPUs-to-the-screen.patch

98b35a
From 471289fa1dc359555ceed6302f7d9605ab6be3ea Mon Sep 17 00:00:00 2001
98b35a
From: Dave Airlie <airlied@redhat.com>
98b35a
Date: Mon, 2 Apr 2018 16:49:02 -0400
98b35a
Subject: [PATCH] autobind GPUs to the screen
98b35a
98b35a
This is a modified version of a patch we've been carry-ing in Fedora and
98b35a
RHEL for years now. This patch automatically adds secondary GPUs to the
98b35a
master as output sink / offload source making e.g. the use of
98b35a
slave-outputs just work, with requiring the user to manually run
98b35a
"xrandr --setprovideroutputsource" before he can hookup an external
98b35a
monitor to his hybrid graphics laptop.
98b35a
98b35a
There is one problem with this patch, which is why it was not upstreamed
98b35a
before. What to do when a secondary GPU gets detected really is a policy
98b35a
decission (e.g. one may want to autobind PCI GPUs but not USB ones) and
98b35a
as such should be under control of the Desktop Environment.
98b35a
98b35a
Unconditionally adding autobinding support to the xserver will result
98b35a
in races between the DE dealing with the hotplug of a secondary GPU
98b35a
and the server itself dealing with it.
98b35a
98b35a
However we've waited for years for any Desktop Environments to actually
98b35a
start doing some sort of autoconfiguration of secondary GPUs and there
98b35a
is still not a single DE dealing with this, so I believe that it is
98b35a
time to upstream this now.
98b35a
98b35a
To avoid potential future problems if any DEs get support for doing
98b35a
secondary GPU configuration themselves, the new autobind functionality
98b35a
is made optional. Since no DEs currently support doing this themselves it
98b35a
is enabled by default. When DEs grow support for doing this themselves
98b35a
they can disable the servers autobinding through the servers cmdline or a
98b35a
xorg.conf snippet.
98b35a
98b35a
Signed-off-by: Dave Airlie <airlied@gmail.com>
98b35a
[hdegoede@redhat.com: Make configurable, fix with nvidia, submit upstream]
98b35a
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
98b35a
---
98b35a
 hw/xfree86/common/xf86Config.c      | 19 +++++++++++++++++++
98b35a
 hw/xfree86/common/xf86Globals.c     |  2 ++
98b35a
 hw/xfree86/common/xf86Init.c        | 20 ++++++++++++++++++++
98b35a
 hw/xfree86/common/xf86Priv.h        |  1 +
98b35a
 hw/xfree86/common/xf86Privstr.h     |  1 +
98b35a
 hw/xfree86/common/xf86platformBus.c |  4 ++++
98b35a
 hw/xfree86/man/Xorg.man             |  7 +++++++
98b35a
 hw/xfree86/man/xorg.conf.man        |  6 ++++++
98b35a
 randr/randrstr.h                    |  3 +++
98b35a
 randr/rrprovider.c                  | 22 ++++++++++++++++++++++
98b35a
 10 files changed, 85 insertions(+)
98b35a
98b35a
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
98b35a
index 2c1d335..d7d7c2e 100644
98b35a
--- a/hw/xfree86/common/xf86Config.c
98b35a
+++ b/hw/xfree86/common/xf86Config.c
98b35a
@@ -643,6 +643,7 @@ typedef enum {
98b35a
     FLAG_DRI2,
98b35a
     FLAG_USE_SIGIO,
98b35a
     FLAG_AUTO_ADD_GPU,
98b35a
+    FLAG_AUTO_BIND_GPU,
98b35a
     FLAG_MAX_CLIENTS,
98b35a
     FLAG_IGLX,
98b35a
     FLAG_DEBUG,
98b35a
@@ -699,6 +700,8 @@ static OptionInfoRec FlagOptions[] = {
98b35a
      {0}, FALSE},
98b35a
     {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
98b35a
      {0}, FALSE},
98b35a
+    {FLAG_AUTO_BIND_GPU, "AutoBindGPU", OPTV_BOOLEAN,
98b35a
+     {0}, FALSE},
98b35a
     {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER,
98b35a
      {0}, FALSE },
98b35a
     {FLAG_IGLX, "IndirectGLX", OPTV_BOOLEAN,
98b35a
@@ -779,6 +782,22 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
98b35a
     }
98b35a
     xf86Msg(from, "%sutomatically adding GPU devices\n",
98b35a
             xf86Info.autoAddGPU ? "A" : "Not a");
98b35a
+
98b35a
+    if (xf86AutoBindGPUDisabled) {
98b35a
+        xf86Info.autoBindGPU = FALSE;
98b35a
+        from = X_CMDLINE;
98b35a
+    }
98b35a
+    else if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_BIND_GPU)) {
98b35a
+        xf86GetOptValBool(FlagOptions, FLAG_AUTO_BIND_GPU,
98b35a
+                          &xf86Info.autoBindGPU);
98b35a
+        from = X_CONFIG;
98b35a
+    }
98b35a
+    else {
98b35a
+        from = X_DEFAULT;
98b35a
+    }
98b35a
+    xf86Msg(from, "%sutomatically binding GPU devices\n",
98b35a
+            xf86Info.autoBindGPU ? "A" : "Not a");
98b35a
+
98b35a
     /*
98b35a
      * Set things up based on the config file information.  Some of these
98b35a
      * settings may be overridden later when the command line options are
98b35a
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
98b35a
index e890f05..7b27b4c 100644
98b35a
--- a/hw/xfree86/common/xf86Globals.c
98b35a
+++ b/hw/xfree86/common/xf86Globals.c
98b35a
@@ -131,6 +131,7 @@ xf86InfoRec xf86Info = {
98b35a
 #else
98b35a
     .autoAddGPU = FALSE,
98b35a
 #endif
98b35a
+    .autoBindGPU = TRUE,
98b35a
 };
98b35a
 
98b35a
 const char *xf86ConfigFile = NULL;
98b35a
@@ -191,6 +192,7 @@ Bool xf86FlipPixels = FALSE;
98b35a
 Gamma xf86Gamma = { 0.0, 0.0, 0.0 };
98b35a
 
98b35a
 Bool xf86AllowMouseOpenFail = FALSE;
98b35a
+Bool xf86AutoBindGPUDisabled = FALSE;
98b35a
 
98b35a
 #ifdef XF86VIDMODE
98b35a
 Bool xf86VidModeDisabled = FALSE;
98b35a
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
98b35a
index ea42ec9..ec255b6 100644
98b35a
--- a/hw/xfree86/common/xf86Init.c
98b35a
+++ b/hw/xfree86/common/xf86Init.c
98b35a
@@ -76,6 +76,7 @@
98b35a
 #include "xf86DDC.h"
98b35a
 #include "xf86Xinput.h"
98b35a
 #include "xf86InPriv.h"
98b35a
+#include "xf86Crtc.h"
98b35a
 #include "picturestr.h"
98b35a
 #include "randrstr.h"
98b35a
 #include "glxvndabi.h"
98b35a
@@ -237,6 +238,19 @@ xf86PrivsElevated(void)
98b35a
     return PrivsElevated();
98b35a
 }
98b35a
 
98b35a
+static void
98b35a
+xf86AutoConfigOutputDevices(void)
98b35a
+{
98b35a
+    int i;
98b35a
+
98b35a
+    if (!xf86Info.autoBindGPU)
98b35a
+        return;
98b35a
+
98b35a
+    for (i = 0; i < xf86NumGPUScreens; i++)
98b35a
+        RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
98b35a
+                                      xf86ScrnToScreen(xf86Screens[0]));
98b35a
+}
98b35a
+
98b35a
 static void
98b35a
 TrapSignals(void)
98b35a
 {
98b35a
@@ -770,6 +784,8 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
98b35a
     for (i = 0; i < xf86NumGPUScreens; i++)
98b35a
         AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
98b35a
 
98b35a
+    xf86AutoConfigOutputDevices();
98b35a
+
98b35a
     xf86VGAarbiterWrapFunctions();
98b35a
     if (sigio_blocked)
98b35a
         input_unlock();
98b35a
@@ -1278,6 +1294,10 @@ ddxProcessArgument(int argc, char **argv, int i)
98b35a
         xf86Info.iglxFrom = X_CMDLINE;
98b35a
         return 0;
98b35a
     }
98b35a
+    if (!strcmp(argv[i], "-noautoBindGPU")) {
98b35a
+        xf86AutoBindGPUDisabled = TRUE;
98b35a
+        return 1;
98b35a
+    }
98b35a
 
98b35a
     /* OS-specific processing */
98b35a
     return xf86ProcessArgument(argc, argv, i);
98b35a
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
98b35a
index 4fe2b5f..6566622 100644
98b35a
--- a/hw/xfree86/common/xf86Priv.h
98b35a
+++ b/hw/xfree86/common/xf86Priv.h
98b35a
@@ -46,6 +46,7 @@
98b35a
 extern _X_EXPORT const char *xf86ConfigFile;
98b35a
 extern _X_EXPORT const char *xf86ConfigDir;
98b35a
 extern _X_EXPORT Bool xf86AllowMouseOpenFail;
98b35a
+extern _X_EXPORT Bool xf86AutoBindGPUDisabled;
98b35a
 
98b35a
 #ifdef XF86VIDMODE
98b35a
 extern _X_EXPORT Bool xf86VidModeDisabled;
98b35a
diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
98b35a
index 21c2e1f..6c71863 100644
98b35a
--- a/hw/xfree86/common/xf86Privstr.h
98b35a
+++ b/hw/xfree86/common/xf86Privstr.h
98b35a
@@ -98,6 +98,7 @@ typedef struct {
98b35a
 
98b35a
     Bool autoAddGPU;
98b35a
     const char *debug;
98b35a
+    Bool autoBindGPU;
98b35a
 } xf86InfoRec, *xf86InfoPtr;
98b35a
 
98b35a
 /* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */
98b35a
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
98b35a
index cef47da..913a324 100644
98b35a
--- a/hw/xfree86/common/xf86platformBus.c
98b35a
+++ b/hw/xfree86/common/xf86platformBus.c
98b35a
@@ -49,6 +49,7 @@
98b35a
 #include "Pci.h"
98b35a
 #include "xf86platformBus.h"
98b35a
 #include "xf86Config.h"
98b35a
+#include "xf86Crtc.h"
98b35a
 
98b35a
 #include "randrstr.h"
98b35a
 int platformSlotClaimed;
98b35a
@@ -665,6 +666,9 @@ xf86platformAddDevice(int index)
98b35a
    }
98b35a
    /* attach unbound to 0 protocol screen */
98b35a
    AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
98b35a
+   if (xf86Info.autoBindGPU)
98b35a
+       RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
98b35a
+                                     xf86ScrnToScreen(xf86Screens[0]));
98b35a
 
98b35a
    RRResourcesChanged(xf86Screens[0]->pScreen);
98b35a
    RRTellChanged(xf86Screens[0]->pScreen);
98b35a
diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man
98b35a
index 13a9dc3..745f986 100644
98b35a
--- a/hw/xfree86/man/Xorg.man
98b35a
+++ b/hw/xfree86/man/Xorg.man
98b35a
@@ -283,6 +283,13 @@ is a comma separated list of directories to search for
98b35a
 server modules.  This option is only available when the server is run
98b35a
 as root (i.e, with real-uid 0).
98b35a
 .TP 8
98b35a
+.B \-noautoBindGPU
98b35a
+Disable automatically setting secondary GPUs up as output sinks and offload
98b35a
+sources. This is equivalent to setting the
98b35a
+.B AutoBindGPU
98b35a
+xorg.conf(__filemansuffix__) file option. To
98b35a
+.B false.
98b35a
+.TP 8
98b35a
 .B \-nosilk
98b35a
 Disable Silken Mouse support.
98b35a
 .TP 8
98b35a
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
98b35a
index 9589262..8d51e06 100644
98b35a
--- a/hw/xfree86/man/xorg.conf.man
98b35a
+++ b/hw/xfree86/man/xorg.conf.man
98b35a
@@ -672,6 +672,12 @@ Enabled by default.
98b35a
 If this option is disabled, then no GPU devices will be added from the udev
98b35a
 backend. Enabled by default. (May need to be disabled to setup Xinerama).
98b35a
 .TP 7
98b35a
+.BI "Option \*qAutoBindGPU\*q  \*q" boolean \*q
98b35a
+If enabled then secondary GPUs will be automatically set up as output-sinks and
98b35a
+offload-sources. Making e.g. laptop outputs connected only to the secondary
98b35a
+GPU directly available for use without needing to run
98b35a
+"xrandr --setprovideroutputsource". Enabled by default.
98b35a
+.TP 7
98b35a
 .BI "Option \*qLog\*q \*q" string \*q
98b35a
 This option controls whether the log is flushed and/or synced to disk after
98b35a
 each message.
98b35a
diff --git a/randr/randrstr.h b/randr/randrstr.h
98b35a
index f94174b..092d726 100644
98b35a
--- a/randr/randrstr.h
98b35a
+++ b/randr/randrstr.h
98b35a
@@ -1039,6 +1039,9 @@ RRProviderLookup(XID id, RRProviderPtr *provider_p);
98b35a
 extern _X_EXPORT void
98b35a
 RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider);
98b35a
 
98b35a
+extern _X_EXPORT void
98b35a
+RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen);
98b35a
+
98b35a
 /* rrproviderproperty.c */
98b35a
 
98b35a
 extern _X_EXPORT void
98b35a
diff --git a/randr/rrprovider.c b/randr/rrprovider.c
98b35a
index e4bc2bf..e04c18f 100644
98b35a
--- a/randr/rrprovider.c
98b35a
+++ b/randr/rrprovider.c
98b35a
@@ -485,3 +485,25 @@ RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
98b35a
 
98b35a
     WriteEventsToClient(client, 1, (xEvent *) &pe);
98b35a
 }
98b35a
+
98b35a
+void
98b35a
+RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen)
98b35a
+{
98b35a
+    rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
98b35a
+    rrScrPrivPtr masterPriv = rrGetScrPriv(masterScreen);
98b35a
+    RRProviderPtr provider = pScrPriv->provider;
98b35a
+    RRProviderPtr master_provider = masterPriv->provider;
98b35a
+
98b35a
+    if (!provider || !master_provider)
98b35a
+        return;
98b35a
+
98b35a
+    if ((provider->capabilities & RR_Capability_SinkOutput) &&
98b35a
+        (master_provider->capabilities & RR_Capability_SourceOutput)) {
98b35a
+        pScrPriv->rrProviderSetOutputSource(pScreen, provider, master_provider);
98b35a
+        RRInitPrimeSyncProps(pScreen);
98b35a
+    }
98b35a
+
98b35a
+    if ((provider->capabilities & RR_Capability_SourceOffload) &&
98b35a
+        (master_provider->capabilities & RR_Capability_SinkOffload))
98b35a
+        pScrPriv->rrProviderSetOffloadSink(pScreen, provider, master_provider);
98b35a
+}
98b35a
-- 
98b35a
2.16.2
98b35a