xref: /OK3568_Linux_fs/external/xserver/hw/dmx/dmxinit.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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. */
79 int dmxNumScreens;
80 DMXScreenInfo *dmxScreens;
81 
82 int dmxNumInputs;
83 DMXInputInfo *dmxInputs;
84 
85 XErrorEvent dmxLastErrorEvent;
86 Bool dmxErrorOccurred = FALSE;
87 
88 char *dmxFontPath = NULL;
89 
90 Bool dmxOffScreenOpt = TRUE;
91 
92 Bool dmxSubdividePrimitives = TRUE;
93 
94 Bool dmxLazyWindowCreation = TRUE;
95 
96 Bool dmxUseXKB = TRUE;
97 
98 int dmxDepth = 0;
99 
100 #ifndef GLXEXT
101 static Bool dmxGLXProxy = FALSE;
102 #else
103 Bool dmxGLXProxy = TRUE;
104 
105 Bool dmxGLXSwapGroupSupport = TRUE;
106 
107 Bool dmxGLXSyncSwap = FALSE;
108 
109 Bool dmxGLXFinishSwap = FALSE;
110 #endif
111 
112 RESTYPE RRProviderType = 0;
113 
114 Bool dmxIgnoreBadFontPaths = FALSE;
115 
116 Bool 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 */
121 static int
dmxErrorHandler(Display * dpy,XErrorEvent * ev)122 dmxErrorHandler(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                (unsigned int) ev->resourceid);
168         break;
169     case BadAtom:
170         dmxLog(dmxWarning, "                 AtomID:       0x%x\n",
171                (unsigned int) ev->resourceid);
172         break;
173     default:
174         dmxLog(dmxWarning, "                 ResourceID:   0x%x\n",
175                (unsigned int) ev->resourceid);
176         break;
177     }
178 
179     /* Provide serial number information */
180     dmxLog(dmxWarning, "                 Failed serial number:  %d\n",
181            (unsigned int) ev->serial);
182     dmxLog(dmxWarning, "                 Current serial number: %d\n",
183            (unsigned int) dpy->request);
184     return 0;
185 }
186 
187 #ifdef GLXEXT
188 static int
dmxNOPErrorHandler(Display * dpy,XErrorEvent * ev)189 dmxNOPErrorHandler(Display * dpy, XErrorEvent * ev)
190 {
191     return 0;
192 }
193 #endif
194 
195 Bool
dmxOpenDisplay(DMXScreenInfo * dmxScreen)196 dmxOpenDisplay(DMXScreenInfo * dmxScreen)
197 {
198     if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->name)))
199         return FALSE;
200 
201     dmxPropertyDisplay(dmxScreen);
202     return TRUE;
203 }
204 
205 void
dmxSetErrorHandler(DMXScreenInfo * dmxScreen)206 dmxSetErrorHandler(DMXScreenInfo * dmxScreen)
207 {
208     XSetErrorHandler(dmxErrorHandler);
209 }
210 
211 static void
dmxPrintScreenInfo(DMXScreenInfo * dmxScreen)212 dmxPrintScreenInfo(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 
296 void
dmxGetScreenAttribs(DMXScreenInfo * dmxScreen)297 dmxGetScreenAttribs(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 
382 Bool
dmxGetVisualInfo(DMXScreenInfo * dmxScreen)383 dmxGetVisualInfo(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 
435 void
dmxGetColormaps(DMXScreenInfo * dmxScreen)436 dmxGetColormaps(DMXScreenInfo * dmxScreen)
437 {
438     int i;
439 
440     dmxScreen->beNumDefColormaps = dmxScreen->beNumVisuals;
441     dmxScreen->beDefColormaps = xallocarray(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 
456 void
dmxGetPixmapFormats(DMXScreenInfo * dmxScreen)457 dmxGetPixmapFormats(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 
468 static Bool
dmxSetPixmapFormats(ScreenInfo * pScreenInfo,DMXScreenInfo * dmxScreen)469 dmxSetPixmapFormats(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 
500 void
dmxCheckForWM(DMXScreenInfo * dmxScreen)501 dmxCheckForWM(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 */
517 static void
dmxDisplayInit(DMXScreenInfo * dmxScreen)518 dmxDisplayInit(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 
dmxAddExtensions(void)535 static void dmxAddExtensions(void)
536 {
537     const ExtensionModule dmxExtensions[] = {
538         { DMXExtensionInit, DMX_EXTENSION_NAME, NULL },
539     };
540 
541     LoadExtensionList(dmxExtensions, ARRAY_SIZE(dmxExtensions), TRUE);
542 }
543 
544 /** This routine is called in Xserver/dix/main.c from \a main(). */
545 void
InitOutput(ScreenInfo * pScreenInfo,int argc,char * argv[])546 InitOutput(ScreenInfo * pScreenInfo, int argc, char *argv[])
547 {
548     int i;
549     static unsigned long dmxGeneration = 0;
550 
551     if (dmxGeneration != serverGeneration) {
552         int vendrel = VENDOR_RELEASE;
553         int major, minor, year, month, day;
554 
555         dmxGeneration = serverGeneration;
556 
557         major = vendrel / 100000000;
558         vendrel -= major * 100000000;
559         minor = vendrel / 1000000;
560         vendrel -= minor * 1000000;
561         year = vendrel / 10000;
562         vendrel -= year * 10000;
563         month = vendrel / 100;
564         vendrel -= month * 100;
565         day = vendrel;
566 
567         /* Add other epoch tests here */
568         if (major > 0 && minor > 0)
569             year += 2000;
570 
571         dmxLog(dmxInfo, "Generation:         %lu\n", dmxGeneration);
572         dmxLog(dmxInfo, "DMX version:        %d.%d.%02d%02d%02d (%s)\n",
573                major, minor, year, month, day, VENDOR_STRING);
574 
575         SetVendorRelease(VENDOR_RELEASE);
576         SetVendorString(VENDOR_STRING);
577 
578         dmxLog(dmxInfo, "MAXSCREENS:         %d\n", MAXSCREENS);
579 
580         for (i = 0; i < dmxNumScreens; i++) {
581             if (dmxScreens[i].beDisplay)
582                 dmxLog(dmxWarning, "Display \"%s\" still open\n",
583                        dmxScreens[i].name);
584             dmxStatFree(dmxScreens[i].stat);
585             dmxScreens[i].stat = NULL;
586         }
587         for (i = 0; i < dmxNumInputs; i++)
588             dmxInputFree(&dmxInputs[i]);
589         free(dmxScreens);
590         free(dmxInputs);
591         dmxScreens = NULL;
592         dmxInputs = NULL;
593         dmxNumScreens = 0;
594         dmxNumInputs = 0;
595     }
596 
597     /* Make sure that the command-line arguments are sane. */
598     if (dmxAddRemoveScreens && dmxGLXProxy) {
599         /* Currently it is not possible to support GLX and Render
600          * extensions with dynamic screen addition/removal due to the
601          * state that each extension keeps, which cannot be restored. */
602         dmxLog(dmxWarning,
603                "GLX Proxy and Render extensions do not yet support dynamic\n");
604         dmxLog(dmxWarning,
605                "screen addition and removal.  Please specify -noglxproxy\n");
606         dmxLog(dmxWarning,
607                "and -norender on the command line or in the configuration\n");
608         dmxLog(dmxWarning,
609                "file to disable these two extensions if you wish to use\n");
610         dmxLog(dmxWarning,
611                "the dynamic addition and removal of screens support.\n");
612         dmxLog(dmxFatal,
613                "Dynamic screen addition/removal error (see above).\n");
614     }
615 
616     /* ddxProcessArgument has been called at this point, but any data
617      * from the configuration file has not been applied.  Do so, and be
618      * sure we have at least one back-end display. */
619     dmxConfigConfigure();
620     if (!dmxNumScreens)
621         dmxLog(dmxFatal, "InitOutput: no back-end displays found\n");
622     if (!dmxNumInputs)
623         dmxLog(dmxInfo, "InitOutput: no inputs found\n");
624 
625     /* Disable lazy window creation optimization if offscreen
626      * optimization is disabled */
627     if (!dmxOffScreenOpt && dmxLazyWindowCreation) {
628         dmxLog(dmxInfo,
629                "InitOutput: Disabling lazy window creation optimization\n");
630         dmxLog(dmxInfo,
631                "            since it requires the offscreen optimization\n");
632         dmxLog(dmxInfo, "            to function properly.\n");
633         dmxLazyWindowCreation = FALSE;
634     }
635 
636     /* Open each display and gather information about it. */
637     for (i = 0; i < dmxNumScreens; i++)
638         dmxDisplayInit(&dmxScreens[i]);
639 
640 #ifdef PANORAMIX
641     /* Register a Xinerama callback which will run from within
642      * PanoramiXCreateConnectionBlock.  We can use the callback to
643      * determine if Xinerama is loaded and to check the visuals
644      * determined by PanoramiXConsolidate. */
645     XineramaRegisterConnectionBlockCallback(dmxConnectionBlockCallback);
646 #endif
647 
648     /* Since we only have a single screen thus far, we only need to set
649        the pixmap formats to match that screen.  FIXME: this isn't true. */
650     if (!dmxSetPixmapFormats(pScreenInfo, &dmxScreens[0]))
651         return;
652 
653     /* Might want to install a signal handler to allow cleaning up after
654      * unexpected signals.  The DIX/OS layer already handles SIGINT and
655      * SIGTERM, so everything is OK for expected signals. --DD
656      *
657      * SIGHUP, SIGINT, and SIGTERM are trapped in os/connection.c
658      * SIGQUIT is another common signal that is sent from the keyboard.
659      * Trap it here, to ensure that the keyboard modifier map and other
660      * state for the input devices are restored. (This makes the
661      * behavior of SIGQUIT somewhat unexpected, since it will be the
662      * same as the behavior of SIGINT.  However, leaving the modifier
663      * map of the input devices empty is even more unexpected.) --RF
664      */
665     OsSignal(SIGQUIT, GiveUp);
666 
667 #ifdef GLXEXT
668     /* Check if GLX extension exists on all back-end servers */
669     for (i = 0; i < dmxNumScreens; i++)
670         noGlxExtension |= (dmxScreens[i].glxMajorOpcode == 0);
671 #endif
672 
673     if (serverGeneration == 1)
674         dmxAddExtensions();
675 
676     /* Tell dix layer about the backend displays */
677     for (i = 0; i < dmxNumScreens; i++) {
678 
679 #ifdef GLXEXT
680         if (!noGlxExtension) {
681             /*
682              * Builds GLX configurations from the list of visuals
683              * supported by the back-end server, and give that
684              * configuration list to the glx layer - so that he will
685              * build the visuals accordingly.
686              */
687 
688             DMXScreenInfo *dmxScreen = &dmxScreens[i];
689             __GLXvisualConfig *configs = NULL;
690             dmxGlxVisualPrivate **configprivs = NULL;
691             int nconfigs = 0;
692             int (*oldErrorHandler) (Display *, XErrorEvent *);
693 
694             /* Catch errors if when using an older GLX w/o FBconfigs */
695             oldErrorHandler = XSetErrorHandler(dmxNOPErrorHandler);
696 
697             /* Get FBConfigs of the back-end server */
698             dmxScreen->fbconfigs = GetGLXFBConfigs(dmxScreen->beDisplay,
699                                                    dmxScreen->glxMajorOpcode,
700                                                    &dmxScreen->numFBConfigs);
701 
702             XSetErrorHandler(oldErrorHandler);
703 
704             dmxScreen->glxVisuals =
705                 GetGLXVisualConfigs(dmxScreen->beDisplay,
706                                     DefaultScreen(dmxScreen->beDisplay),
707                                     &dmxScreen->numGlxVisuals);
708 
709             if (dmxScreen->fbconfigs) {
710                 configs =
711                     GetGLXVisualConfigsFromFBConfigs(dmxScreen->fbconfigs,
712                                                      dmxScreen->numFBConfigs,
713                                                      dmxScreen->beVisuals,
714                                                      dmxScreen->beNumVisuals,
715                                                      dmxScreen->glxVisuals,
716                                                      dmxScreen->numGlxVisuals,
717                                                      &nconfigs);
718             }
719             else {
720                 configs = dmxScreen->glxVisuals;
721                 nconfigs = dmxScreen->numGlxVisuals;
722             }
723 
724             configprivs = xallocarray(nconfigs, sizeof(dmxGlxVisualPrivate *));
725 
726             if (configs != NULL && configprivs != NULL) {
727                 int j;
728 
729                 /* Initialize our private info for each visual
730                  * (currently only x_visual_depth and x_visual_class)
731                  */
732                 for (j = 0; j < nconfigs; j++) {
733 
734                     configprivs[j] = (dmxGlxVisualPrivate *)
735                         malloc(sizeof(dmxGlxVisualPrivate));
736                     configprivs[j]->x_visual_depth = 0;
737                     configprivs[j]->x_visual_class = 0;
738 
739                     /* Find the visual depth */
740                     if (configs[j].vid > 0) {
741                         int k;
742 
743                         for (k = 0; k < dmxScreen->beNumVisuals; k++) {
744                             if (dmxScreen->beVisuals[k].visualid ==
745                                 configs[j].vid) {
746                                 configprivs[j]->x_visual_depth =
747                                     dmxScreen->beVisuals[k].depth;
748                                 configprivs[j]->x_visual_class =
749                                     dmxScreen->beVisuals[k].class;
750                                 break;
751                             }
752                         }
753                     }
754                 }
755 
756                 XFlush(dmxScreen->beDisplay);
757             }
758         }
759 #endif                          /* GLXEXT */
760 
761         AddScreen(dmxScreenInit, argc, argv);
762     }
763 
764     /* Compute origin information. */
765     dmxInitOrigins();
766 
767     /* Compute overlap information. */
768     dmxInitOverlap();
769 
770     /* Make sure there is a global width/height available */
771     dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
772 
773     /* FIXME: The following is temporarily placed here.  When the DMX
774      * extension is available, it will be move there.
775      */
776     dmxInitFonts();
777 
778     /* Initialize the render extension */
779     if (!noRenderExtension)
780         dmxInitRender();
781 
782     /* Initialized things that need timer hooks */
783     dmxStatInit();
784     dmxSyncInit();              /* Calls RegisterBlockAndWakeupHandlers */
785 }
786 
787 /* RATS: Assuming the fp string (which comes from the command-line argv
788          vector) is NULL-terminated, the buffer is large enough for the
789          strcpy. */
790 static void
dmxSetDefaultFontPath(const char * fp)791 dmxSetDefaultFontPath(const char *fp)
792 {
793     if (dmxFontPath) {
794         int fplen = strlen(fp) + 1;
795         int len = strlen(dmxFontPath);
796 
797         dmxFontPath = realloc(dmxFontPath, len + fplen + 1);
798         dmxFontPath[len] = ',';
799         strncpy(&dmxFontPath[len + 1], fp, fplen);
800     }
801     else {
802         dmxFontPath = strdup(fp);
803     }
804 
805     defaultFontPath = dmxFontPath;
806 }
807 
808 /** This function is called in Xserver/os/utils.c from \a AbortServer().
809  * We must ensure that backend and console state is restored in the
810  * event the server shutdown wasn't clean. */
811 void
AbortDDX(enum ExitCode error)812 AbortDDX(enum ExitCode error)
813 {
814     int i;
815 
816     for (i = 0; i < dmxNumScreens; i++) {
817         DMXScreenInfo *dmxScreen = &dmxScreens[i];
818 
819         if (dmxScreen->beDisplay)
820             XCloseDisplay(dmxScreen->beDisplay);
821         dmxScreen->beDisplay = NULL;
822     }
823 }
824 
825 #ifdef DDXBEFORERESET
826 void
ddxBeforeReset(void)827 ddxBeforeReset(void)
828 {
829 }
830 #endif
831 
832 /** This function is called in Xserver/dix/main.c from \a main() when
833  * dispatchException & DE_TERMINATE (which is the only way to exit the
834  * main loop without an interruption. */
835 void
ddxGiveUp(enum ExitCode error)836 ddxGiveUp(enum ExitCode error)
837 {
838     AbortDDX(error);
839 }
840 
841 #if INPUTTHREAD
842 /** This function is called in Xserver/os/inputthread.c when starting
843     the input thread. */
844 void
ddxInputThreadInit(void)845 ddxInputThreadInit(void)
846 {
847 }
848 #endif
849 
850 /** This function is called in Xserver/os/osinit.c from \a OsInit(). */
851 void
OsVendorInit(void)852 OsVendorInit(void)
853 {
854 }
855 
856 /** This function is called in Xserver/os/utils.c from \a FatalError()
857  * and \a VFatalError().  (Note that setting the function pointer \a
858  * OsVendorVErrorFProc will cause \a VErrorF() (which is called by the
859  * two routines mentioned here, as well as by others) to use the
860  * referenced routine instead of \a vfprintf().) */
861 void
OsVendorFatalError(const char * f,va_list args)862 OsVendorFatalError(const char *f, va_list args)
863 {
864 }
865 
866 /** Process our command line arguments. */
867 int
ddxProcessArgument(int argc,char * argv[],int i)868 ddxProcessArgument(int argc, char *argv[], int i)
869 {
870     int retval = 0;
871 
872     if (!strcmp(argv[i], "-display")) {
873         if (++i < argc)
874             dmxConfigStoreDisplay(argv[i]);
875         retval = 2;
876     }
877     else if (!strcmp(argv[i], "-inputfrom") || !strcmp(argv[i], "-input")) {
878         if (++i < argc)
879             dmxConfigStoreInput(argv[i]);
880         retval = 2;
881     }
882     else if (!strcmp(argv[i], "-xinputfrom") || !strcmp(argv[i], "-xinput")) {
883         if (++i < argc)
884             dmxConfigStoreXInput(argv[i]);
885         retval = 2;
886     }
887     else if (!strcmp(argv[i], "-noshadowfb")) {
888         retval = 1;
889     }
890     else if (!strcmp(argv[i], "-nomulticursor")) {
891         dmxCursorNoMulti();
892         retval = 1;
893     }
894     else if (!strcmp(argv[i], "-shadowfb")) {
895         retval = 1;
896     }
897     else if (!strcmp(argv[i], "-configfile")) {
898         if (++i < argc)
899             dmxConfigStoreFile(argv[i]);
900         retval = 2;
901     }
902     else if (!strcmp(argv[i], "-config")) {
903         if (++i < argc)
904             dmxConfigStoreConfig(argv[i]);
905         retval = 2;
906     }
907     else if (!strcmp(argv[i], "-fontpath")) {
908         if (++i < argc)
909             dmxSetDefaultFontPath(argv[i]);
910         retval = 2;
911     }
912     else if (!strcmp(argv[i], "-stat")) {
913         if ((i += 2) < argc)
914             dmxStatActivate(argv[i - 1], argv[i]);
915         retval = 3;
916     }
917     else if (!strcmp(argv[i], "-syncbatch")) {
918         if (++i < argc)
919             dmxSyncActivate(argv[i]);
920         retval = 2;
921     }
922     else if (!strcmp(argv[i], "-nooffscreenopt")) {
923         dmxOffScreenOpt = FALSE;
924         retval = 1;
925     }
926     else if (!strcmp(argv[i], "-nosubdivprims")) {
927         dmxSubdividePrimitives = FALSE;
928         retval = 1;
929     }
930     else if (!strcmp(argv[i], "-nowindowopt")) {
931         dmxLazyWindowCreation = FALSE;
932         retval = 1;
933     }
934     else if (!strcmp(argv[i], "-noxkb")) {
935         dmxUseXKB = FALSE;
936         retval = 1;
937     }
938     else if (!strcmp(argv[i], "-depth")) {
939         if (++i < argc)
940             dmxDepth = atoi(argv[i]);
941         retval = 2;
942     }
943     else if (!strcmp(argv[i], "-norender")) {
944         noRenderExtension = TRUE;
945         retval = 1;
946 #ifdef GLXEXT
947     }
948     else if (!strcmp(argv[i], "-noglxproxy")) {
949         dmxGLXProxy = FALSE;
950         retval = 1;
951     }
952     else if (!strcmp(argv[i], "-noglxswapgroup")) {
953         dmxGLXSwapGroupSupport = FALSE;
954         retval = 1;
955     }
956     else if (!strcmp(argv[i], "-glxsyncswap")) {
957         dmxGLXSyncSwap = TRUE;
958         retval = 1;
959     }
960     else if (!strcmp(argv[i], "-glxfinishswap")) {
961         dmxGLXFinishSwap = TRUE;
962         retval = 1;
963 #endif
964     }
965     else if (!strcmp(argv[i], "-ignorebadfontpaths")) {
966         dmxIgnoreBadFontPaths = TRUE;
967         retval = 1;
968     }
969     else if (!strcmp(argv[i], "-addremovescreens")) {
970         dmxAddRemoveScreens = TRUE;
971         retval = 1;
972     }
973     else if (!strcmp(argv[i], "-param")) {
974         if ((i += 2) < argc) {
975             if (!strcasecmp(argv[i - 1], "xkbrules"))
976                 dmxConfigSetXkbRules(argv[i]);
977             else if (!strcasecmp(argv[i - 1], "xkbmodel"))
978                 dmxConfigSetXkbModel(argv[i]);
979             else if (!strcasecmp(argv[i - 1], "xkblayout"))
980                 dmxConfigSetXkbLayout(argv[i]);
981             else if (!strcasecmp(argv[i - 1], "xkbvariant"))
982                 dmxConfigSetXkbVariant(argv[i]);
983             else if (!strcasecmp(argv[i - 1], "xkboptions"))
984                 dmxConfigSetXkbOptions(argv[i]);
985             else
986                 dmxLog(dmxWarning,
987                        "-param requires: XkbRules, XkbModel, XkbLayout,"
988                        " XkbVariant, or XkbOptions\n");
989         }
990         retval = 3;
991     }
992     if (!serverGeneration)
993         dmxConfigSetMaxScreens();
994     return retval;
995 }
996 
997 /** Provide succinct usage information for the DMX server. */
998 void
ddxUseMsg(void)999 ddxUseMsg(void)
1000 {
1001     ErrorF("\n\nDevice Dependent Usage:\n");
1002     ErrorF("-display string      Specify the back-end display(s)\n");
1003     ErrorF("-input string        Specify input source for core device\n");
1004     ErrorF("-xinput string       Specify input source for XInput device\n");
1005     ErrorF("-shadowfb            Enable shadow frame buffer\n");
1006     ErrorF("-configfile file     Read from a configuration file\n");
1007     ErrorF("-config config       Select a specific configuration\n");
1008     ErrorF("-nomulticursor       Turn of multiple cursor support\n");
1009     ErrorF("-fontpath            Sets the default font path\n");
1010     ErrorF("-stat inter scrns    Print out performance statistics\n");
1011     ErrorF("-syncbatch inter     Set interval for XSync batching\n");
1012     ErrorF("-nooffscreenopt      Disable offscreen optimization\n");
1013     ErrorF("-nosubdivprims       Disable primitive subdivision\n");
1014     ErrorF("                     optimization\n");
1015     ErrorF("-nowindowopt         Disable lazy window creation optimization\n");
1016     ErrorF("-noxkb               Disable use of the XKB extension with\n");
1017     ErrorF("                     backend displays (cf. -kb).\n");
1018     ErrorF("-depth               Specify the default root window depth\n");
1019     ErrorF("-norender            Disable RENDER extension support\n");
1020 #ifdef GLXEXT
1021     ErrorF("-noglxproxy          Disable GLX Proxy\n");
1022     ErrorF("-noglxswapgroup      Disable swap group and swap barrier\n");
1023     ErrorF("                     extensions in GLX proxy\n");
1024     ErrorF("-glxsyncswap         Force XSync after swap buffers\n");
1025     ErrorF("-glxfinishswap       Force glFinish after swap buffers\n");
1026 #endif
1027     ErrorF
1028         ("-ignorebadfontpaths  Ignore bad font paths during initialization\n");
1029     ErrorF("-addremovescreens    Enable dynamic screen addition/removal\n");
1030     ErrorF("-param ...           Specify configuration parameters (e.g.,\n");
1031     ErrorF("                     XkbRules, XkbModel, XkbLayout, etc.)\n");
1032     ErrorF("\n");
1033     ErrorF("    If the -input string matches a -display string, then input\n"
1034            "    is taken from that backend display.  (XInput cannot be taken\n"
1035            "    from a backend display.)  Placing \",console\" after the\n"
1036            "    display name will force a console window to be opened on\n"
1037            "    that display in addition to the backend input.  This is\n"
1038            "    useful if the backend window does not cover the whole\n"
1039            "    physical display.\n\n");
1040 
1041     ErrorF("    Otherwise, if the -input or -xinput string specifies another\n"
1042            "    X display, then a console window will be created on that\n"
1043            "    display.  Placing \",windows\" or \",nowindows\" after the\n"
1044            "    display name will control the display of window outlines in\n"
1045            "    the console.\n\n");
1046 
1047     ErrorF("    -input or -xinput dummy specifies no input.\n");
1048     ErrorF("    -input or -xinput local specifies the use of a raw keyboard,\n"
1049            "    mouse, or other (extension) device:\n"
1050            "        -input local,kbd,ps2 will use a ps2 mouse\n"
1051            "        -input local,kbd,ms  will use a serial mouse\n"
1052            "        -input local,usb-kbd,usb-mou will use USB devices \n"
1053            "        -xinput local,usb-oth will use a non-mouse and\n"
1054            "                non-keyboard USB device with XInput\n\n");
1055 
1056     ErrorF("    Special Keys:\n");
1057     ErrorF("        Ctrl-Alt-g    Server grab/ungrab (console only)\n");
1058     ErrorF("        Ctrl-Alt-f    Fine (1-pixel) mouse mode (console only)\n");
1059     ErrorF("        Ctrl-Alt-q    Quit (core devices only)\n");
1060     ErrorF("        Ctrl-Alt-F*   Switch to VC (local only)\n");
1061 }
1062