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

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