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