db3d278
From 5b6faa0534453ea362de32a5bda0c4466c8e45b9 Mon Sep 17 00:00:00 2001
97c6429
From: Dave Airlie <airlied@redhat.com>
97c6429
Date: Fri, 17 Aug 2012 09:49:24 +1000
db3d278
Subject: [PATCH xserver v2] 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>
db3d278
[hdegoede@redhat.com: Make configurable, 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
97c6429
---
db3d278
 hw/xfree86/common/xf86Config.c      | 19 +++++++++++++++++++
db3d278
 hw/xfree86/common/xf86Globals.c     |  2 ++
db3d278
 hw/xfree86/common/xf86Init.c        | 16 ++++++++++++++++
db3d278
 hw/xfree86/common/xf86Priv.h        |  1 +
db3d278
 hw/xfree86/common/xf86Privstr.h     |  1 +
db3d278
 hw/xfree86/common/xf86platformBus.c |  2 ++
db3d278
 hw/xfree86/man/Xorg.man             |  7 +++++++
db3d278
 hw/xfree86/man/xorg.conf.man        |  6 ++++++
db3d278
 hw/xfree86/modes/xf86Crtc.c         | 28 ++++++++++++++++++++++++++++
db3d278
 hw/xfree86/modes/xf86Crtc.h         |  3 +++
db3d278
 10 files changed, 85 insertions(+)
97c6429
db3d278
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
db3d278
index 560e2ea..31b34a2 100644
db3d278
--- a/hw/xfree86/common/xf86Config.c
db3d278
+++ b/hw/xfree86/common/xf86Config.c
db3d278
@@ -720,6 +720,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;
db3d278
@@ -781,6 +782,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,
db3d278
@@ -860,6 +863,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
db3d278
index 07cfabf..072c3fc 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;
db3d278
@@ -196,6 +197,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
db3d278
index a544b65..70c5b7a 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"
db3d278
@@ -298,6 +299,15 @@ xf86PrivsElevated(void)
fc48514
 }
97c6429
 
db3d278
 static void
fc48514
+xf86AutoConfigOutputDevices(void)
fc48514
+{
fc48514
+    int i;
fc48514
+
fc48514
+    for (i = 0; i < xf86NumGPUScreens; i++)
fc48514
+        xf86AutoConfigOutputDevice(xf86GPUScreens[i], xf86Screens[0]);
fc48514
+}
fc48514
+
db3d278
+static void
fc48514
 InstallSignalHandlers(void)
fc48514
 {
db3d278
     /*
db3d278
@@ -871,6 +881,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();
db3d278
@@ -1389,6 +1401,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
db3d278
index 9e327b9..a0a98aa 100644
db3d278
--- a/hw/xfree86/common/xf86Privstr.h
db3d278
+++ b/hw/xfree86/common/xf86Privstr.h
db3d278
@@ -104,6 +104,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
db3d278
index 39fb1dd..3e2264f 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;
db3d278
@@ -560,6 +561,7 @@ xf86platformAddDevice(int index)
Dave Airlie 9dc0b02
    }
fc48514
    /* attach unbound to 0 protocol screen */
fc48514
    AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
fc48514
+   xf86AutoConfigOutputDevice(xf86GPUScreens[i], 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
db3d278
index 94b199e..bdc121a 100644
db3d278
--- a/hw/xfree86/man/xorg.conf.man
db3d278
+++ b/hw/xfree86/man/xorg.conf.man
db3d278
@@ -676,6 +676,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.
fc48514
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
db3d278
index 966a168..4960678 100644
fc48514
--- a/hw/xfree86/modes/xf86Crtc.c
fc48514
+++ b/hw/xfree86/modes/xf86Crtc.c
db3d278
@@ -3462,3 +3462,31 @@ xf86DetachAllCrtc(ScrnInfoPtr scrn)
fc48514
             crtc->x = crtc->y = 0;
fc48514
         }
fc48514
 }
fc48514
+
fc48514
+void xf86AutoConfigOutputDevice(ScrnInfoPtr pScrn, ScrnInfoPtr master)
fc48514
+{
fc48514
+    RRProviderPtr master_provider;
fc48514
+    xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(master);
fc48514
+    xf86CrtcConfigPtr slave_config = XF86_CRTC_CONFIG_PTR(pScrn);
db3d278
+
db3d278
+    if (!xf86Info.autoBindGPU)
db3d278
+        return;
fc48514
+
8830e76
+    if (!config || !slave_config)
8830e76
+        return;
8830e76
+
fc48514
+    master_provider = config->randr_provider;
fc48514
+
fc48514
+    if ((master->capabilities & RR_Capability_SinkOffload) &&
db3d278
+               pScrn->capabilities & RR_Capability_SourceOffload) {
db3d278
+        /* source offload */
fc48514
+        AttachOffloadGPU(master->pScreen, pScrn->pScreen);
fc48514
+        slave_config->randr_provider->offload_sink = master_provider;
Dave Airlie 9620f4c
+    }
Dave Airlie 9620f4c
+    if ((master->capabilities & RR_Capability_SourceOutput) &&
fc48514
+               pScrn->capabilities & RR_Capability_SinkOutput) {
fc48514
+        /* sink offload */
fc48514
+        AttachOutputGPU(master->pScreen, pScrn->pScreen);
fc48514
+        slave_config->randr_provider->output_source = master_provider;
fc48514
+    }
fc48514
+}
db3d278
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
db3d278
index 14ba9d7..6cf7e89 100644
db3d278
--- a/hw/xfree86/modes/xf86Crtc.h
db3d278
+++ b/hw/xfree86/modes/xf86Crtc.h
db3d278
@@ -1051,4 +1051,7 @@ xf86ProviderSetup(ScrnInfoPtr scrn,
db3d278
 extern _X_EXPORT void
db3d278
 xf86DetachAllCrtc(ScrnInfoPtr scrn);
db3d278
 
db3d278
+extern _X_EXPORT void
db3d278
+xf86AutoConfigOutputDevice(ScrnInfoPtr pScrn, ScrnInfoPtr master);
db3d278
+
db3d278
 #endif                          /* _XF86CRTC_H_ */
Dave Airlie 9dc0b02
-- 
db3d278
2.9.3
Dave Airlie 9dc0b02