Commit 078277e4 authored by Dave Airlie's avatar Dave Airlie Committed by Hans de Goede

xf86: 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: default avatarDave Airlie <airlied@gmail.com>
[hdegoede@redhat.com: Make configurable, fix with nvidia, submit upstream]
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Reviewed-by: Eric Anholt's avatarEric Anholt <eric@anholt.net>
Reviewed-by: default avatarEmil Velikov <emil.velikov@collabora.com>
---
Changes in v2:
-Make the default enabled instead of installing a xorg.conf
 snippet which enables it unconditionally

Changes in v3:
-Handle GPUScreen autoconfig in randr/rrprovider.c, looking at
 rrScrPriv->provider, rather then in hw/xfree86/modes/xf86Crtc.c
 looking at xf86CrtcConfig->provider. This fixes the autoconfig not
 working with the nvidia binary driver
parent fbd2bb9d
......@@ -642,6 +642,7 @@ typedef enum {
FLAG_DRI2,
FLAG_USE_SIGIO,
FLAG_AUTO_ADD_GPU,
FLAG_AUTO_BIND_GPU,
FLAG_MAX_CLIENTS,
FLAG_IGLX,
FLAG_DEBUG,
......@@ -696,6 +697,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,
......@@ -775,6 +778,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
......
......@@ -132,6 +132,7 @@ xf86InfoRec xf86Info = {
#else
.autoAddGPU = FALSE,
#endif
.autoBindGPU = TRUE,
};
const char *xf86ConfigFile = NULL;
......@@ -190,6 +191,7 @@ rgb xf86Weight = { 0, 0, 0 };
Gamma xf86Gamma = { 0.0, 0.0, 0.0 };
Bool xf86AllowMouseOpenFail = FALSE;
Bool xf86AutoBindGPUDisabled = FALSE;
#ifdef XF86VIDMODE
Bool xf86VidModeDisabled = FALSE;
......
......@@ -73,6 +73,7 @@
#include "xf86DDC.h"
#include "xf86Xinput.h"
#include "xf86InPriv.h"
#include "xf86Crtc.h"
#include "picturestr.h"
#include "randrstr.h"
#include "glxvndabi.h"
......@@ -225,6 +226,19 @@ xf86PrivsElevated(void)
return PrivsElevated();
}
static void
xf86AutoConfigOutputDevices(void)
{
int i;
if (!xf86Info.autoBindGPU)
return;
for (i = 0; i < xf86NumGPUScreens; i++)
RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
xf86ScrnToScreen(xf86Screens[0]));
}
static void
AddSeatId(CallbackListPtr *pcbl, void *data, void *screen)
{
......@@ -703,6 +717,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();
......@@ -1179,6 +1195,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);
......
......@@ -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;
......
......@@ -97,6 +97,7 @@ typedef struct {
Bool autoAddGPU;
const char *debug;
Bool autoBindGPU;
} xf86InfoRec, *xf86InfoPtr;
/* ISC's cc can't handle ~ of UL constants, so explicitly type cast them. */
......
......@@ -49,6 +49,7 @@
#include "Pci.h"
#include "xf86platformBus.h"
#include "xf86Config.h"
#include "xf86Crtc.h"
#include "randrstr.h"
int platformSlotClaimed;
......@@ -665,6 +666,9 @@ xf86platformAddDevice(int index)
}
/* attach unbound to 0 protocol screen */
AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
if (xf86Info.autoBindGPU)
RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
xf86ScrnToScreen(xf86Screens[0]));
RRResourcesChanged(xf86Screens[0]->pScreen);
RRTellChanged(xf86Screens[0]->pScreen);
......
......@@ -280,6 +280,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
......
......@@ -663,6 +663,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.
......
......@@ -1042,6 +1042,9 @@ RRProviderLookup(XID id, RRProviderPtr *provider_p);
extern _X_EXPORT void
RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider);
extern _X_EXPORT void
RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen);
/* rrproviderproperty.c */
extern _X_EXPORT void
......
......@@ -485,3 +485,25 @@ RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
WriteEventsToClient(client, 1, (xEvent *) &pe);
}
void
RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen)
{
rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
rrScrPrivPtr masterPriv = rrGetScrPriv(masterScreen);
RRProviderPtr provider = pScrPriv->provider;
RRProviderPtr master_provider = masterPriv->provider;
if (!provider || !master_provider)
return;
if ((provider->capabilities & RR_Capability_SinkOutput) &&
(master_provider->capabilities & RR_Capability_SourceOutput)) {
pScrPriv->rrProviderSetOutputSource(pScreen, provider, master_provider);
RRInitPrimeSyncProps(pScreen);
}
if ((provider->capabilities & RR_Capability_SourceOffload) &&
(master_provider->capabilities & RR_Capability_SinkOffload))
pScrPriv->rrProviderSetOffloadSink(pScreen, provider, master_provider);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment