dmxinit.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. /*
  2. * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
  3. *
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation on the rights to use, copy, modify, merge,
  10. * publish, distribute, sublicense, and/or sell copies of the Software,
  11. * and to permit persons to whom the Software is furnished to do so,
  12. * subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice (including the
  15. * next paragraph) shall be included in all copies or substantial
  16. * portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
  22. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  23. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  25. * SOFTWARE.
  26. */
  27. /*
  28. * Authors:
  29. * Kevin E. Martin <kem@redhat.com>
  30. * David H. Dawes <dawes@xfree86.org>
  31. * Rickard E. (Rik) Faith <faith@redhat.com>
  32. *
  33. */
  34. /** \file
  35. * Provide expected functions for initialization from the ddx layer and
  36. * global variables for the DMX server. */
  37. #ifdef HAVE_DMX_CONFIG_H
  38. #include <dmx-config.h>
  39. #endif
  40. #include "dmx.h"
  41. #include "dmxinit.h"
  42. #include "dmxsync.h"
  43. #include "dmxlog.h"
  44. #include "dmxinput.h"
  45. #include "dmxscrinit.h"
  46. #include "dmxcursor.h"
  47. #include "dmxfont.h"
  48. #include "config/dmxconfig.h"
  49. #include "dmxcb.h"
  50. #include "dmxprop.h"
  51. #include "dmxstat.h"
  52. #include "dmxpict.h"
  53. #include <X11/Xos.h> /* For gettimeofday */
  54. #include <X11/Xmu/SysUtil.h> /* For XmuGetHostname */
  55. #include "dixstruct.h"
  56. #ifdef PANORAMIX
  57. #include "panoramiXsrv.h"
  58. #endif
  59. #include <signal.h> /* For SIGQUIT */
  60. #ifdef GLXEXT
  61. #include <GL/glx.h>
  62. #include <GL/glxint.h>
  63. #include "dmx_glxvisuals.h"
  64. #include "glx_extinit.h"
  65. #include <X11/extensions/Xext.h>
  66. #include <X11/extensions/extutil.h>
  67. #endif /* GLXEXT */
  68. #include <X11/extensions/dmxproto.h>
  69. /* Global variables available to all Xserver/hw/dmx routines. */
  70. int dmxNumScreens;
  71. DMXScreenInfo *dmxScreens;
  72. int dmxNumInputs;
  73. DMXInputInfo *dmxInputs;
  74. XErrorEvent dmxLastErrorEvent;
  75. Bool dmxErrorOccurred = FALSE;
  76. char *dmxFontPath = NULL;
  77. Bool dmxOffScreenOpt = TRUE;
  78. Bool dmxSubdividePrimitives = TRUE;
  79. Bool dmxLazyWindowCreation = TRUE;
  80. Bool dmxUseXKB = TRUE;
  81. int dmxDepth = 0;
  82. #ifndef GLXEXT
  83. static Bool dmxGLXProxy = FALSE;
  84. #else
  85. Bool dmxGLXProxy = TRUE;
  86. Bool dmxGLXSwapGroupSupport = TRUE;
  87. Bool dmxGLXSyncSwap = FALSE;
  88. Bool dmxGLXFinishSwap = FALSE;
  89. #endif
  90. RESTYPE RRProviderType = 0;
  91. Bool dmxIgnoreBadFontPaths = FALSE;
  92. Bool dmxAddRemoveScreens = FALSE;
  93. /* dmxErrorHandler catches errors that occur when calling one of the
  94. * back-end servers. Some of this code is based on _XPrintDefaultError
  95. * in xc/lib/X11/XlibInt.c */
  96. static int
  97. dmxErrorHandler(Display * dpy, XErrorEvent * ev)
  98. {
  99. #define DMX_ERROR_BUF_SIZE 256
  100. /* RATS: these buffers are only used in
  101. * length-limited calls. */
  102. char buf[DMX_ERROR_BUF_SIZE];
  103. char request[DMX_ERROR_BUF_SIZE];
  104. _XExtension *ext = NULL;
  105. dmxErrorOccurred = TRUE;
  106. dmxLastErrorEvent = *ev;
  107. XGetErrorText(dpy, ev->error_code, buf, sizeof(buf));
  108. dmxLog(dmxWarning, "dmxErrorHandler: %s\n", buf);
  109. /* Find major opcode name */
  110. if (ev->request_code < 128) {
  111. snprintf(request, sizeof(request), "%d", ev->request_code);
  112. XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
  113. }
  114. else {
  115. for (ext = dpy->ext_procs;
  116. ext && ext->codes.major_opcode != ev->request_code;
  117. ext = ext->next);
  118. if (ext)
  119. strlcpy(buf, ext->name, sizeof(buf));
  120. else
  121. buf[0] = '\0';
  122. }
  123. dmxLog(dmxWarning, " Major opcode: %d (%s)\n",
  124. ev->request_code, buf);
  125. /* Find minor opcode name */
  126. if (ev->request_code >= 128 && ext) {
  127. snprintf(request, sizeof(request), "%d", ev->request_code);
  128. snprintf(request, sizeof(request), "%s.%d", ext->name, ev->minor_code);
  129. XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
  130. dmxLog(dmxWarning, " Minor opcode: %d (%s)\n",
  131. ev->minor_code, buf);
  132. }
  133. /* Provide value information */
  134. switch (ev->error_code) {
  135. case BadValue:
  136. dmxLog(dmxWarning, " Value: 0x%x\n",
  137. ev->resourceid);
  138. break;
  139. case BadAtom:
  140. dmxLog(dmxWarning, " AtomID: 0x%x\n",
  141. ev->resourceid);
  142. break;
  143. default:
  144. dmxLog(dmxWarning, " ResourceID: 0x%x\n",
  145. ev->resourceid);
  146. break;
  147. }
  148. /* Provide serial number information */
  149. dmxLog(dmxWarning, " Failed serial number: %d\n",
  150. ev->serial);
  151. dmxLog(dmxWarning, " Current serial number: %d\n",
  152. dpy->request);
  153. return 0;
  154. }
  155. #ifdef GLXEXT
  156. static int
  157. dmxNOPErrorHandler(Display * dpy, XErrorEvent * ev)
  158. {
  159. return 0;
  160. }
  161. #endif
  162. Bool
  163. dmxOpenDisplay(DMXScreenInfo * dmxScreen)
  164. {
  165. if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->name)))
  166. return FALSE;
  167. dmxPropertyDisplay(dmxScreen);
  168. return TRUE;
  169. }
  170. void
  171. dmxSetErrorHandler(DMXScreenInfo * dmxScreen)
  172. {
  173. XSetErrorHandler(dmxErrorHandler);
  174. }
  175. static void
  176. dmxPrintScreenInfo(DMXScreenInfo * dmxScreen)
  177. {
  178. XWindowAttributes attribs;
  179. int ndepths = 0, *depths = NULL;
  180. int i;
  181. Display *dpy = dmxScreen->beDisplay;
  182. Screen *s = DefaultScreenOfDisplay(dpy);
  183. int scr = DefaultScreen(dpy);
  184. XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs);
  185. if (!(depths = XListDepths(dpy, scr, &ndepths)))
  186. ndepths = 0;
  187. dmxLogOutput(dmxScreen, "Name of display: %s\n", DisplayString(dpy));
  188. dmxLogOutput(dmxScreen, "Version number: %d.%d\n",
  189. ProtocolVersion(dpy), ProtocolRevision(dpy));
  190. dmxLogOutput(dmxScreen, "Vendor string: %s\n", ServerVendor(dpy));
  191. if (!strstr(ServerVendor(dpy), "XFree86")) {
  192. dmxLogOutput(dmxScreen, "Vendor release: %d\n", VendorRelease(dpy));
  193. }
  194. else {
  195. /* This code based on xdpyinfo.c */
  196. int v = VendorRelease(dpy);
  197. int major = -1, minor = -1, patch = -1, subpatch = -1;
  198. if (v < 336)
  199. major = v / 100, minor = (v / 10) % 10, patch = v % 10;
  200. else if (v < 3900) {
  201. major = v / 1000;
  202. minor = (v / 100) % 10;
  203. if (((v / 10) % 10) || (v % 10)) {
  204. patch = (v / 10) % 10;
  205. if (v % 10)
  206. subpatch = v % 10;
  207. }
  208. }
  209. else if (v < 40000000) {
  210. major = v / 1000;
  211. minor = (v / 10) % 10;
  212. if (v % 10)
  213. patch = v % 10;
  214. }
  215. else {
  216. major = v / 10000000;
  217. minor = (v / 100000) % 100;
  218. patch = (v / 1000) % 100;
  219. if (v % 1000)
  220. subpatch = v % 1000;
  221. }
  222. dmxLogOutput(dmxScreen, "Vendor release: %d (XFree86 version: %d.%d",
  223. v, major, minor);
  224. if (patch > 0)
  225. dmxLogOutputCont(dmxScreen, ".%d", patch);
  226. if (subpatch > 0)
  227. dmxLogOutputCont(dmxScreen, ".%d", subpatch);
  228. dmxLogOutputCont(dmxScreen, ")\n");
  229. }
  230. dmxLogOutput(dmxScreen, "Dimensions: %dx%d pixels\n",
  231. attribs.width, attribs.height);
  232. dmxLogOutput(dmxScreen, "%d depths on screen %d: ", ndepths, scr);
  233. for (i = 0; i < ndepths; i++)
  234. dmxLogOutputCont(dmxScreen, "%c%d", i ? ',' : ' ', depths[i]);
  235. dmxLogOutputCont(dmxScreen, "\n");
  236. dmxLogOutput(dmxScreen, "Depth of root window: %d plane%s (%d)\n",
  237. attribs.depth, attribs.depth == 1 ? "" : "s",
  238. DisplayPlanes(dpy, scr));
  239. dmxLogOutput(dmxScreen, "Number of colormaps: %d min, %d max\n",
  240. MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
  241. dmxLogOutput(dmxScreen, "Options: backing-store %s, save-unders %s\n",
  242. (DoesBackingStore(s) == NotUseful) ? "no" :
  243. ((DoesBackingStore(s) == Always) ? "yes" : "when mapped"),
  244. DoesSaveUnders(s) ? "yes" : "no");
  245. dmxLogOutput(dmxScreen, "Window Manager running: %s\n",
  246. (dmxScreen->WMRunningOnBE) ? "yes" : "no");
  247. if (dmxScreen->WMRunningOnBE) {
  248. dmxLogOutputWarning(dmxScreen,
  249. "Window manager running "
  250. "-- colormaps not supported\n");
  251. }
  252. XFree(depths);
  253. }
  254. void
  255. dmxGetScreenAttribs(DMXScreenInfo * dmxScreen)
  256. {
  257. XWindowAttributes attribs;
  258. Display *dpy = dmxScreen->beDisplay;
  259. #ifdef GLXEXT
  260. int dummy;
  261. #endif
  262. XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs);
  263. dmxScreen->beWidth = attribs.width;
  264. dmxScreen->beHeight = attribs.height;
  265. /* Fill in missing geometry information */
  266. if (dmxScreen->scrnXSign < 0) {
  267. if (dmxScreen->scrnWidth) {
  268. dmxScreen->scrnX = (attribs.width - dmxScreen->scrnWidth
  269. - dmxScreen->scrnX);
  270. }
  271. else {
  272. dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX;
  273. dmxScreen->scrnX = 0;
  274. }
  275. }
  276. if (dmxScreen->scrnYSign < 0) {
  277. if (dmxScreen->scrnHeight) {
  278. dmxScreen->scrnY = (attribs.height - dmxScreen->scrnHeight
  279. - dmxScreen->scrnY);
  280. }
  281. else {
  282. dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
  283. dmxScreen->scrnY = 0;
  284. }
  285. }
  286. if (!dmxScreen->scrnWidth)
  287. dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX;
  288. if (!dmxScreen->scrnHeight)
  289. dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
  290. if (!dmxScreen->rootWidth)
  291. dmxScreen->rootWidth = dmxScreen->scrnWidth;
  292. if (!dmxScreen->rootHeight)
  293. dmxScreen->rootHeight = dmxScreen->scrnHeight;
  294. if (dmxScreen->rootWidth + dmxScreen->rootX > dmxScreen->scrnWidth)
  295. dmxScreen->rootWidth = dmxScreen->scrnWidth - dmxScreen->rootX;
  296. if (dmxScreen->rootHeight + dmxScreen->rootY > dmxScreen->scrnHeight)
  297. dmxScreen->rootHeight = dmxScreen->scrnHeight - dmxScreen->rootY;
  298. /* FIXME: Get these from the back-end server */
  299. dmxScreen->beXDPI = 75;
  300. dmxScreen->beYDPI = 75;
  301. dmxScreen->beDepth = attribs.depth; /* FIXME: verify that this
  302. * works always. In
  303. * particular, this will work
  304. * well for depth=16, will fail
  305. * because of colormap issues
  306. * at depth 8. More work needs
  307. * to be done here. */
  308. if (dmxScreen->beDepth <= 8)
  309. dmxScreen->beBPP = 8;
  310. else if (dmxScreen->beDepth <= 16)
  311. dmxScreen->beBPP = 16;
  312. else
  313. dmxScreen->beBPP = 32;
  314. #ifdef GLXEXT
  315. /* get the majorOpcode for the back-end GLX extension */
  316. XQueryExtension(dpy, "GLX", &dmxScreen->glxMajorOpcode,
  317. &dummy, &dmxScreen->glxErrorBase);
  318. #endif
  319. dmxPrintScreenInfo(dmxScreen);
  320. dmxLogOutput(dmxScreen, "%dx%d+%d+%d on %dx%d at depth=%d, bpp=%d\n",
  321. dmxScreen->scrnWidth, dmxScreen->scrnHeight,
  322. dmxScreen->scrnX, dmxScreen->scrnY,
  323. dmxScreen->beWidth, dmxScreen->beHeight,
  324. dmxScreen->beDepth, dmxScreen->beBPP);
  325. if (dmxScreen->beDepth == 8)
  326. dmxLogOutputWarning(dmxScreen,
  327. "Support for depth == 8 is not complete\n");
  328. }
  329. Bool
  330. dmxGetVisualInfo(DMXScreenInfo * dmxScreen)
  331. {
  332. int i;
  333. XVisualInfo visinfo;
  334. visinfo.screen = DefaultScreen(dmxScreen->beDisplay);
  335. dmxScreen->beVisuals = XGetVisualInfo(dmxScreen->beDisplay,
  336. VisualScreenMask,
  337. &visinfo, &dmxScreen->beNumVisuals);
  338. dmxScreen->beDefVisualIndex = -1;
  339. if (defaultColorVisualClass >= 0 || dmxDepth > 0) {
  340. for (i = 0; i < dmxScreen->beNumVisuals; i++)
  341. if (defaultColorVisualClass >= 0) {
  342. if (dmxScreen->beVisuals[i].class == defaultColorVisualClass) {
  343. if (dmxDepth > 0) {
  344. if (dmxScreen->beVisuals[i].depth == dmxDepth) {
  345. dmxScreen->beDefVisualIndex = i;
  346. break;
  347. }
  348. }
  349. else {
  350. dmxScreen->beDefVisualIndex = i;
  351. break;
  352. }
  353. }
  354. }
  355. else if (dmxScreen->beVisuals[i].depth == dmxDepth) {
  356. dmxScreen->beDefVisualIndex = i;
  357. break;
  358. }
  359. }
  360. else {
  361. visinfo.visualid =
  362. XVisualIDFromVisual(DefaultVisual(dmxScreen->beDisplay,
  363. visinfo.screen));
  364. for (i = 0; i < dmxScreen->beNumVisuals; i++)
  365. if (visinfo.visualid == dmxScreen->beVisuals[i].visualid) {
  366. dmxScreen->beDefVisualIndex = i;
  367. break;
  368. }
  369. }
  370. for (i = 0; i < dmxScreen->beNumVisuals; i++)
  371. dmxLogVisual(dmxScreen, &dmxScreen->beVisuals[i],
  372. (i == dmxScreen->beDefVisualIndex));
  373. return dmxScreen->beDefVisualIndex >= 0;
  374. }
  375. void
  376. dmxGetColormaps(DMXScreenInfo * dmxScreen)
  377. {
  378. int i;
  379. dmxScreen->beNumDefColormaps = dmxScreen->beNumVisuals;
  380. dmxScreen->beDefColormaps = malloc(dmxScreen->beNumDefColormaps *
  381. sizeof(*dmxScreen->beDefColormaps));
  382. for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
  383. dmxScreen->beDefColormaps[i] =
  384. XCreateColormap(dmxScreen->beDisplay,
  385. DefaultRootWindow(dmxScreen->beDisplay),
  386. dmxScreen->beVisuals[i].visual, AllocNone);
  387. dmxScreen->beBlackPixel = BlackPixel(dmxScreen->beDisplay,
  388. DefaultScreen(dmxScreen->beDisplay));
  389. dmxScreen->beWhitePixel = WhitePixel(dmxScreen->beDisplay,
  390. DefaultScreen(dmxScreen->beDisplay));
  391. }
  392. void
  393. dmxGetPixmapFormats(DMXScreenInfo * dmxScreen)
  394. {
  395. dmxScreen->beDepths =
  396. XListDepths(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay),
  397. &dmxScreen->beNumDepths);
  398. dmxScreen->bePixmapFormats =
  399. XListPixmapFormats(dmxScreen->beDisplay,
  400. &dmxScreen->beNumPixmapFormats);
  401. }
  402. static Bool
  403. dmxSetPixmapFormats(ScreenInfo * pScreenInfo, DMXScreenInfo * dmxScreen)
  404. {
  405. XPixmapFormatValues *bePixmapFormat;
  406. PixmapFormatRec *format;
  407. int i, j;
  408. pScreenInfo->imageByteOrder = ImageByteOrder(dmxScreen->beDisplay);
  409. pScreenInfo->bitmapScanlineUnit = BitmapUnit(dmxScreen->beDisplay);
  410. pScreenInfo->bitmapScanlinePad = BitmapPad(dmxScreen->beDisplay);
  411. pScreenInfo->bitmapBitOrder = BitmapBitOrder(dmxScreen->beDisplay);
  412. pScreenInfo->numPixmapFormats = 0;
  413. for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
  414. bePixmapFormat = &dmxScreen->bePixmapFormats[i];
  415. for (j = 0; j < dmxScreen->beNumDepths; j++)
  416. if ((bePixmapFormat->depth == 1) ||
  417. (bePixmapFormat->depth == dmxScreen->beDepths[j])) {
  418. format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats];
  419. format->depth = bePixmapFormat->depth;
  420. format->bitsPerPixel = bePixmapFormat->bits_per_pixel;
  421. format->scanlinePad = bePixmapFormat->scanline_pad;
  422. pScreenInfo->numPixmapFormats++;
  423. break;
  424. }
  425. }
  426. return TRUE;
  427. }
  428. void
  429. dmxCheckForWM(DMXScreenInfo * dmxScreen)
  430. {
  431. Status status;
  432. XWindowAttributes xwa;
  433. status = XGetWindowAttributes(dmxScreen->beDisplay,
  434. DefaultRootWindow(dmxScreen->beDisplay),
  435. &xwa);
  436. dmxScreen->WMRunningOnBE =
  437. (status &&
  438. ((xwa.all_event_masks & SubstructureRedirectMask) ||
  439. (xwa.all_event_masks & SubstructureNotifyMask)));
  440. }
  441. /** Initialize the display and collect relevant information about the
  442. * display properties */
  443. static void
  444. dmxDisplayInit(DMXScreenInfo * dmxScreen)
  445. {
  446. if (!dmxOpenDisplay(dmxScreen))
  447. dmxLog(dmxFatal,
  448. "dmxOpenDisplay: Unable to open display %s\n", dmxScreen->name);
  449. dmxSetErrorHandler(dmxScreen);
  450. dmxCheckForWM(dmxScreen);
  451. dmxGetScreenAttribs(dmxScreen);
  452. if (!dmxGetVisualInfo(dmxScreen))
  453. dmxLog(dmxFatal, "dmxGetVisualInfo: No matching visuals found\n");
  454. dmxGetColormaps(dmxScreen);
  455. dmxGetPixmapFormats(dmxScreen);
  456. }
  457. /* If this doesn't compile, just add || defined(yoursystem) to the line
  458. * below. This information is to help with bug reports and is not
  459. * critical. */
  460. #if !defined(_POSIX_SOURCE)
  461. static const char *
  462. dmxExecOS(void)
  463. {
  464. return "";
  465. }
  466. #else
  467. #include <sys/utsname.h>
  468. static const char *
  469. dmxExecOS(void)
  470. {
  471. static char buffer[128];
  472. static int initialized = 0;
  473. struct utsname u;
  474. if (!initialized++) {
  475. memset(buffer, 0, sizeof(buffer));
  476. uname(&u);
  477. snprintf(buffer, sizeof(buffer) - 1, "%s %s %s",
  478. u.sysname, u.release, u.version);
  479. }
  480. return buffer;
  481. }
  482. #endif
  483. static const char *
  484. dmxBuildCompiler(void)
  485. {
  486. static char buffer[128];
  487. static int initialized = 0;
  488. if (!initialized++) {
  489. memset(buffer, 0, sizeof(buffer));
  490. #if defined(__GNUC__) && defined(__GNUC_MINOR__) &&defined(__GNUC_PATCHLEVEL__)
  491. snprintf(buffer, sizeof(buffer) - 1, "gcc %d.%d.%d",
  492. __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
  493. #endif
  494. }
  495. return buffer;
  496. }
  497. static const char *
  498. dmxExecHost(void)
  499. {
  500. static char buffer[128];
  501. static int initialized = 0;
  502. if (!initialized++) {
  503. memset(buffer, 0, sizeof(buffer));
  504. XmuGetHostname(buffer, sizeof(buffer) - 1);
  505. }
  506. return buffer;
  507. }
  508. static void dmxAddExtensions(Bool glxSupported)
  509. {
  510. const ExtensionModule dmxExtensions[] = {
  511. { DMXExtensionInit, DMX_EXTENSION_NAME, NULL },
  512. #ifdef GLXEXT
  513. { GlxExtensionInit, "GLX", &glxSupported },
  514. #endif
  515. };
  516. LoadExtensionList(dmxExtensions, ARRAY_SIZE(dmxExtensions), TRUE);
  517. }
  518. /** This routine is called in Xserver/dix/main.c from \a main(). */
  519. void
  520. InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
  521. {
  522. int i;
  523. static unsigned long dmxGeneration = 0;
  524. #ifdef GLXEXT
  525. static Bool glxSupported = TRUE;
  526. #else
  527. const Bool glxSupported = FALSE;
  528. #endif
  529. if (dmxGeneration != serverGeneration) {
  530. int vendrel = VENDOR_RELEASE;
  531. int major, minor, year, month, day;
  532. dmxGeneration = serverGeneration;
  533. major = vendrel / 100000000;
  534. vendrel -= major * 100000000;
  535. minor = vendrel / 1000000;
  536. vendrel -= minor * 1000000;
  537. year = vendrel / 10000;
  538. vendrel -= year * 10000;
  539. month = vendrel / 100;
  540. vendrel -= month * 100;
  541. day = vendrel;
  542. /* Add other epoch tests here */
  543. if (major > 0 && minor > 0)
  544. year += 2000;
  545. dmxLog(dmxInfo, "Generation: %d\n", dmxGeneration);
  546. dmxLog(dmxInfo, "DMX version: %d.%d.%02d%02d%02d (%s)\n",
  547. major, minor, year, month, day, VENDOR_STRING);
  548. SetVendorRelease(VENDOR_RELEASE);
  549. SetVendorString(VENDOR_STRING);
  550. if (dmxGeneration == 1) {
  551. dmxLog(dmxInfo, "DMX Build OS: %s (%s)\n", OSNAME, OSVENDOR);
  552. dmxLog(dmxInfo, "DMX Build Compiler: %s\n", dmxBuildCompiler());
  553. dmxLog(dmxInfo, "DMX Execution OS: %s\n", dmxExecOS());
  554. dmxLog(dmxInfo, "DMX Execution Host: %s\n", dmxExecHost());
  555. }
  556. dmxLog(dmxInfo, "MAXSCREENS: %d\n", MAXSCREENS);
  557. for (i = 0; i < dmxNumScreens; i++) {
  558. if (dmxScreens[i].beDisplay)
  559. dmxLog(dmxWarning, "Display \"%s\" still open\n",
  560. dmxScreens[i].name);
  561. dmxStatFree(dmxScreens[i].stat);
  562. dmxScreens[i].stat = NULL;
  563. }
  564. for (i = 0; i < dmxNumInputs; i++)
  565. dmxInputFree(&dmxInputs[i]);
  566. free(dmxScreens);
  567. free(dmxInputs);
  568. dmxScreens = NULL;
  569. dmxInputs = NULL;
  570. dmxNumScreens = 0;
  571. dmxNumInputs = 0;
  572. }
  573. /* Make sure that the command-line arguments are sane. */
  574. if (dmxAddRemoveScreens && dmxGLXProxy) {
  575. /* Currently it is not possible to support GLX and Render
  576. * extensions with dynamic screen addition/removal due to the
  577. * state that each extension keeps, which cannot be restored. */
  578. dmxLog(dmxWarning,
  579. "GLX Proxy and Render extensions do not yet support dynamic\n");
  580. dmxLog(dmxWarning,
  581. "screen addition and removal. Please specify -noglxproxy\n");
  582. dmxLog(dmxWarning,
  583. "and -norender on the command line or in the configuration\n");
  584. dmxLog(dmxWarning,
  585. "file to disable these two extensions if you wish to use\n");
  586. dmxLog(dmxWarning,
  587. "the dynamic addition and removal of screens support.\n");
  588. dmxLog(dmxFatal,
  589. "Dynamic screen addition/removal error (see above).\n");
  590. }
  591. /* ddxProcessArgument has been called at this point, but any data
  592. * from the configuration file has not been applied. Do so, and be
  593. * sure we have at least one back-end display. */
  594. dmxConfigConfigure();
  595. if (!dmxNumScreens)
  596. dmxLog(dmxFatal, "InitOutput: no back-end displays found\n");
  597. if (!dmxNumInputs)
  598. dmxLog(dmxInfo, "InitOutput: no inputs found\n");
  599. /* Disable lazy window creation optimization if offscreen
  600. * optimization is disabled */
  601. if (!dmxOffScreenOpt && dmxLazyWindowCreation) {
  602. dmxLog(dmxInfo,
  603. "InitOutput: Disabling lazy window creation optimization\n");
  604. dmxLog(dmxInfo,
  605. " since it requires the offscreen optimization\n");
  606. dmxLog(dmxInfo, " to function properly.\n");
  607. dmxLazyWindowCreation = FALSE;
  608. }
  609. /* Open each display and gather information about it. */
  610. for (i = 0; i < dmxNumScreens; i++)
  611. dmxDisplayInit(&dmxScreens[i]);
  612. #if PANORAMIX
  613. /* Register a Xinerama callback which will run from within
  614. * PanoramiXCreateConnectionBlock. We can use the callback to
  615. * determine if Xinerama is loaded and to check the visuals
  616. * determined by PanoramiXConsolidate. */
  617. XineramaRegisterConnectionBlockCallback(dmxConnectionBlockCallback);
  618. #endif
  619. /* Since we only have a single screen thus far, we only need to set
  620. the pixmap formats to match that screen. FIXME: this isn't true. */
  621. if (!dmxSetPixmapFormats(pScreenInfo, &dmxScreens[0]))
  622. return;
  623. /* Might want to install a signal handler to allow cleaning up after
  624. * unexpected signals. The DIX/OS layer already handles SIGINT and
  625. * SIGTERM, so everything is OK for expected signals. --DD
  626. *
  627. * SIGHUP, SIGINT, and SIGTERM are trapped in os/connection.c
  628. * SIGQUIT is another common signal that is sent from the keyboard.
  629. * Trap it here, to ensure that the keyboard modifier map and other
  630. * state for the input devices are restored. (This makes the
  631. * behavior of SIGQUIT somewhat unexpected, since it will be the
  632. * same as the behavior of SIGINT. However, leaving the modifier
  633. * map of the input devices empty is even more unexpected.) --RF
  634. */
  635. OsSignal(SIGQUIT, GiveUp);
  636. #ifdef GLXEXT
  637. /* Check if GLX extension exists on all back-end servers */
  638. for (i = 0; i < dmxNumScreens; i++)
  639. glxSupported &= (dmxScreens[i].glxMajorOpcode > 0);
  640. #endif
  641. if (serverGeneration == 1)
  642. dmxAddExtensions(glxSupported);
  643. /* Tell dix layer about the backend displays */
  644. for (i = 0; i < dmxNumScreens; i++) {
  645. #ifdef GLXEXT
  646. if (glxSupported) {
  647. /*
  648. * Builds GLX configurations from the list of visuals
  649. * supported by the back-end server, and give that
  650. * configuration list to the glx layer - so that he will
  651. * build the visuals accordingly.
  652. */
  653. DMXScreenInfo *dmxScreen = &dmxScreens[i];
  654. __GLXvisualConfig *configs = NULL;
  655. dmxGlxVisualPrivate **configprivs = NULL;
  656. int nconfigs = 0;
  657. int (*oldErrorHandler) (Display *, XErrorEvent *);
  658. int i;
  659. /* Catch errors if when using an older GLX w/o FBconfigs */
  660. oldErrorHandler = XSetErrorHandler(dmxNOPErrorHandler);
  661. /* Get FBConfigs of the back-end server */
  662. dmxScreen->fbconfigs = GetGLXFBConfigs(dmxScreen->beDisplay,
  663. dmxScreen->glxMajorOpcode,
  664. &dmxScreen->numFBConfigs);
  665. XSetErrorHandler(oldErrorHandler);
  666. dmxScreen->glxVisuals =
  667. GetGLXVisualConfigs(dmxScreen->beDisplay,
  668. DefaultScreen(dmxScreen->beDisplay),
  669. &dmxScreen->numGlxVisuals);
  670. if (dmxScreen->fbconfigs) {
  671. configs =
  672. GetGLXVisualConfigsFromFBConfigs(dmxScreen->fbconfigs,
  673. dmxScreen->numFBConfigs,
  674. dmxScreen->beVisuals,
  675. dmxScreen->beNumVisuals,
  676. dmxScreen->glxVisuals,
  677. dmxScreen->numGlxVisuals,
  678. &nconfigs);
  679. }
  680. else {
  681. configs = dmxScreen->glxVisuals;
  682. nconfigs = dmxScreen->numGlxVisuals;
  683. }
  684. configprivs = malloc(nconfigs * sizeof(dmxGlxVisualPrivate *));
  685. if (configs != NULL && configprivs != NULL) {
  686. /* Initialize our private info for each visual
  687. * (currently only x_visual_depth and x_visual_class)
  688. */
  689. for (i = 0; i < nconfigs; i++) {
  690. configprivs[i] = (dmxGlxVisualPrivate *)
  691. malloc(sizeof(dmxGlxVisualPrivate));
  692. configprivs[i]->x_visual_depth = 0;
  693. configprivs[i]->x_visual_class = 0;
  694. /* Find the visual depth */
  695. if (configs[i].vid > 0) {
  696. int j;
  697. for (j = 0; j < dmxScreen->beNumVisuals; j++) {
  698. if (dmxScreen->beVisuals[j].visualid ==
  699. configs[i].vid) {
  700. configprivs[i]->x_visual_depth =
  701. dmxScreen->beVisuals[j].depth;
  702. configprivs[i]->x_visual_class =
  703. dmxScreen->beVisuals[j].class;
  704. break;
  705. }
  706. }
  707. }
  708. }
  709. XFlush(dmxScreen->beDisplay);
  710. }
  711. }
  712. #endif /* GLXEXT */
  713. AddScreen(dmxScreenInit, argc, argv);
  714. }
  715. /* Compute origin information. */
  716. dmxInitOrigins();
  717. /* Compute overlap information. */
  718. dmxInitOverlap();
  719. /* Make sure there is a global width/height available */
  720. dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
  721. /* FIXME: The following is temporarily placed here. When the DMX
  722. * extension is available, it will be move there.
  723. */
  724. dmxInitFonts();
  725. /* Initialize the render extension */
  726. if (!noRenderExtension)
  727. dmxInitRender();
  728. /* Initialized things that need timer hooks */
  729. dmxStatInit();
  730. dmxSyncInit(); /* Calls RegisterBlockAndWakeupHandlers */
  731. }
  732. /* RATS: Assuming the fp string (which comes from the command-line argv
  733. vector) is NULL-terminated, the buffer is large enough for the
  734. strcpy. */
  735. static void
  736. dmxSetDefaultFontPath(const char *fp)
  737. {
  738. if (dmxFontPath) {
  739. int fplen = strlen(fp) + 1;
  740. int len = strlen(dmxFontPath);
  741. dmxFontPath = realloc(dmxFontPath, len + fplen + 1);
  742. dmxFontPath[len] = ',';
  743. strncpy(&dmxFontPath[len + 1], fp, fplen);
  744. }
  745. else {
  746. dmxFontPath = strdup(fp);
  747. }
  748. defaultFontPath = dmxFontPath;
  749. }
  750. /** This function is called in Xserver/os/utils.c from \a AbortServer().
  751. * We must ensure that backend and console state is restored in the
  752. * event the server shutdown wasn't clean. */
  753. void
  754. AbortDDX(enum ExitCode error)
  755. {
  756. int i;
  757. for (i = 0; i < dmxNumScreens; i++) {
  758. DMXScreenInfo *dmxScreen = &dmxScreens[i];
  759. if (dmxScreen->beDisplay)
  760. XCloseDisplay(dmxScreen->beDisplay);
  761. dmxScreen->beDisplay = NULL;
  762. }
  763. }
  764. #ifdef DDXBEFORERESET
  765. void
  766. ddxBeforeReset(void)
  767. {
  768. }
  769. #endif
  770. /** This function is called in Xserver/dix/main.c from \a main() when
  771. * dispatchException & DE_TERMINATE (which is the only way to exit the
  772. * main loop without an interruption. */
  773. void
  774. ddxGiveUp(enum ExitCode error)
  775. {
  776. AbortDDX(error);
  777. }
  778. /** This function is called in Xserver/os/osinit.c from \a OsInit(). */
  779. void
  780. OsVendorInit(void)
  781. {
  782. }
  783. /** This function is called in Xserver/os/utils.c from \a FatalError()
  784. * and \a VFatalError(). (Note that setting the function pointer \a
  785. * OsVendorVErrorFProc will cause \a VErrorF() (which is called by the
  786. * two routines mentioned here, as well as by others) to use the
  787. * referenced routine instead of \a vfprintf().) */
  788. void
  789. OsVendorFatalError(const char *f, va_list args)
  790. {
  791. }
  792. /** Process our command line arguments. */
  793. int
  794. ddxProcessArgument(int argc, char *argv[], int i)
  795. {
  796. int retval = 0;
  797. if (!strcmp(argv[i], "-display")) {
  798. if (++i < argc)
  799. dmxConfigStoreDisplay(argv[i]);
  800. retval = 2;
  801. }
  802. else if (!strcmp(argv[i], "-inputfrom") || !strcmp(argv[i], "-input")) {
  803. if (++i < argc)
  804. dmxConfigStoreInput(argv[i]);
  805. retval = 2;
  806. }
  807. else if (!strcmp(argv[i], "-xinputfrom") || !strcmp(argv[i], "-xinput")) {
  808. if (++i < argc)
  809. dmxConfigStoreXInput(argv[i]);
  810. retval = 2;
  811. }
  812. else if (!strcmp(argv[i], "-noshadowfb")) {
  813. retval = 1;
  814. }
  815. else if (!strcmp(argv[i], "-nomulticursor")) {
  816. dmxCursorNoMulti();
  817. retval = 1;
  818. }
  819. else if (!strcmp(argv[i], "-shadowfb")) {
  820. retval = 1;
  821. }
  822. else if (!strcmp(argv[i], "-configfile")) {
  823. if (++i < argc)
  824. dmxConfigStoreFile(argv[i]);
  825. retval = 2;
  826. }
  827. else if (!strcmp(argv[i], "-config")) {
  828. if (++i < argc)
  829. dmxConfigStoreConfig(argv[i]);
  830. retval = 2;
  831. }
  832. else if (!strcmp(argv[i], "-fontpath")) {
  833. if (++i < argc)
  834. dmxSetDefaultFontPath(argv[i]);
  835. retval = 2;
  836. }
  837. else if (!strcmp(argv[i], "-stat")) {
  838. if ((i += 2) < argc)
  839. dmxStatActivate(argv[i - 1], argv[i]);
  840. retval = 3;
  841. }
  842. else if (!strcmp(argv[i], "-syncbatch")) {
  843. if (++i < argc)
  844. dmxSyncActivate(argv[i]);
  845. retval = 2;
  846. }
  847. else if (!strcmp(argv[i], "-nooffscreenopt")) {
  848. dmxOffScreenOpt = FALSE;
  849. retval = 1;
  850. }
  851. else if (!strcmp(argv[i], "-nosubdivprims")) {
  852. dmxSubdividePrimitives = FALSE;
  853. retval = 1;
  854. }
  855. else if (!strcmp(argv[i], "-nowindowopt")) {
  856. dmxLazyWindowCreation = FALSE;
  857. retval = 1;
  858. }
  859. else if (!strcmp(argv[i], "-noxkb")) {
  860. dmxUseXKB = FALSE;
  861. retval = 1;
  862. }
  863. else if (!strcmp(argv[i], "-depth")) {
  864. if (++i < argc)
  865. dmxDepth = atoi(argv[i]);
  866. retval = 2;
  867. }
  868. else if (!strcmp(argv[i], "-norender")) {
  869. noRenderExtension = TRUE;
  870. retval = 1;
  871. #ifdef GLXEXT
  872. }
  873. else if (!strcmp(argv[i], "-noglxproxy")) {
  874. dmxGLXProxy = FALSE;
  875. retval = 1;
  876. }
  877. else if (!strcmp(argv[i], "-noglxswapgroup")) {
  878. dmxGLXSwapGroupSupport = FALSE;
  879. retval = 1;
  880. }
  881. else if (!strcmp(argv[i], "-glxsyncswap")) {
  882. dmxGLXSyncSwap = TRUE;
  883. retval = 1;
  884. }
  885. else if (!strcmp(argv[i], "-glxfinishswap")) {
  886. dmxGLXFinishSwap = TRUE;
  887. retval = 1;
  888. #endif
  889. }
  890. else if (!strcmp(argv[i], "-ignorebadfontpaths")) {
  891. dmxIgnoreBadFontPaths = TRUE;
  892. retval = 1;
  893. }
  894. else if (!strcmp(argv[i], "-addremovescreens")) {
  895. dmxAddRemoveScreens = TRUE;
  896. retval = 1;
  897. }
  898. else if (!strcmp(argv[i], "-param")) {
  899. if ((i += 2) < argc) {
  900. if (!strcasecmp(argv[i - 1], "xkbrules"))
  901. dmxConfigSetXkbRules(argv[i]);
  902. else if (!strcasecmp(argv[i - 1], "xkbmodel"))
  903. dmxConfigSetXkbModel(argv[i]);
  904. else if (!strcasecmp(argv[i - 1], "xkblayout"))
  905. dmxConfigSetXkbLayout(argv[i]);
  906. else if (!strcasecmp(argv[i - 1], "xkbvariant"))
  907. dmxConfigSetXkbVariant(argv[i]);
  908. else if (!strcasecmp(argv[i - 1], "xkboptions"))
  909. dmxConfigSetXkbOptions(argv[i]);
  910. else
  911. dmxLog(dmxWarning,
  912. "-param requires: XkbRules, XkbModel, XkbLayout,"
  913. " XkbVariant, or XkbOptions\n");
  914. }
  915. retval = 3;
  916. }
  917. if (!serverGeneration)
  918. dmxConfigSetMaxScreens();
  919. return retval;
  920. }
  921. /** Provide succinct usage information for the DMX server. */
  922. void
  923. ddxUseMsg(void)
  924. {
  925. ErrorF("\n\nDevice Dependent Usage:\n");
  926. ErrorF("-display string Specify the back-end display(s)\n");
  927. ErrorF("-input string Specify input source for core device\n");
  928. ErrorF("-xinput string Specify input source for XInput device\n");
  929. ErrorF("-shadowfb Enable shadow frame buffer\n");
  930. ErrorF("-configfile file Read from a configuration file\n");
  931. ErrorF("-config config Select a specific configuration\n");
  932. ErrorF("-nomulticursor Turn of multiple cursor support\n");
  933. ErrorF("-fontpath Sets the default font path\n");
  934. ErrorF("-stat inter scrns Print out performance statistics\n");
  935. ErrorF("-syncbatch inter Set interval for XSync batching\n");
  936. ErrorF("-nooffscreenopt Disable offscreen optimization\n");
  937. ErrorF("-nosubdivprims Disable primitive subdivision\n");
  938. ErrorF(" optimization\n");
  939. ErrorF("-nowindowopt Disable lazy window creation optimization\n");
  940. ErrorF("-noxkb Disable use of the XKB extension with\n");
  941. ErrorF(" backend displays (cf. -kb).\n");
  942. ErrorF("-depth Specify the default root window depth\n");
  943. ErrorF("-norender Disable RENDER extension support\n");
  944. #ifdef GLXEXT
  945. ErrorF("-noglxproxy Disable GLX Proxy\n");
  946. ErrorF("-noglxswapgroup Disable swap group and swap barrier\n");
  947. ErrorF(" extensions in GLX proxy\n");
  948. ErrorF("-glxsyncswap Force XSync after swap buffers\n");
  949. ErrorF("-glxfinishswap Force glFinish after swap buffers\n");
  950. #endif
  951. ErrorF
  952. ("-ignorebadfontpaths Ignore bad font paths during initialization\n");
  953. ErrorF("-addremovescreens Enable dynamic screen addition/removal\n");
  954. ErrorF("-param ... Specify configuration parameters (e.g.,\n");
  955. ErrorF(" XkbRules, XkbModel, XkbLayout, etc.)\n");
  956. ErrorF("\n");
  957. ErrorF(" If the -input string matches a -display string, then input\n"
  958. " is taken from that backend display. (XInput cannot be taken\n"
  959. " from a backend display.) Placing \",console\" after the\n"
  960. " display name will force a console window to be opened on\n"
  961. " that display in addition to the backend input. This is\n"
  962. " useful if the backend window does not cover the whole\n"
  963. " physical display.\n\n");
  964. ErrorF(" Otherwise, if the -input or -xinput string specifies another\n"
  965. " X display, then a console window will be created on that\n"
  966. " display. Placing \",windows\" or \",nowindows\" after the\n"
  967. " display name will control the display of window outlines in\n"
  968. " the console.\n\n");
  969. ErrorF(" -input or -xinput dummy specifies no input.\n");
  970. ErrorF(" -input or -xinput local specifies the use of a raw keyboard,\n"
  971. " mouse, or other (extension) device:\n"
  972. " -input local,kbd,ps2 will use a ps2 mouse\n"
  973. " -input local,kbd,ms will use a serial mouse\n"
  974. " -input local,usb-kbd,usb-mou will use USB devices \n"
  975. " -xinput local,usb-oth will use a non-mouse and\n"
  976. " non-keyboard USB device with XInput\n\n");
  977. ErrorF(" Special Keys:\n");
  978. ErrorF(" Ctrl-Alt-g Server grab/ungrab (console only)\n");
  979. ErrorF(" Ctrl-Alt-f Fine (1-pixel) mouse mode (console only)\n");
  980. ErrorF(" Ctrl-Alt-q Quit (core devices only)\n");
  981. ErrorF(" Ctrl-Alt-F* Switch to VC (local only)\n");
  982. }