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

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