2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
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:
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.
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
30 * Kevin E. Martin <kem@redhat.com>
31 * David H. Dawes <dawes@xfree86.org>
32 * Rickard E. (Rik) Faith <faith@redhat.com>
37 * Provide expected functions for initialization from the ddx layer and
38 * global variables for the DMX server. */
40 #ifdef HAVE_DMX_CONFIG_H
41 #include <dmx-config.h>
49 #include "dmxscrinit.h"
50 #include "dmxcursor.h"
52 #include "config/dmxconfig.h"
58 #include <X11/Xos.h> /* For gettimeofday */
59 #include <X11/Xmu/SysUtil.h> /* For XmuGetHostname */
60 #include "dixstruct.h"
62 #include "panoramiXsrv.h"
65 #include <signal.h> /* For SIGQUIT */
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>
76 #include <X11/extensions/dmxproto.h>
78 /* Global variables available to all Xserver/hw/dmx routines. */
80 DMXScreenInfo
*dmxScreens
;
83 DMXInputInfo
*dmxInputs
;
85 XErrorEvent dmxLastErrorEvent
;
86 Bool dmxErrorOccurred
= FALSE
;
88 char *dmxFontPath
= NULL
;
90 Bool dmxOffScreenOpt
= TRUE
;
92 Bool dmxSubdividePrimitives
= TRUE
;
94 Bool dmxLazyWindowCreation
= TRUE
;
96 Bool dmxUseXKB
= TRUE
;
101 static Bool dmxGLXProxy
= FALSE
;
103 Bool dmxGLXProxy
= TRUE
;
105 Bool dmxGLXSwapGroupSupport
= TRUE
;
107 Bool dmxGLXSyncSwap
= FALSE
;
109 Bool dmxGLXFinishSwap
= FALSE
;
112 RESTYPE RRProviderType
= 0;
114 Bool dmxIgnoreBadFontPaths
= FALSE
;
116 Bool dmxAddRemoveScreens
= FALSE
;
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 */
122 dmxErrorHandler(Display
* dpy
, XErrorEvent
* ev
)
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
;
131 dmxErrorOccurred
= TRUE
;
132 dmxLastErrorEvent
= *ev
;
134 XGetErrorText(dpy
, ev
->error_code
, buf
, sizeof(buf
));
135 dmxLog(dmxWarning
, "dmxErrorHandler: %s\n", buf
);
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
));
143 for (ext
= dpy
->ext_procs
;
144 ext
&& ext
->codes
.major_opcode
!= ev
->request_code
;
147 strlcpy(buf
, ext
->name
, sizeof(buf
));
151 dmxLog(dmxWarning
, " Major opcode: %d (%s)\n",
152 ev
->request_code
, buf
);
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
);
163 /* Provide value information */
164 switch (ev
->error_code
) {
166 dmxLog(dmxWarning
, " Value: 0x%x\n",
170 dmxLog(dmxWarning
, " AtomID: 0x%x\n",
174 dmxLog(dmxWarning
, " ResourceID: 0x%x\n",
179 /* Provide serial number information */
180 dmxLog(dmxWarning
, " Failed serial number: %d\n",
182 dmxLog(dmxWarning
, " Current serial number: %d\n",
189 dmxNOPErrorHandler(Display
* dpy
, XErrorEvent
* ev
)
196 dmxOpenDisplay(DMXScreenInfo
* dmxScreen
)
198 if (!(dmxScreen
->beDisplay
= XOpenDisplay(dmxScreen
->name
)))
201 dmxPropertyDisplay(dmxScreen
);
206 dmxSetErrorHandler(DMXScreenInfo
* dmxScreen
)
208 XSetErrorHandler(dmxErrorHandler
);
212 dmxPrintScreenInfo(DMXScreenInfo
* dmxScreen
)
214 XWindowAttributes attribs
;
215 int ndepths
= 0, *depths
= NULL
;
217 Display
*dpy
= dmxScreen
->beDisplay
;
218 Screen
*s
= DefaultScreenOfDisplay(dpy
);
219 int scr
= DefaultScreen(dpy
);
221 XGetWindowAttributes(dpy
, DefaultRootWindow(dpy
), &attribs
);
222 if (!(depths
= XListDepths(dpy
, scr
, &ndepths
)))
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
));
233 /* This code based on xdpyinfo.c */
234 int v
= VendorRelease(dpy
);
235 int major
= -1, minor
= -1, patch
= -1, subpatch
= -1;
238 major
= v
/ 100, minor
= (v
/ 10) % 10, patch
= v
% 10;
241 minor
= (v
/ 100) % 10;
242 if (((v
/ 10) % 10) || (v
% 10)) {
243 patch
= (v
/ 10) % 10;
248 else if (v
< 40000000) {
250 minor
= (v
/ 10) % 10;
255 major
= v
/ 10000000;
256 minor
= (v
/ 100000) % 100;
257 patch
= (v
/ 1000) % 100;
261 dmxLogOutput(dmxScreen
, "Vendor release: %d (XFree86 version: %d.%d",
264 dmxLogOutputCont(dmxScreen
, ".%d", patch
);
266 dmxLogOutputCont(dmxScreen
, ".%d", subpatch
);
267 dmxLogOutputCont(dmxScreen
, ")\n");
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");
288 if (dmxScreen
->WMRunningOnBE
) {
289 dmxLogOutputWarning(dmxScreen
,
290 "Window manager running "
291 "-- colormaps not supported\n");
297 dmxGetScreenAttribs(DMXScreenInfo
* dmxScreen
)
299 XWindowAttributes attribs
;
300 Display
*dpy
= dmxScreen
->beDisplay
;
306 XGetWindowAttributes(dpy
, DefaultRootWindow(dpy
), &attribs
);
308 dmxScreen
->beWidth
= attribs
.width
;
309 dmxScreen
->beHeight
= attribs
.height
;
311 /* Fill in missing geometry information */
312 if (dmxScreen
->scrnXSign
< 0) {
313 if (dmxScreen
->scrnWidth
) {
314 dmxScreen
->scrnX
= (attribs
.width
- dmxScreen
->scrnWidth
318 dmxScreen
->scrnWidth
= attribs
.width
- dmxScreen
->scrnX
;
319 dmxScreen
->scrnX
= 0;
322 if (dmxScreen
->scrnYSign
< 0) {
323 if (dmxScreen
->scrnHeight
) {
324 dmxScreen
->scrnY
= (attribs
.height
- dmxScreen
->scrnHeight
328 dmxScreen
->scrnHeight
= attribs
.height
- dmxScreen
->scrnY
;
329 dmxScreen
->scrnY
= 0;
332 if (!dmxScreen
->scrnWidth
)
333 dmxScreen
->scrnWidth
= attribs
.width
- dmxScreen
->scrnX
;
334 if (!dmxScreen
->scrnHeight
)
335 dmxScreen
->scrnHeight
= attribs
.height
- dmxScreen
->scrnY
;
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
;
346 /* FIXME: Get these from the back-end server */
347 dmxScreen
->beXDPI
= 75;
348 dmxScreen
->beYDPI
= 75;
350 dmxScreen
->beDepth
= attribs
.depth
; /* FIXME: verify that this
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. */
358 if (dmxScreen
->beDepth
<= 8)
359 dmxScreen
->beBPP
= 8;
360 else if (dmxScreen
->beDepth
<= 16)
361 dmxScreen
->beBPP
= 16;
363 dmxScreen
->beBPP
= 32;
366 /* get the majorOpcode for the back-end GLX extension */
367 XQueryExtension(dpy
, "GLX", &dmxScreen
->glxMajorOpcode
,
368 &dummy
, &dmxScreen
->glxErrorBase
);
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");
383 dmxGetVisualInfo(DMXScreenInfo
* dmxScreen
)
388 visinfo
.screen
= DefaultScreen(dmxScreen
->beDisplay
);
389 dmxScreen
->beVisuals
= XGetVisualInfo(dmxScreen
->beDisplay
,
391 &visinfo
, &dmxScreen
->beNumVisuals
);
393 dmxScreen
->beDefVisualIndex
= -1;
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
) {
400 if (dmxScreen
->beVisuals
[i
].depth
== dmxDepth
) {
401 dmxScreen
->beDefVisualIndex
= i
;
406 dmxScreen
->beDefVisualIndex
= i
;
411 else if (dmxScreen
->beVisuals
[i
].depth
== dmxDepth
) {
412 dmxScreen
->beDefVisualIndex
= i
;
418 XVisualIDFromVisual(DefaultVisual(dmxScreen
->beDisplay
,
421 for (i
= 0; i
< dmxScreen
->beNumVisuals
; i
++)
422 if (visinfo
.visualid
== dmxScreen
->beVisuals
[i
].visualid
) {
423 dmxScreen
->beDefVisualIndex
= i
;
428 for (i
= 0; i
< dmxScreen
->beNumVisuals
; i
++)
429 dmxLogVisual(dmxScreen
, &dmxScreen
->beVisuals
[i
],
430 (i
== dmxScreen
->beDefVisualIndex
));
432 return dmxScreen
->beDefVisualIndex
>= 0;
436 dmxGetColormaps(DMXScreenInfo
* dmxScreen
)
440 dmxScreen
->beNumDefColormaps
= dmxScreen
->beNumVisuals
;
441 dmxScreen
->beDefColormaps
= malloc(dmxScreen
->beNumDefColormaps
*
442 sizeof(*dmxScreen
->beDefColormaps
));
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
);
450 dmxScreen
->beBlackPixel
= BlackPixel(dmxScreen
->beDisplay
,
451 DefaultScreen(dmxScreen
->beDisplay
));
452 dmxScreen
->beWhitePixel
= WhitePixel(dmxScreen
->beDisplay
,
453 DefaultScreen(dmxScreen
->beDisplay
));
457 dmxGetPixmapFormats(DMXScreenInfo
* dmxScreen
)
459 dmxScreen
->beDepths
=
460 XListDepths(dmxScreen
->beDisplay
, DefaultScreen(dmxScreen
->beDisplay
),
461 &dmxScreen
->beNumDepths
);
463 dmxScreen
->bePixmapFormats
=
464 XListPixmapFormats(dmxScreen
->beDisplay
,
465 &dmxScreen
->beNumPixmapFormats
);
469 dmxSetPixmapFormats(ScreenInfo
* pScreenInfo
, DMXScreenInfo
* dmxScreen
)
471 XPixmapFormatValues
*bePixmapFormat
;
472 PixmapFormatRec
*format
;
475 pScreenInfo
->imageByteOrder
= ImageByteOrder(dmxScreen
->beDisplay
);
476 pScreenInfo
->bitmapScanlineUnit
= BitmapUnit(dmxScreen
->beDisplay
);
477 pScreenInfo
->bitmapScanlinePad
= BitmapPad(dmxScreen
->beDisplay
);
478 pScreenInfo
->bitmapBitOrder
= BitmapBitOrder(dmxScreen
->beDisplay
);
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
];
488 format
->depth
= bePixmapFormat
->depth
;
489 format
->bitsPerPixel
= bePixmapFormat
->bits_per_pixel
;
490 format
->scanlinePad
= bePixmapFormat
->scanline_pad
;
492 pScreenInfo
->numPixmapFormats
++;
501 dmxCheckForWM(DMXScreenInfo
* dmxScreen
)
504 XWindowAttributes xwa
;
506 status
= XGetWindowAttributes(dmxScreen
->beDisplay
,
507 DefaultRootWindow(dmxScreen
->beDisplay
),
509 dmxScreen
->WMRunningOnBE
=
511 ((xwa
.all_event_masks
& SubstructureRedirectMask
) ||
512 (xwa
.all_event_masks
& SubstructureNotifyMask
)));
515 /** Initialize the display and collect relevant information about the
516 * display properties */
518 dmxDisplayInit(DMXScreenInfo
* dmxScreen
)
520 if (!dmxOpenDisplay(dmxScreen
))
522 "dmxOpenDisplay: Unable to open display %s\n", dmxScreen
->name
);
524 dmxSetErrorHandler(dmxScreen
);
525 dmxCheckForWM(dmxScreen
);
526 dmxGetScreenAttribs(dmxScreen
);
528 if (!dmxGetVisualInfo(dmxScreen
))
529 dmxLog(dmxFatal
, "dmxGetVisualInfo: No matching visuals found\n");
531 dmxGetColormaps(dmxScreen
);
532 dmxGetPixmapFormats(dmxScreen
);
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
538 #if !defined(_POSIX_SOURCE)
545 #include <sys/utsname.h>
549 static char buffer
[128];
550 static int initialized
= 0;
553 if (!initialized
++) {
554 memset(buffer
, 0, sizeof(buffer
));
556 snprintf(buffer
, sizeof(buffer
) - 1, "%s %s %s",
557 u
.sysname
, u
.release
, u
.version
);
564 dmxBuildCompiler(void)
566 static char buffer
[128];
567 static int initialized
= 0;
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__
);
582 static char buffer
[128];
583 static int initialized
= 0;
585 if (!initialized
++) {
586 memset(buffer
, 0, sizeof(buffer
));
587 XmuGetHostname(buffer
, sizeof(buffer
) - 1);
592 static void dmxAddExtensions(Bool glxSupported
)
594 const ExtensionModule dmxExtensions
[] = {
595 { DMXExtensionInit
, DMX_EXTENSION_NAME
, NULL
},
597 { GlxExtensionInit
, "GLX", &glxSupported
},
602 for (i
= 0; i
< ARRAY_SIZE(dmxExtensions
); i
++)
603 LoadExtension(&dmxExtensions
[i
], TRUE
);
606 /** This routine is called in Xserver/dix/main.c from \a main(). */
608 InitOutput(ScreenInfo
* pScreenInfo
, int argc
, char *argv
[])
611 static unsigned long dmxGeneration
= 0;
614 static Bool glxSupported
= TRUE
;
616 const Bool glxSupported
= FALSE
;
619 if (dmxGeneration
!= serverGeneration
) {
620 int vendrel
= VENDOR_RELEASE
;
621 int major
, minor
, year
, month
, day
;
623 dmxGeneration
= serverGeneration
;
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;
635 /* Add other epoch tests here */
636 if (major
> 0 && minor
> 0)
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
);
643 SetVendorRelease(VENDOR_RELEASE
);
644 SetVendorString(VENDOR_STRING
);
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());
652 dmxLog(dmxInfo
, "MAXSCREENS: %d\n", MAXSCREENS
);
654 for (i
= 0; i
< dmxNumScreens
; i
++) {
655 if (dmxScreens
[i
].beDisplay
)
656 dmxLog(dmxWarning
, "Display \"%s\" still open\n",
658 dmxStatFree(dmxScreens
[i
].stat
);
659 dmxScreens
[i
].stat
= NULL
;
661 for (i
= 0; i
< dmxNumInputs
; i
++)
662 dmxInputFree(&dmxInputs
[i
]);
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. */
677 "GLX Proxy and Render extensions do not yet support dynamic\n");
679 "screen addition and removal. Please specify -noglxproxy\n");
681 "and -norender on the command line or in the configuration\n");
683 "file to disable these two extensions if you wish to use\n");
685 "the dynamic addition and removal of screens support.\n");
687 "Dynamic screen addition/removal error (see above).\n");
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();
695 dmxLog(dmxFatal
, "InitOutput: no back-end displays found\n");
697 dmxLog(dmxInfo
, "InitOutput: no inputs found\n");
699 /* Disable lazy window creation optimization if offscreen
700 * optimization is disabled */
701 if (!dmxOffScreenOpt
&& dmxLazyWindowCreation
) {
703 "InitOutput: Disabling lazy window creation optimization\n");
705 " since it requires the offscreen optimization\n");
706 dmxLog(dmxInfo
, " to function properly.\n");
707 dmxLazyWindowCreation
= FALSE
;
710 /* Open each display and gather information about it. */
711 for (i
= 0; i
< dmxNumScreens
; i
++)
712 dmxDisplayInit(&dmxScreens
[i
]);
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
);
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]))
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
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
739 OsSignal(SIGQUIT
, GiveUp
);
742 /* Check if GLX extension exists on all back-end servers */
743 for (i
= 0; i
< dmxNumScreens
; i
++)
744 glxSupported
&= (dmxScreens
[i
].glxMajorOpcode
> 0);
747 if (serverGeneration
== 1)
748 dmxAddExtensions(glxSupported
);
750 /* Tell dix layer about the backend displays */
751 for (i
= 0; i
< dmxNumScreens
; i
++) {
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.
762 DMXScreenInfo
*dmxScreen
= &dmxScreens
[i
];
763 __GLXvisualConfig
*configs
= NULL
;
764 dmxGlxVisualPrivate
**configprivs
= NULL
;
766 int (*oldErrorHandler
) (Display
*, XErrorEvent
*);
769 /* Catch errors if when using an older GLX w/o FBconfigs */
770 oldErrorHandler
= XSetErrorHandler(dmxNOPErrorHandler
);
772 /* Get FBConfigs of the back-end server */
773 dmxScreen
->fbconfigs
= GetGLXFBConfigs(dmxScreen
->beDisplay
,
774 dmxScreen
->glxMajorOpcode
,
775 &dmxScreen
->numFBConfigs
);
777 XSetErrorHandler(oldErrorHandler
);
779 dmxScreen
->glxVisuals
=
780 GetGLXVisualConfigs(dmxScreen
->beDisplay
,
781 DefaultScreen(dmxScreen
->beDisplay
),
782 &dmxScreen
->numGlxVisuals
);
784 if (dmxScreen
->fbconfigs
) {
786 GetGLXVisualConfigsFromFBConfigs(dmxScreen
->fbconfigs
,
787 dmxScreen
->numFBConfigs
,
788 dmxScreen
->beVisuals
,
789 dmxScreen
->beNumVisuals
,
790 dmxScreen
->glxVisuals
,
791 dmxScreen
->numGlxVisuals
,
795 configs
= dmxScreen
->glxVisuals
;
796 nconfigs
= dmxScreen
->numGlxVisuals
;
799 configprivs
= malloc(nconfigs
* sizeof(dmxGlxVisualPrivate
*));
801 if (configs
!= NULL
&& configprivs
!= NULL
) {
803 /* Initialize our private info for each visual
804 * (currently only x_visual_depth and x_visual_class)
806 for (i
= 0; i
< nconfigs
; i
++) {
808 configprivs
[i
] = (dmxGlxVisualPrivate
*)
809 malloc(sizeof(dmxGlxVisualPrivate
));
810 configprivs
[i
]->x_visual_depth
= 0;
811 configprivs
[i
]->x_visual_class
= 0;
813 /* Find the visual depth */
814 if (configs
[i
].vid
> 0) {
817 for (j
= 0; j
< dmxScreen
->beNumVisuals
; j
++) {
818 if (dmxScreen
->beVisuals
[j
].visualid
==
820 configprivs
[i
]->x_visual_depth
=
821 dmxScreen
->beVisuals
[j
].depth
;
822 configprivs
[i
]->x_visual_class
=
823 dmxScreen
->beVisuals
[j
].class;
830 XFlush(dmxScreen
->beDisplay
);
835 AddScreen(dmxScreenInit
, argc
, argv
);
838 /* Compute origin information. */
841 /* Compute overlap information. */
844 /* Make sure there is a global width/height available */
845 dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX
);
847 /* FIXME: The following is temporarily placed here. When the DMX
848 * extension is available, it will be move there.
852 /* Initialize the render extension */
853 if (!noRenderExtension
)
856 /* Initialized things that need timer hooks */
858 dmxSyncInit(); /* Calls RegisterBlockAndWakeupHandlers */
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
865 dmxSetDefaultFontPath(const char *fp
)
868 int fplen
= strlen(fp
) + 1;
869 int len
= strlen(dmxFontPath
);
871 dmxFontPath
= realloc(dmxFontPath
, len
+ fplen
+ 1);
872 dmxFontPath
[len
] = ',';
873 strncpy(&dmxFontPath
[len
+ 1], fp
, fplen
);
876 dmxFontPath
= strdup(fp
);
879 defaultFontPath
= dmxFontPath
;
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. */
886 AbortDDX(enum ExitCode error
)
890 for (i
= 0; i
< dmxNumScreens
; i
++) {
891 DMXScreenInfo
*dmxScreen
= &dmxScreens
[i
];
893 if (dmxScreen
->beDisplay
)
894 XCloseDisplay(dmxScreen
->beDisplay
);
895 dmxScreen
->beDisplay
= NULL
;
899 #ifdef DDXBEFORERESET
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. */
910 ddxGiveUp(enum ExitCode error
)
915 /** This function is called in Xserver/os/osinit.c from \a OsInit(). */
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().) */
927 OsVendorFatalError(const char *f
, va_list args
)
931 /** Process our command line arguments. */
933 ddxProcessArgument(int argc
, char *argv
[], int i
)
937 if (!strcmp(argv
[i
], "-display")) {
939 dmxConfigStoreDisplay(argv
[i
]);
942 else if (!strcmp(argv
[i
], "-inputfrom") || !strcmp(argv
[i
], "-input")) {
944 dmxConfigStoreInput(argv
[i
]);
947 else if (!strcmp(argv
[i
], "-xinputfrom") || !strcmp(argv
[i
], "-xinput")) {
949 dmxConfigStoreXInput(argv
[i
]);
952 else if (!strcmp(argv
[i
], "-noshadowfb")) {
955 else if (!strcmp(argv
[i
], "-nomulticursor")) {
959 else if (!strcmp(argv
[i
], "-shadowfb")) {
962 else if (!strcmp(argv
[i
], "-configfile")) {
964 dmxConfigStoreFile(argv
[i
]);
967 else if (!strcmp(argv
[i
], "-config")) {
969 dmxConfigStoreConfig(argv
[i
]);
972 else if (!strcmp(argv
[i
], "-fontpath")) {
974 dmxSetDefaultFontPath(argv
[i
]);
977 else if (!strcmp(argv
[i
], "-stat")) {
979 dmxStatActivate(argv
[i
- 1], argv
[i
]);
982 else if (!strcmp(argv
[i
], "-syncbatch")) {
984 dmxSyncActivate(argv
[i
]);
987 else if (!strcmp(argv
[i
], "-nooffscreenopt")) {
988 dmxOffScreenOpt
= FALSE
;
991 else if (!strcmp(argv
[i
], "-nosubdivprims")) {
992 dmxSubdividePrimitives
= FALSE
;
995 else if (!strcmp(argv
[i
], "-nowindowopt")) {
996 dmxLazyWindowCreation
= FALSE
;
999 else if (!strcmp(argv
[i
], "-noxkb")) {
1003 else if (!strcmp(argv
[i
], "-depth")) {
1005 dmxDepth
= atoi(argv
[i
]);
1008 else if (!strcmp(argv
[i
], "-norender")) {
1009 noRenderExtension
= TRUE
;
1013 else if (!strcmp(argv
[i
], "-noglxproxy")) {
1014 dmxGLXProxy
= FALSE
;
1017 else if (!strcmp(argv
[i
], "-noglxswapgroup")) {
1018 dmxGLXSwapGroupSupport
= FALSE
;
1021 else if (!strcmp(argv
[i
], "-glxsyncswap")) {
1022 dmxGLXSyncSwap
= TRUE
;
1025 else if (!strcmp(argv
[i
], "-glxfinishswap")) {
1026 dmxGLXFinishSwap
= TRUE
;
1030 else if (!strcmp(argv
[i
], "-ignorebadfontpaths")) {
1031 dmxIgnoreBadFontPaths
= TRUE
;
1034 else if (!strcmp(argv
[i
], "-addremovescreens")) {
1035 dmxAddRemoveScreens
= TRUE
;
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
]);
1052 "-param requires: XkbRules, XkbModel, XkbLayout,"
1053 " XkbVariant, or XkbOptions\n");
1057 if (!serverGeneration
)
1058 dmxConfigSetMaxScreens();
1062 /** Provide succinct usage information for the DMX server. */
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");
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");
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");
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");
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");
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");
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");