Blame SOURCES/xserver-autobind-hotplug.patch

a3e08e
From 4471df41ea6e94834a2b10643ca7fcd69682d276 Mon Sep 17 00:00:00 2001
70130e
From: Dave Airlie <airlied@redhat.com>
70130e
Date: Fri, 17 Aug 2012 09:49:24 +1000
a3e08e
Subject: [PATCH xserver v3] 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
Changes in v2:
a3e08e
-Make the default enabled instead of installing a xorg.conf
a3e08e
 snippet which enables it unconditionally
a3e08e
Changes in v3:
a3e08e
-Handle GPUScreen autoconfig in randr/rrprovider.c, looking at
a3e08e
 rrScrPriv->provider, rather then in hw/xfree86/modes/xf86Crtc.c
a3e08e
 looking at xf86CrtcConfig->provider. This fixes the autoconfig not
a3e08e
 working with the nvidia binary driver
a3e08e
---
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
a3e08e
index 21daf1a..df3ca50 100644
a3e08e
--- a/hw/xfree86/common/xf86Config.c
a3e08e
+++ b/hw/xfree86/common/xf86Config.c
a3e08e
@@ -719,6 +719,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,
a3e08e
 } FlagValues;
a3e08e
@@ -778,6 +779,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,
a3e08e
@@ -857,6 +860,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
a3e08e
index e962b75..0d1e31b 100644
a3e08e
--- a/hw/xfree86/common/xf86Globals.c
a3e08e
+++ b/hw/xfree86/common/xf86Globals.c
a3e08e
@@ -136,6 +136,7 @@ xf86InfoRec xf86Info = {
a3e08e
 #else
a3e08e
     .autoAddGPU = FALSE,
a3e08e
 #endif
a3e08e
+    .autoBindGPU = TRUE,
a3e08e
 };
a3e08e
 
a3e08e
 const char *xf86ConfigFile = NULL;
a3e08e
@@ -197,6 +198,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
a3e08e
index a544b65..b0cba3d 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"
a3e08e
 
a3e08e
 #include "xf86Bus.h"
a3e08e
@@ -298,6 +299,19 @@ xf86PrivsElevated(void)
70130e
 }
70130e
 
a3e08e
 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
+
a3e08e
+static void
70130e
 InstallSignalHandlers(void)
70130e
 {
a3e08e
     /*
a3e08e
@@ -871,6 +885,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();
a3e08e
@@ -1389,6 +1405,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
a3e08e
index c1f8a18..9a3d0df 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
a3e08e
index c29b3cc..4c5f54b 100644
a3e08e
--- a/hw/xfree86/common/xf86Privstr.h
a3e08e
+++ b/hw/xfree86/common/xf86Privstr.h
a3e08e
@@ -102,6 +102,7 @@ typedef struct {
a3e08e
     MessageType dri2From;
a3e08e
 
a3e08e
     Bool autoAddGPU;
a3e08e
+    Bool autoBindGPU;
a3e08e
 } xf86InfoRec, *xf86InfoPtr;
a3e08e
 
a3e08e
 #ifdef DPMSExtension
70130e
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
a3e08e
index 063e81c..42789ca 100644
70130e
--- a/hw/xfree86/common/xf86platformBus.c
70130e
+++ b/hw/xfree86/common/xf86platformBus.c
a3e08e
@@ -48,6 +48,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;
a3e08e
@@ -579,6 +580,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
a3e08e
index def9bfc..8df6b7d 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
a3e08e
index 7d0c524..3e596e4 100644
a3e08e
--- a/hw/xfree86/man/xorg.conf.man
a3e08e
+++ b/hw/xfree86/man/xorg.conf.man
a3e08e
@@ -673,6 +673,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
a3e08e
index 706e9a7..66999d5 100644
a3e08e
--- a/randr/randrstr.h
a3e08e
+++ b/randr/randrstr.h
a3e08e
@@ -976,6 +976,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
a3e08e
index f9df67e..abc5685 100644
a3e08e
--- a/randr/rrprovider.c
a3e08e
+++ b/randr/rrprovider.c
a3e08e
@@ -482,3 +482,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
-- 
a3e08e
2.9.3
70130e