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

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