xserver-autobind-hotplug.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. From 4471df41ea6e94834a2b10643ca7fcd69682d276 Mon Sep 17 00:00:00 2001
  2. From: Dave Airlie <airlied@redhat.com>
  3. Date: Fri, 17 Aug 2012 09:49:24 +1000
  4. Subject: [PATCH xserver v3] autobind GPUs to the screen
  5. This is a modified version of a patch we've been carry-ing in Fedora and
  6. RHEL for years now. This patch automatically adds secondary GPUs to the
  7. master as output sink / offload source making e.g. the use of
  8. slave-outputs just work, with requiring the user to manually run
  9. "xrandr --setprovideroutputsource" before he can hookup an external
  10. monitor to his hybrid graphics laptop.
  11. There is one problem with this patch, which is why it was not upstreamed
  12. before. What to do when a secondary GPU gets detected really is a policy
  13. decission (e.g. one may want to autobind PCI GPUs but not USB ones) and
  14. as such should be under control of the Desktop Environment.
  15. Unconditionally adding autobinding support to the xserver will result
  16. in races between the DE dealing with the hotplug of a secondary GPU
  17. and the server itself dealing with it.
  18. However we've waited for years for any Desktop Environments to actually
  19. start doing some sort of autoconfiguration of secondary GPUs and there
  20. is still not a single DE dealing with this, so I believe that it is
  21. time to upstream this now.
  22. To avoid potential future problems if any DEs get support for doing
  23. secondary GPU configuration themselves, the new autobind functionality
  24. is made optional. Since no DEs currently support doing this themselves it
  25. is enabled by default. When DEs grow support for doing this themselves
  26. they can disable the servers autobinding through the servers cmdline or a
  27. xorg.conf snippet.
  28. Signed-off-by: Dave Airlie <airlied@gmail.com>
  29. [hdegoede@redhat.com: Make configurable, fix with nvidia, submit upstream]
  30. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  31. ---
  32. Changes in v2:
  33. -Make the default enabled instead of installing a xorg.conf
  34. snippet which enables it unconditionally
  35. Changes in v3:
  36. -Handle GPUScreen autoconfig in randr/rrprovider.c, looking at
  37. rrScrPriv->provider, rather then in hw/xfree86/modes/xf86Crtc.c
  38. looking at xf86CrtcConfig->provider. This fixes the autoconfig not
  39. working with the nvidia binary driver
  40. ---
  41. hw/xfree86/common/xf86Config.c | 19 +++++++++++++++++++
  42. hw/xfree86/common/xf86Globals.c | 2 ++
  43. hw/xfree86/common/xf86Init.c | 20 ++++++++++++++++++++
  44. hw/xfree86/common/xf86Priv.h | 1 +
  45. hw/xfree86/common/xf86Privstr.h | 1 +
  46. hw/xfree86/common/xf86platformBus.c | 4 ++++
  47. hw/xfree86/man/Xorg.man | 7 +++++++
  48. hw/xfree86/man/xorg.conf.man | 6 ++++++
  49. randr/randrstr.h | 3 +++
  50. randr/rrprovider.c | 22 ++++++++++++++++++++++
  51. 10 files changed, 85 insertions(+)
  52. diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
  53. index 21daf1a..df3ca50 100644
  54. --- a/hw/xfree86/common/xf86Config.c
  55. +++ b/hw/xfree86/common/xf86Config.c
  56. @@ -719,6 +719,7 @@ typedef enum {
  57. FLAG_DRI2,
  58. FLAG_USE_SIGIO,
  59. FLAG_AUTO_ADD_GPU,
  60. + FLAG_AUTO_BIND_GPU,
  61. FLAG_MAX_CLIENTS,
  62. FLAG_IGLX,
  63. } FlagValues;
  64. @@ -778,6 +779,8 @@ static OptionInfoRec FlagOptions[] = {
  65. {0}, FALSE},
  66. {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
  67. {0}, FALSE},
  68. + {FLAG_AUTO_BIND_GPU, "AutoBindGPU", OPTV_BOOLEAN,
  69. + {0}, FALSE},
  70. {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER,
  71. {0}, FALSE },
  72. {FLAG_IGLX, "IndirectGLX", OPTV_BOOLEAN,
  73. @@ -857,6 +860,22 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
  74. }
  75. xf86Msg(from, "%sutomatically adding GPU devices\n",
  76. xf86Info.autoAddGPU ? "A" : "Not a");
  77. +
  78. + if (xf86AutoBindGPUDisabled) {
  79. + xf86Info.autoBindGPU = FALSE;
  80. + from = X_CMDLINE;
  81. + }
  82. + else if (xf86IsOptionSet(FlagOptions, FLAG_AUTO_BIND_GPU)) {
  83. + xf86GetOptValBool(FlagOptions, FLAG_AUTO_BIND_GPU,
  84. + &xf86Info.autoBindGPU);
  85. + from = X_CONFIG;
  86. + }
  87. + else {
  88. + from = X_DEFAULT;
  89. + }
  90. + xf86Msg(from, "%sutomatically binding GPU devices\n",
  91. + xf86Info.autoBindGPU ? "A" : "Not a");
  92. +
  93. /*
  94. * Set things up based on the config file information. Some of these
  95. * settings may be overridden later when the command line options are
  96. diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
  97. index e962b75..0d1e31b 100644
  98. --- a/hw/xfree86/common/xf86Globals.c
  99. +++ b/hw/xfree86/common/xf86Globals.c
  100. @@ -136,6 +136,7 @@ xf86InfoRec xf86Info = {
  101. #else
  102. .autoAddGPU = FALSE,
  103. #endif
  104. + .autoBindGPU = TRUE,
  105. };
  106. const char *xf86ConfigFile = NULL;
  107. @@ -197,6 +198,7 @@ Bool xf86FlipPixels = FALSE;
  108. Gamma xf86Gamma = { 0.0, 0.0, 0.0 };
  109. Bool xf86AllowMouseOpenFail = FALSE;
  110. +Bool xf86AutoBindGPUDisabled = FALSE;
  111. #ifdef XF86VIDMODE
  112. Bool xf86VidModeDisabled = FALSE;
  113. diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
  114. index a544b65..b0cba3d 100644
  115. --- a/hw/xfree86/common/xf86Init.c
  116. +++ b/hw/xfree86/common/xf86Init.c
  117. @@ -76,6 +76,7 @@
  118. #include "xf86DDC.h"
  119. #include "xf86Xinput.h"
  120. #include "xf86InPriv.h"
  121. +#include "xf86Crtc.h"
  122. #include "picturestr.h"
  123. #include "xf86Bus.h"
  124. @@ -298,6 +299,19 @@ xf86PrivsElevated(void)
  125. }
  126. static void
  127. +xf86AutoConfigOutputDevices(void)
  128. +{
  129. + int i;
  130. +
  131. + if (!xf86Info.autoBindGPU)
  132. + return;
  133. +
  134. + for (i = 0; i < xf86NumGPUScreens; i++)
  135. + RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
  136. + xf86ScrnToScreen(xf86Screens[0]));
  137. +}
  138. +
  139. +static void
  140. InstallSignalHandlers(void)
  141. {
  142. /*
  143. @@ -871,6 +885,8 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
  144. for (i = 0; i < xf86NumGPUScreens; i++)
  145. AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
  146. + xf86AutoConfigOutputDevices();
  147. +
  148. xf86VGAarbiterWrapFunctions();
  149. if (sigio_blocked)
  150. input_unlock();
  151. @@ -1389,6 +1405,10 @@ ddxProcessArgument(int argc, char **argv, int i)
  152. xf86Info.iglxFrom = X_CMDLINE;
  153. return 0;
  154. }
  155. + if (!strcmp(argv[i], "-noautoBindGPU")) {
  156. + xf86AutoBindGPUDisabled = TRUE;
  157. + return 1;
  158. + }
  159. /* OS-specific processing */
  160. return xf86ProcessArgument(argc, argv, i);
  161. diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
  162. index c1f8a18..9a3d0df 100644
  163. --- a/hw/xfree86/common/xf86Priv.h
  164. +++ b/hw/xfree86/common/xf86Priv.h
  165. @@ -46,6 +46,7 @@
  166. extern _X_EXPORT const char *xf86ConfigFile;
  167. extern _X_EXPORT const char *xf86ConfigDir;
  168. extern _X_EXPORT Bool xf86AllowMouseOpenFail;
  169. +extern _X_EXPORT Bool xf86AutoBindGPUDisabled;
  170. #ifdef XF86VIDMODE
  171. extern _X_EXPORT Bool xf86VidModeDisabled;
  172. diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
  173. index c29b3cc..4c5f54b 100644
  174. --- a/hw/xfree86/common/xf86Privstr.h
  175. +++ b/hw/xfree86/common/xf86Privstr.h
  176. @@ -102,6 +102,7 @@ typedef struct {
  177. MessageType dri2From;
  178. Bool autoAddGPU;
  179. + Bool autoBindGPU;
  180. } xf86InfoRec, *xf86InfoPtr;
  181. #ifdef DPMSExtension
  182. diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c
  183. index 063e81c..42789ca 100644
  184. --- a/hw/xfree86/common/xf86platformBus.c
  185. +++ b/hw/xfree86/common/xf86platformBus.c
  186. @@ -48,6 +48,7 @@
  187. #include "Pci.h"
  188. #include "xf86platformBus.h"
  189. #include "xf86Config.h"
  190. +#include "xf86Crtc.h"
  191. #include "randrstr.h"
  192. int platformSlotClaimed;
  193. @@ -579,6 +580,9 @@ xf86platformAddDevice(int index)
  194. }
  195. /* attach unbound to 0 protocol screen */
  196. AttachUnboundGPU(xf86Screens[0]->pScreen, xf86GPUScreens[i]->pScreen);
  197. + if (xf86Info.autoBindGPU)
  198. + RRProviderAutoConfigGpuScreen(xf86ScrnToScreen(xf86GPUScreens[i]),
  199. + xf86ScrnToScreen(xf86Screens[0]));
  200. RRResourcesChanged(xf86Screens[0]->pScreen);
  201. RRTellChanged(xf86Screens[0]->pScreen);
  202. diff --git a/hw/xfree86/man/Xorg.man b/hw/xfree86/man/Xorg.man
  203. index def9bfc..8df6b7d 100644
  204. --- a/hw/xfree86/man/Xorg.man
  205. +++ b/hw/xfree86/man/Xorg.man
  206. @@ -283,6 +283,13 @@ is a comma separated list of directories to search for
  207. server modules. This option is only available when the server is run
  208. as root (i.e, with real-uid 0).
  209. .TP 8
  210. +.B \-noautoBindGPU
  211. +Disable automatically setting secondary GPUs up as output sinks and offload
  212. +sources. This is equivalent to setting the
  213. +.B AutoBindGPU
  214. +xorg.conf(__filemansuffix__) file option. To
  215. +.B false.
  216. +.TP 8
  217. .B \-nosilk
  218. Disable Silken Mouse support.
  219. .TP 8
  220. diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
  221. index 7d0c524..3e596e4 100644
  222. --- a/hw/xfree86/man/xorg.conf.man
  223. +++ b/hw/xfree86/man/xorg.conf.man
  224. @@ -673,6 +673,12 @@ Enabled by default.
  225. If this option is disabled, then no GPU devices will be added from the udev
  226. backend. Enabled by default. (May need to be disabled to setup Xinerama).
  227. .TP 7
  228. +.BI "Option \*qAutoBindGPU\*q \*q" boolean \*q
  229. +If enabled then secondary GPUs will be automatically set up as output-sinks and
  230. +offload-sources. Making e.g. laptop outputs connected only to the secondary
  231. +GPU directly available for use without needing to run
  232. +"xrandr --setprovideroutputsource". Enabled by default.
  233. +.TP 7
  234. .BI "Option \*qLog\*q \*q" string \*q
  235. This option controls whether the log is flushed and/or synced to disk after
  236. each message.
  237. diff --git a/randr/randrstr.h b/randr/randrstr.h
  238. index 706e9a7..66999d5 100644
  239. --- a/randr/randrstr.h
  240. +++ b/randr/randrstr.h
  241. @@ -976,6 +976,9 @@ RRProviderLookup(XID id, RRProviderPtr *provider_p);
  242. extern _X_EXPORT void
  243. RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider);
  244. +extern _X_EXPORT void
  245. +RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen);
  246. +
  247. /* rrproviderproperty.c */
  248. extern _X_EXPORT void
  249. diff --git a/randr/rrprovider.c b/randr/rrprovider.c
  250. index f9df67e..abc5685 100644
  251. --- a/randr/rrprovider.c
  252. +++ b/randr/rrprovider.c
  253. @@ -482,3 +482,25 @@ RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
  254. WriteEventsToClient(client, 1, (xEvent *) &pe);
  255. }
  256. +
  257. +void
  258. +RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr masterScreen)
  259. +{
  260. + rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
  261. + rrScrPrivPtr masterPriv = rrGetScrPriv(masterScreen);
  262. + RRProviderPtr provider = pScrPriv->provider;
  263. + RRProviderPtr master_provider = masterPriv->provider;
  264. +
  265. + if (!provider || !master_provider)
  266. + return;
  267. +
  268. + if ((provider->capabilities & RR_Capability_SinkOutput) &&
  269. + (master_provider->capabilities & RR_Capability_SourceOutput)) {
  270. + pScrPriv->rrProviderSetOutputSource(pScreen, provider, master_provider);
  271. + RRInitPrimeSyncProps(pScreen);
  272. + }
  273. +
  274. + if ((provider->capabilities & RR_Capability_SourceOffload) &&
  275. + (master_provider->capabilities & RR_Capability_SinkOffload))
  276. + pScrPriv->rrProviderSetOffloadSink(pScreen, provider, master_provider);
  277. +}
  278. --
  279. 2.9.3