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