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

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