6c7b302
From 4471df41ea6e94834a2b10643ca7fcd69682d276 Mon Sep 17 00:00:00 2001
97c6429
From: Dave Airlie <airlied@redhat.com>
97c6429
Date: Fri, 17 Aug 2012 09:49:24 +1000
6c7b302
Subject: [PATCH xserver v3] autobind GPUs to the screen
97c6429
db3d278
This is a modified version of a patch we've been carry-ing in Fedora and
db3d278
RHEL for years now. This patch automatically adds secondary GPUs to the
db3d278
master as output sink / offload source making e.g. the use of
db3d278
slave-outputs just work, with requiring the user to manually run
db3d278
"xrandr --setprovideroutputsource" before he can hookup an external
db3d278
monitor to his hybrid graphics laptop.
97c6429
db3d278
There is one problem with this patch, which is why it was not upstreamed
db3d278
before. What to do when a secondary GPU gets detected really is a policy
db3d278
decission (e.g. one may want to autobind PCI GPUs but not USB ones) and
db3d278
as such should be under control of the Desktop Environment.
db3d278
db3d278
Unconditionally adding autobinding support to the xserver will result
db3d278
in races between the DE dealing with the hotplug of a secondary GPU
db3d278
and the server itself dealing with it.
db3d278
db3d278
However we've waited for years for any Desktop Environments to actually
db3d278
start doing some sort of autoconfiguration of secondary GPUs and there
db3d278
is still not a single DE dealing with this, so I believe that it is
db3d278
time to upstream this now.
db3d278
db3d278
To avoid potential future problems if any DEs get support for doing
db3d278
secondary GPU configuration themselves, the new autobind functionality
db3d278
is made optional. Since no DEs currently support doing this themselves it
db3d278
is enabled by default. When DEs grow support for doing this themselves
db3d278
they can disable the servers autobinding through the servers cmdline or a
db3d278
xorg.conf snippet.
Dave Airlie 02cbf43
Dave Airlie 02cbf43
Signed-off-by: Dave Airlie <airlied@gmail.com>
6c7b302
[hdegoede@redhat.com: Make configurable, fix with nvidia, submit upstream]
db3d278
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
db3d278
---
db3d278
Changes in v2:
db3d278
-Make the default enabled instead of installing a xorg.conf
db3d278
 snippet which enables it unconditionally
6c7b302
Changes in v3:
6c7b302
-Handle GPUScreen autoconfig in randr/rrprovider.c, looking at
6c7b302
 rrScrPriv->provider, rather then in hw/xfree86/modes/xf86Crtc.c
6c7b302
 looking at xf86CrtcConfig->provider. This fixes the autoconfig not
6c7b302
 working with the nvidia binary driver
97c6429
---
db3d278
 hw/xfree86/common/xf86Config.c      | 19 +++++++++++++++++++
db3d278
 hw/xfree86/common/xf86Globals.c     |  2 ++
6c7b302
 hw/xfree86/common/xf86Init.c        | 20 ++++++++++++++++++++
db3d278
 hw/xfree86/common/xf86Priv.h        |  1 +
db3d278
 hw/xfree86/common/xf86Privstr.h     |  1 +
6c7b302
 hw/xfree86/common/xf86platformBus.c |  4 ++++
db3d278
 hw/xfree86/man/Xorg.man             |  7 +++++++
db3d278
 hw/xfree86/man/xorg.conf.man        |  6 ++++++
6c7b302
 randr/randrstr.h                    |  3 +++
6c7b302
 randr/rrprovider.c                  | 22 ++++++++++++++++++++++
db3d278
 10 files changed, 85 insertions(+)
97c6429
db3d278
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
6c7b302
index 21daf1a..df3ca50 100644
db3d278
--- a/hw/xfree86/common/xf86Config.c
db3d278
+++ b/hw/xfree86/common/xf86Config.c
6c7b302
@@ -719,6 +719,7 @@ typedef enum {
db3d278
     FLAG_DRI2,
db3d278
     FLAG_USE_SIGIO,
db3d278
     FLAG_AUTO_ADD_GPU,
db3d278
+    FLAG_AUTO_BIND_GPU,
db3d278
     FLAG_MAX_CLIENTS,
db3d278
     FLAG_IGLX,
db3d278
 } FlagValues;
6c7b302
@@ -778,6 +779,8 @@ static OptionInfoRec FlagOptions[] = {
db3d278
      {0}, FALSE},
db3d278
     {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
db3d278
      {0}, FALSE},
db3d278
+    {FLAG_AUTO_BIND_GPU, "AutoBindGPU", OPTV_BOOLEAN,
db3d278
+     {0}, FALSE},
db3d278
     {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER,
db3d278
      {0}, FALSE },
db3d278
     {FLAG_IGLX, "IndirectGLX", OPTV_BOOLEAN,
6c7b302
@@ -857,6 +860,22 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
db3d278
     }
db3d278
     xf86Msg(from, "%sutomatically adding GPU devices\n",
db3d278
             xf86Info.autoAddGPU ? "A" : "Not a");
db3d278
+
db3d278
+    if (xf86AutoBindGPUDisabled) {
db3d278
+        xf86Info.autoBindGPU = FALSE;
db3d278
+        from = X_CMDLINE;
db3d278
+    }
db3d278
+    else if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_BIND_GPU)) {
db3d278
+        xf86GetOptValBool(FlagOptions, FLAG_AUTO_BIND_GPU,
db3d278
+                          &xf86Info.autoBindGPU);
db3d278
+        from = X_CONFIG;
db3d278
+    }
db3d278
+    else {
db3d278
+        from = X_DEFAULT;
db3d278
+    }
db3d278
+    xf86Msg(from, "%sutomatically binding GPU devices\n",
db3d278
+            xf86Info.autoBindGPU ? "A" : "Not a");
db3d278
+
db3d278
     /*
db3d278
      * Set things up based on the config file information.  Some of these
db3d278
      * settings may be overridden later when the command line options are
db3d278
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
6c7b302
index e962b75..0d1e31b 100644
db3d278
--- a/hw/xfree86/common/xf86Globals.c
db3d278
+++ b/hw/xfree86/common/xf86Globals.c
db3d278
@@ -136,6 +136,7 @@ xf86InfoRec xf86Info = {
db3d278
 #else
db3d278
     .autoAddGPU = FALSE,
db3d278
 #endif
db3d278
+    .autoBindGPU = TRUE,
db3d278
 };
db3d278
 
db3d278
 const char *xf86ConfigFile = NULL;
6c7b302
@@ -197,6 +198,7 @@ Bool xf86FlipPixels = FALSE;
db3d278
 Gamma xf86Gamma = { 0.0, 0.0, 0.0 };
db3d278
 
db3d278
 Bool xf86AllowMouseOpenFail = FALSE;
db3d278
+Bool xf86AutoBindGPUDisabled = FALSE;
db3d278
 
db3d278
 #ifdef XF86VIDMODE
db3d278
 Bool xf86VidModeDisabled = FALSE;
97c6429
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
6c7b302
index a544b65..b0cba3d 100644
97c6429
--- a/hw/xfree86/common/xf86Init.c
97c6429
+++ b/hw/xfree86/common/xf86Init.c
db3d278
@@ -76,6 +76,7 @@
db3d278
 #include "xf86DDC.h"
db3d278
 #include "xf86Xinput.h"
db3d278
 #include "xf86InPriv.h"
db3d278
+#include "xf86Crtc.h"
db3d278
 #include "picturestr.h"
db3d278
 
db3d278
 #include "xf86Bus.h"
6c7b302
@@ -298,6 +299,19 @@ xf86PrivsElevated(void)
fc48514
 }
97c6429
 
db3d278
 static void
fc48514
+xf86AutoConfigOutputDevices(void)
fc48514
+{
fc48514
+    int i;
fc48514
+
6c7b302
+    if (!xf86Info.autoBindGPU)
6c7b302
+        return;
6c7b302
+
fc48514
+    for (i = 0; i < xf86NumGPUScreens; i++)
6c7b302
+        RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
6c7b302
+                                      xf86ScrnToScreen(xf86Screens[0]));
fc48514
+}
fc48514
+
db3d278
+static void
fc48514
 InstallSignalHandlers(void)
fc48514
 {
db3d278
     /*
6c7b302
@@ -871,6 +885,8 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
fc48514
     for (i = 0; i < xf86NumGPUScreens; i++)
fc48514
         AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
97c6429
 
fc48514
+    xf86AutoConfigOutputDevices();
fc48514
+
97c6429
     xf86VGAarbiterWrapFunctions();
97c6429
     if (sigio_blocked)
db3d278
         input_unlock();
6c7b302
@@ -1389,6 +1405,10 @@ ddxProcessArgument(int argc, char **argv, int i)
db3d278
         xf86Info.iglxFrom = X_CMDLINE;
db3d278
         return 0;
db3d278
     }
db3d278
+    if (!strcmp(argv[i], "-noautoBindGPU")) {
db3d278
+        xf86AutoBindGPUDisabled = TRUE;
db3d278
+        return 1;
db3d278
+    }
db3d278
 
db3d278
     /* OS-specific processing */
db3d278
     return xf86ProcessArgument(argc, argv, i);
db3d278
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
db3d278
index c1f8a18..9a3d0df 100644
db3d278
--- a/hw/xfree86/common/xf86Priv.h
db3d278
+++ b/hw/xfree86/common/xf86Priv.h
db3d278
@@ -46,6 +46,7 @@
db3d278
 extern _X_EXPORT const char *xf86ConfigFile;
db3d278
 extern _X_EXPORT const char *xf86ConfigDir;
db3d278
 extern _X_EXPORT Bool xf86AllowMouseOpenFail;
db3d278
+extern _X_EXPORT Bool xf86AutoBindGPUDisabled;
db3d278
 
db3d278
 #ifdef XF86VIDMODE
db3d278
 extern _X_EXPORT Bool xf86VidModeDisabled;
db3d278
diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
6c7b302
index c29b3cc..4c5f54b 100644
db3d278
--- a/hw/xfree86/common/xf86Privstr.h
db3d278
+++ b/hw/xfree86/common/xf86Privstr.h
6c7b302
@@ -102,6 +102,7 @@ typedef struct {
db3d278
     MessageType dri2From;
db3d278
 
db3d278
     Bool autoAddGPU;
db3d278
+    Bool autoBindGPU;
db3d278
 } xf86InfoRec, *xf86InfoPtr;
db3d278
 
db3d278
 #ifdef DPMSExtension
97c6429
diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
6c7b302
index 063e81c..42789ca 100644
97c6429
--- a/hw/xfree86/common/xf86platformBus.c
97c6429
+++ b/hw/xfree86/common/xf86platformBus.c
db3d278
@@ -48,6 +48,7 @@
db3d278
 #include "Pci.h"
db3d278
 #include "xf86platformBus.h"
db3d278
 #include "xf86Config.h"
db3d278
+#include "xf86Crtc.h"
97c6429
 
db3d278
 #include "randrstr.h"
db3d278
 int platformSlotClaimed;
6c7b302
@@ -579,6 +580,9 @@ xf86platformAddDevice(int index)
Dave Airlie 9dc0b02
    }
fc48514
    /* attach unbound to 0 protocol screen */
fc48514
    AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
6c7b302
+   if (xf86Info.autoBindGPU)
6c7b302
+       RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
6c7b302
+                                     xf86ScrnToScreen(xf86Screens[0]));
fc48514
 
488b3f2
    RRResourcesChanged(xf86Screens[0]->pScreen);
488b3f2
    RRTellChanged(xf86Screens[0]->pScreen);
db3d278
diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man
db3d278
index def9bfc..8df6b7d 100644
db3d278
--- a/hw/xfree86/man/Xorg.man
db3d278
+++ b/hw/xfree86/man/Xorg.man
db3d278
@@ -283,6 +283,13 @@ is a comma separated list of directories to search for
db3d278
 server modules.  This option is only available when the server is run
db3d278
 as root (i.e, with real-uid 0).
db3d278
 .TP 8
db3d278
+.B \-noautoBindGPU
db3d278
+Disable automatically setting secondary GPUs up as output sinks and offload
db3d278
+sources. This is equivalent to setting the
db3d278
+.B AutoBindGPU
db3d278
+xorg.conf(__filemansuffix__) file option. To
db3d278
+.B false.
db3d278
+.TP 8
db3d278
 .B \-nosilk
db3d278
 Disable Silken Mouse support.
db3d278
 .TP 8
db3d278
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
6c7b302
index 7d0c524..3e596e4 100644
db3d278
--- a/hw/xfree86/man/xorg.conf.man
db3d278
+++ b/hw/xfree86/man/xorg.conf.man
6c7b302
@@ -673,6 +673,12 @@ Enabled by default.
db3d278
 If this option is disabled, then no GPU devices will be added from the udev
db3d278
 backend. Enabled by default. (May need to be disabled to setup Xinerama).
db3d278
 .TP 7
db3d278
+.BI "Option \*qAutoBindGPU\*q  \*q" boolean \*q
db3d278
+If enabled then secondary GPUs will be automatically set up as output-sinks and
db3d278
+offload-sources. Making e.g. laptop outputs connected only to the secondary
db3d278
+GPU directly available for use without needing to run
db3d278
+"xrandr --setprovideroutputsource". Enabled by default.
db3d278
+.TP 7
db3d278
 .BI "Option \*qLog\*q \*q" string \*q
db3d278
 This option controls whether the log is flushed and/or synced to disk after
db3d278
 each message.
6c7b302
diff --git a/randr/randrstr.h b/randr/randrstr.h
6c7b302
index 706e9a7..66999d5 100644
6c7b302
--- a/randr/randrstr.h
6c7b302
+++ b/randr/randrstr.h
6c7b302
@@ -976,6 +976,9 @@ RRProviderLookup(XID id, RRProviderPtr *provider_p);
6c7b302
 extern _X_EXPORT void
6c7b302
 RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider);
6c7b302
 
6c7b302
+extern _X_EXPORT void
6c7b302
+RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen);
6c7b302
+
6c7b302
 /* rrproviderproperty.c */
6c7b302
 
6c7b302
 extern _X_EXPORT void
6c7b302
diff --git a/randr/rrprovider.c b/randr/rrprovider.c
6c7b302
index f9df67e..abc5685 100644
6c7b302
--- a/randr/rrprovider.c
6c7b302
+++ b/randr/rrprovider.c
6c7b302
@@ -482,3 +482,25 @@ RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
6c7b302
 
6c7b302
     WriteEventsToClient(client, 1, (xEvent *) &pe);
fc48514
 }
fc48514
+
6c7b302
+void
6c7b302
+RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen)
fc48514
+{
6c7b302
+    rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
6c7b302
+    rrScrPrivPtr masterPriv = rrGetScrPriv(masterScreen);
6c7b302
+    RRProviderPtr provider = pScrPriv->provider;
6c7b302
+    RRProviderPtr master_provider = masterPriv->provider;
db3d278
+
6c7b302
+    if (!provider || !master_provider)
8830e76
+        return;
8830e76
+
6c7b302
+    if ((provider->capabilities & RR_Capability_SinkOutput) &&
6c7b302
+        (master_provider->capabilities & RR_Capability_SourceOutput)) {
6c7b302
+        pScrPriv->rrProviderSetOutputSource(pScreen, provider, master_provider);
6c7b302
+        RRInitPrimeSyncProps(pScreen);
fc48514
+    }
db3d278
+
6c7b302
+    if ((provider->capabilities & RR_Capability_SourceOffload) &&
6c7b302
+        (master_provider->capabilities & RR_Capability_SinkOffload))
6c7b302
+        pScrPriv->rrProviderSetOffloadSink(pScreen, provider, master_provider);
6c7b302
+}
Dave Airlie 9dc0b02
-- 
db3d278
2.9.3
Dave Airlie 9dc0b02