From 5b6faa0534453ea362de32a5bda0c4466c8e45b9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 17 Aug 2012 09:49:24 +1000 Subject: [PATCH xserver v2] autobind GPUs to the screen This is a modified version of a patch we've been carry-ing in Fedora and RHEL for years now. This patch automatically adds secondary GPUs to the master as output sink / offload source making e.g. the use of slave-outputs just work, with requiring the user to manually run "xrandr --setprovideroutputsource" before he can hookup an external monitor to his hybrid graphics laptop. There is one problem with this patch, which is why it was not upstreamed before. What to do when a secondary GPU gets detected really is a policy decission (e.g. one may want to autobind PCI GPUs but not USB ones) and as such should be under control of the Desktop Environment. Unconditionally adding autobinding support to the xserver will result in races between the DE dealing with the hotplug of a secondary GPU and the server itself dealing with it. However we've waited for years for any Desktop Environments to actually start doing some sort of autoconfiguration of secondary GPUs and there is still not a single DE dealing with this, so I believe that it is time to upstream this now. To avoid potential future problems if any DEs get support for doing secondary GPU configuration themselves, the new autobind functionality is made optional. Since no DEs currently support doing this themselves it is enabled by default. When DEs grow support for doing this themselves they can disable the servers autobinding through the servers cmdline or a xorg.conf snippet. Signed-off-by: Dave Airlie [hdegoede@redhat.com: Make configurable, submit upstream] Signed-off-by: Hans de Goede --- Changes in v2: -Make the default enabled instead of installing a xorg.conf snippet which enables it unconditionally --- hw/xfree86/common/xf86Config.c | 19 +++++++++++++++++++ hw/xfree86/common/xf86Globals.c | 2 ++ hw/xfree86/common/xf86Init.c | 16 ++++++++++++++++ hw/xfree86/common/xf86Priv.h | 1 + hw/xfree86/common/xf86Privstr.h | 1 + hw/xfree86/common/xf86platformBus.c | 2 ++ hw/xfree86/man/Xorg.man | 7 +++++++ hw/xfree86/man/xorg.conf.man | 6 ++++++ hw/xfree86/modes/xf86Crtc.c | 28 ++++++++++++++++++++++++++++ hw/xfree86/modes/xf86Crtc.h | 3 +++ 10 files changed, 85 insertions(+) diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 560e2ea..31b34a2 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -720,6 +720,7 @@ typedef enum { FLAG_DRI2, FLAG_USE_SIGIO, FLAG_AUTO_ADD_GPU, + FLAG_AUTO_BIND_GPU, FLAG_MAX_CLIENTS, FLAG_IGLX, } FlagValues; @@ -781,6 +782,8 @@ static OptionInfoRec FlagOptions[] = { {0}, FALSE}, {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN, {0}, FALSE}, + {FLAG_AUTO_BIND_GPU, "AutoBindGPU", OPTV_BOOLEAN, + {0}, FALSE}, {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER, {0}, FALSE }, {FLAG_IGLX, "IndirectGLX", OPTV_BOOLEAN, @@ -860,6 +863,22 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts) } xf86Msg(from, "%sutomatically adding GPU devices\n", xf86Info.autoAddGPU ? "A" : "Not a"); + + if (xf86AutoBindGPUDisabled) { + xf86Info.autoBindGPU = FALSE; + from = X_CMDLINE; + } + else if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_BIND_GPU)) { + xf86GetOptValBool(FlagOptions, FLAG_AUTO_BIND_GPU, + &xf86Info.autoBindGPU); + from = X_CONFIG; + } + else { + from = X_DEFAULT; + } + xf86Msg(from, "%sutomatically binding GPU devices\n", + xf86Info.autoBindGPU ? "A" : "Not a"); + /* * Set things up based on the config file information. Some of these * settings may be overridden later when the command line options are diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c index 07cfabf..072c3fc 100644 --- a/hw/xfree86/common/xf86Globals.c +++ b/hw/xfree86/common/xf86Globals.c @@ -136,6 +136,7 @@ xf86InfoRec xf86Info = { #else .autoAddGPU = FALSE, #endif + .autoBindGPU = TRUE, }; const char *xf86ConfigFile = NULL; @@ -196,6 +197,7 @@ Bool xf86FlipPixels = FALSE; Gamma xf86Gamma = { 0.0, 0.0, 0.0 }; Bool xf86AllowMouseOpenFail = FALSE; +Bool xf86AutoBindGPUDisabled = FALSE; #ifdef XF86VIDMODE Bool xf86VidModeDisabled = FALSE; diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c index a544b65..70c5b7a 100644 --- a/hw/xfree86/common/xf86Init.c +++ b/hw/xfree86/common/xf86Init.c @@ -76,6 +76,7 @@ #include "xf86DDC.h" #include "xf86Xinput.h" #include "xf86InPriv.h" +#include "xf86Crtc.h" #include "picturestr.h" #include "xf86Bus.h" @@ -298,6 +299,15 @@ xf86PrivsElevated(void) } static void +xf86AutoConfigOutputDevices(void) +{ + int i; + + for (i = 0; i < xf86NumGPUScreens; i++) + xf86AutoConfigOutputDevice(xf86GPUScreens[i], xf86Screens[0]); +} + +static void InstallSignalHandlers(void) { /* @@ -871,6 +881,8 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) for (i = 0; i < xf86NumGPUScreens; i++) AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen); + xf86AutoConfigOutputDevices(); + xf86VGAarbiterWrapFunctions(); if (sigio_blocked) input_unlock(); @@ -1389,6 +1401,10 @@ ddxProcessArgument(int argc, char **argv, int i) xf86Info.iglxFrom = X_CMDLINE; return 0; } + if (!strcmp(argv[i], "-noautoBindGPU")) { + xf86AutoBindGPUDisabled = TRUE; + return 1; + } /* OS-specific processing */ return xf86ProcessArgument(argc, argv, i); diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h index c1f8a18..9a3d0df 100644 --- a/hw/xfree86/common/xf86Priv.h +++ b/hw/xfree86/common/xf86Priv.h @@ -46,6 +46,7 @@ extern _X_EXPORT const char *xf86ConfigFile; extern _X_EXPORT const char *xf86ConfigDir; extern _X_EXPORT Bool xf86AllowMouseOpenFail; +extern _X_EXPORT Bool xf86AutoBindGPUDisabled; #ifdef XF86VIDMODE extern _X_EXPORT Bool xf86VidModeDisabled; diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h index 9e327b9..a0a98aa 100644 --- a/hw/xfree86/common/xf86Privstr.h +++ b/hw/xfree86/common/xf86Privstr.h @@ -104,6 +104,7 @@ typedef struct { MessageType dri2From; Bool autoAddGPU; + Bool autoBindGPU; } xf86InfoRec, *xf86InfoPtr; #ifdef DPMSExtension diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c index 39fb1dd..3e2264f 100644 --- a/hw/xfree86/common/xf86platformBus.c +++ b/hw/xfree86/common/xf86platformBus.c @@ -48,6 +48,7 @@ #include "Pci.h" #include "xf86platformBus.h" #include "xf86Config.h" +#include "xf86Crtc.h" #include "randrstr.h" int platformSlotClaimed; @@ -560,6 +561,7 @@ xf86platformAddDevice(int index) } /* attach unbound to 0 protocol screen */ AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen); + xf86AutoConfigOutputDevice(xf86GPUScreens[i], xf86Screens[0]); RRResourcesChanged(xf86Screens[0]->pScreen); RRTellChanged(xf86Screens[0]->pScreen); diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man index def9bfc..8df6b7d 100644 --- a/hw/xfree86/man/Xorg.man +++ b/hw/xfree86/man/Xorg.man @@ -283,6 +283,13 @@ is a comma separated list of directories to search for server modules. This option is only available when the server is run as root (i.e, with real-uid 0). .TP 8 +.B \-noautoBindGPU +Disable automatically setting secondary GPUs up as output sinks and offload +sources. This is equivalent to setting the +.B AutoBindGPU +xorg.conf(__filemansuffix__) file option. To +.B false. +.TP 8 .B \-nosilk Disable Silken Mouse support. .TP 8 diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man index 94b199e..bdc121a 100644 --- a/hw/xfree86/man/xorg.conf.man +++ b/hw/xfree86/man/xorg.conf.man @@ -676,6 +676,12 @@ Enabled by default. If this option is disabled, then no GPU devices will be added from the udev backend. Enabled by default. (May need to be disabled to setup Xinerama). .TP 7 +.BI "Option \*qAutoBindGPU\*q \*q" boolean \*q +If enabled then secondary GPUs will be automatically set up as output-sinks and +offload-sources. Making e.g. laptop outputs connected only to the secondary +GPU directly available for use without needing to run +"xrandr --setprovideroutputsource". Enabled by default. +.TP 7 .BI "Option \*qLog\*q \*q" string \*q This option controls whether the log is flushed and/or synced to disk after each message. diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index 966a168..4960678 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -3462,3 +3462,31 @@ xf86DetachAllCrtc(ScrnInfoPtr scrn) crtc->x = crtc->y = 0; } } + +void xf86AutoConfigOutputDevice(ScrnInfoPtr pScrn, ScrnInfoPtr master) +{ + RRProviderPtr master_provider; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(master); + xf86CrtcConfigPtr slave_config = XF86_CRTC_CONFIG_PTR(pScrn); + + if (!xf86Info.autoBindGPU) + return; + + if (!config || !slave_config) + return; + + master_provider = config->randr_provider; + + if ((master->capabilities & RR_Capability_SinkOffload) && + pScrn->capabilities & RR_Capability_SourceOffload) { + /* source offload */ + AttachOffloadGPU(master->pScreen, pScrn->pScreen); + slave_config->randr_provider->offload_sink = master_provider; + } + if ((master->capabilities & RR_Capability_SourceOutput) && + pScrn->capabilities & RR_Capability_SinkOutput) { + /* sink offload */ + AttachOutputGPU(master->pScreen, pScrn->pScreen); + slave_config->randr_provider->output_source = master_provider; + } +} diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h index 14ba9d7..6cf7e89 100644 --- a/hw/xfree86/modes/xf86Crtc.h +++ b/hw/xfree86/modes/xf86Crtc.h @@ -1051,4 +1051,7 @@ xf86ProviderSetup(ScrnInfoPtr scrn, extern _X_EXPORT void xf86DetachAllCrtc(ScrnInfoPtr scrn); +extern _X_EXPORT void +xf86AutoConfigOutputDevice(ScrnInfoPtr pScrn, ScrnInfoPtr master); + #endif /* _XF86CRTC_H_ */ -- 2.9.3