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

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