/* * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation on the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* * Authors: * Kevin E. Martin * David H. Dawes * Rickard E. (Rik) Faith * */ /** \file * Provide expected functions for initialization from the ddx layer and * global variables for the DMX server. */ #ifdef HAVE_DMX_CONFIG_H #include #endif #include "dmx.h" #include "dmxinit.h" #include "dmxsync.h" #include "dmxlog.h" #include "dmxinput.h" #include "dmxscrinit.h" #include "dmxcursor.h" #include "dmxfont.h" #include "config/dmxconfig.h" #include "dmxcb.h" #include "dmxprop.h" #include "dmxstat.h" #include "dmxlaunch.h" #include "dmxgrab.h" #include "dmxselection.h" #include "dmxshm.h" #ifdef RENDER #include "dmxpict.h" #endif #ifdef COMPOSITE #include "dmxcomp.h" #endif #include "dmxextension.h" #include /* For gettimeofday */ #include "dixstruct.h" #include "panoramiXsrv.h" #include /* For SIGQUIT */ #include #ifdef GLXEXT #include #include #include "dmx_glxvisuals.h" #include #include extern void GlxSetVisualConfigs( int nconfigs, __GLXvisualConfig *configs, void **configprivs ); #endif /* GLXEXT */ /* Global variables available to all Xserver/hw/dmx routines. */ int dmxNumScreens; DMXScreenInfo *dmxScreens; int dmxNumInputs = 0; DMXInputInfo *dmxInputs; int dmxShadowFB = FALSE; XErrorEvent dmxLastErrorEvent; Bool dmxErrorOccurred = FALSE; char *dmxFontPath = NULL; Bool dmxOffScreenOpt = FALSE; Bool dmxSubdividePrimitives = TRUE; Bool dmxLazyWindowCreation = FALSE; Bool dmxUseXKB = TRUE; int dmxDepth = 0; #ifndef GLXEXT static Bool dmxGLXProxy = FALSE; #else Bool dmxGLXProxy = FALSE; Bool dmxGLXSwapGroupSupport = TRUE; Bool dmxGLXSyncSwap = FALSE; Bool dmxGLXFinishSwap = FALSE; #endif Bool dmxIgnoreBadFontPaths = FALSE; Bool dmxAddRemoveScreens = TRUE; int dmxLaunchIndex = 0; char *dmxLaunchVT = NULL; #ifdef DMXVNC Bool dmxVnc = FALSE; #endif #ifdef RANDR int xRROutputsPerScreen = 2; int xRRCrtcsPerScreen = 2; #endif DMXPropTrans *dmxPropTrans = NULL; int dmxPropTransNum = 0; #ifdef XV char **dmxXvImageFormats = NULL; int dmxXvImageFormatsNum = 0; #endif #include static void dmxSigHandler (int signo) { void *array[64]; size_t size, i; char **strings; ErrorF ("\nBacktrace:\n"); size = backtrace (array, 64); strings = backtrace_symbols (array, size); for (i = 0; i < size; i++) ErrorF ("%d: %s\n", i, strings[i]); free (strings); FatalError ("Caught signal %d. Server aborting\n", signo); } /* dmxErrorHandler catches errors that occur when calling one of the * back-end servers. Some of this code is based on _XPrintDefaultError * in xc/lib/X11/XlibInt.c */ static int dmxErrorHandler(Display *dpy, XErrorEvent *ev) { #define DMX_ERROR_BUF_SIZE 256 /* RATS: these buffers are only used in * length-limited calls. */ char buf[DMX_ERROR_BUF_SIZE]; char request[DMX_ERROR_BUF_SIZE]; _XExtension *ext = NULL; dmxErrorOccurred = TRUE; dmxLastErrorEvent = *ev; XGetErrorText(dpy, ev->error_code, buf, sizeof(buf)); dmxLog(dmxWarning, "dmxErrorHandler: %s\n", buf); /* Find major opcode name */ if (ev->request_code < 128) { XmuSnprintf(request, sizeof(request), "%d", ev->request_code); XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf)); } else { for (ext = dpy->ext_procs; ext && ext->codes.major_opcode != ev->request_code; ext = ext->next); if (ext) strncpy(buf, ext->name, sizeof(buf)); else buf[0] = '\0'; } dmxLog(dmxWarning, " Major opcode: %d (%s)\n", ev->request_code, buf); /* Find minor opcode name */ if (ev->request_code >= 128 && ext) { XmuSnprintf(request, sizeof(request), "%d", ev->request_code); XmuSnprintf(request, sizeof(request), "%s.%d", ext->name, ev->minor_code); XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf)); dmxLog(dmxWarning, " Minor opcode: %d (%s)\n", ev->minor_code, buf); } /* Provide value information */ switch (ev->error_code) { case BadValue: dmxLog(dmxWarning, " Value: 0x%x\n", ev->resourceid); break; case BadAtom: dmxLog(dmxWarning, " AtomID: 0x%x\n", ev->resourceid); break; default: dmxLog(dmxWarning, " ResourceID: 0x%x\n", ev->resourceid); break; } /* Provide serial number information */ dmxLog(dmxWarning, " Failed serial number: %d\n", ev->serial); dmxLog(dmxWarning, " Current serial number: %d\n", dpy->request); // abort (); return 0; } int _dmx_jumpbuf_set = 0; int _dmx_io_error = 0; jmp_buf _dmx_jumpbuf; static int dmxIOErrorHandler (Display *dpy) { _dmx_io_error++; if (!_dmx_jumpbuf_set) { ErrorF ("_dmx_jumpbuf not set\n"); abort (); } else { longjmp (_dmx_jumpbuf, 1); } return 0; } #ifdef GLXEXT static int dmxNOPErrorHandler(Display *dpy, XErrorEvent *ev) { return 0; } #endif char * dmxMemDup (const char *data, int dataLen) { char *d; d = malloc (dataLen); if (!d) return NULL; memcpy (d, data, dataLen); return d; } Bool dmxOpenDisplay(DMXScreenInfo *dmxScreen) { dmxScreen->beDisplay = NULL; if (!dmxScreen->display || !*dmxScreen->display) return FALSE; if (dmxScreen->authType && *dmxScreen->authType) XSetAuthorization (dmxScreen->authType, dmxScreen->authTypeLen, dmxScreen->authData, dmxScreen->authDataLen); if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->display))) return FALSE; dmxScreen->alive = 1; dmxScreen->broken = 0; dmxScreen->inDispatch = FALSE; dmxScreen->fd = XConnectionNumber (dmxScreen->beDisplay); dmxScreen->connection = XGetXCBConnection (dmxScreen->beDisplay); XSetEventQueueOwner (dmxScreen->beDisplay, XCBOwnsEventQueue); dmxScreen->sync.sequence = 0; AddEnabledDevice (dmxScreen->fd); dmxScreen->atomTable = NULL; dmxScreen->atomTableSize = 0; dmxScreen->beAtomTable = NULL; dmxScreen->beAtomTableSize = 0; return TRUE; } void dmxCloseDisplay(DMXScreenInfo *dmxScreen) { RemoveEnabledDevice (dmxScreen->fd); /* make sure all pending sync replies are processed */ dmxSync (dmxScreen, TRUE); if (dmxScreen->atomTable) xfree (dmxScreen->atomTable); if (dmxScreen->beAtomTable) xfree (dmxScreen->beAtomTable); xcb_disconnect (dmxScreen->connection); dmxScreen->alive = 0; } void dmxSetErrorHandler(DMXScreenInfo *dmxScreen) { XSetErrorHandler(dmxErrorHandler); XSetIOErrorHandler(dmxIOErrorHandler); } static void dmxPrintScreenInfo(DMXScreenInfo *dmxScreen) { XWindowAttributes attribs; int ndepths = 0, *depths = NULL; int i; Display *dpy = dmxScreen->beDisplay; Screen *s = DefaultScreenOfDisplay(dpy); int scr = DefaultScreen(dpy); XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs); if (!(depths = XListDepths(dpy, scr, &ndepths))) ndepths = 0; dmxLogOutput(dmxScreen, "Name of display: %s\n", DisplayString(dpy)); dmxLogOutput(dmxScreen, "Version number: %d.%d\n", ProtocolVersion(dpy), ProtocolRevision(dpy)); dmxLogOutput(dmxScreen, "Vendor string: %s\n", ServerVendor(dpy)); if (!strstr(ServerVendor(dpy), "XFree86")) { dmxLogOutput(dmxScreen, "Vendor release: %d\n", VendorRelease(dpy)); } else { /* This code based on xdpyinfo.c */ int v = VendorRelease(dpy); int major = -1, minor = -1, patch = -1, subpatch = -1; if (v < 336) major = v / 100, minor = (v / 10) % 10, patch = v % 10; else if (v < 3900) { major = v / 1000; minor = (v / 100) % 10; if (((v / 10) % 10) || (v % 10)) { patch = (v / 10) % 10; if (v % 10) subpatch = v % 10; } } else if (v < 40000000) { major = v / 1000; minor = (v / 10) % 10; if (v % 10) patch = v % 10; } else { major = v / 10000000; minor = (v / 100000) % 100; patch = (v / 1000) % 100; if (v % 1000) subpatch = v % 1000; } dmxLogOutput(dmxScreen, "Vendor release: %d (XFree86 version: %d.%d", v, major, minor); if (patch > 0) dmxLogOutputCont(dmxScreen, ".%d", patch); if (subpatch > 0) dmxLogOutputCont(dmxScreen, ".%d", subpatch); dmxLogOutputCont(dmxScreen, ")\n"); } dmxLogOutput(dmxScreen, "Dimensions: %dx%d pixels\n", attribs.width, attribs.height); dmxLogOutput(dmxScreen, "%d depths on screen %d: ", ndepths, scr); for (i = 0; i < ndepths; i++) dmxLogOutputCont(dmxScreen, "%c%d", i ? ',' : ' ', depths[i]); dmxLogOutputCont(dmxScreen, "\n"); dmxLogOutput(dmxScreen, "Depth of root window: %d plane%s (%d)\n", attribs.depth, attribs.depth == 1 ? "" : "s", DisplayPlanes(dpy, scr)); dmxLogOutput(dmxScreen, "Number of colormaps: %d min, %d max\n", MinCmapsOfScreen(s), MaxCmapsOfScreen(s)); dmxLogOutput(dmxScreen, "Options: backing-store %s, save-unders %s\n", (DoesBackingStore (s) == NotUseful) ? "no" : ((DoesBackingStore (s) == Always) ? "yes" : "when mapped"), DoesSaveUnders (s) ? "yes" : "no"); XFree(depths); } void dmxGetScreenAttribs(DMXScreenInfo *dmxScreen) { XWindowAttributes attribs; Display *dpy = dmxScreen->beDisplay; #ifdef GLXEXT int dummy; #endif XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs); dmxScreen->beWidth = attribs.width; dmxScreen->beHeight = attribs.height; /* FIXME: Get these from the back-end server */ dmxScreen->beXDPI = 96; dmxScreen->beYDPI = 96; dmxScreen->beDepth = attribs.depth; /* FIXME: verify that this * works always. In * particular, this will work * well for depth=16, will fail * because of colormap issues * at depth 8. More work needs * to be done here. */ if (dmxScreen->beDepth <= 8) dmxScreen->beBPP = 8; else if (dmxScreen->beDepth <= 16) dmxScreen->beBPP = 16; else dmxScreen->beBPP = 32; if (dmxScreen->scrnWin != DefaultRootWindow(dpy)) XGetWindowAttributes(dpy, dmxScreen->scrnWin, &attribs); dmxScreen->scrnWidth = attribs.width; dmxScreen->scrnHeight = attribs.height; #ifdef GLXEXT /* get the majorOpcode for the back-end GLX extension */ XQueryExtension(dpy, "GLX", &dmxScreen->glxMajorOpcode, &dummy, &dmxScreen->glxErrorBase); #endif dmxPrintScreenInfo(dmxScreen); dmxLogOutput(dmxScreen, "%dx%d on %dx%d at depth=%d, bpp=%d\n", dmxScreen->scrnWidth, dmxScreen->scrnHeight, dmxScreen->beWidth, dmxScreen->beHeight, dmxScreen->beDepth, dmxScreen->beBPP); if (dmxScreen->beDepth == 8) dmxLogOutputWarning(dmxScreen, "Support for depth == 8 is not complete\n"); } Bool dmxGetVisualInfo(DMXScreenInfo *dmxScreen) { int i; XVisualInfo visinfo; visinfo.screen = DefaultScreen(dmxScreen->beDisplay); dmxScreen->beVisuals = XGetVisualInfo(dmxScreen->beDisplay, VisualScreenMask, &visinfo, &dmxScreen->beNumVisuals); dmxScreen->beDefVisualIndex = -1; if (defaultColorVisualClass >= 0 || dmxDepth > 0) { for (i = 0; i < dmxScreen->beNumVisuals; i++) if (defaultColorVisualClass >= 0) { if (dmxScreen->beVisuals[i].class == defaultColorVisualClass) { if (dmxDepth > 0) { if (dmxScreen->beVisuals[i].depth == dmxDepth) { dmxScreen->beDefVisualIndex = i; break; } } else { dmxScreen->beDefVisualIndex = i; break; } } } else if (dmxScreen->beVisuals[i].depth == dmxDepth) { dmxScreen->beDefVisualIndex = i; break; } } else { visinfo.visualid = XVisualIDFromVisual(DefaultVisual(dmxScreen->beDisplay, visinfo.screen)); for (i = 0; i < dmxScreen->beNumVisuals; i++) if (visinfo.visualid == dmxScreen->beVisuals[i].visualid) { dmxScreen->beDefVisualIndex = i; break; } } for (i = 0; i < dmxScreen->beNumVisuals; i++) dmxLogVisual(dmxScreen, &dmxScreen->beVisuals[i], (i == dmxScreen->beDefVisualIndex)); return (dmxScreen->beDefVisualIndex >= 0); } void dmxGetColormaps(DMXScreenInfo *dmxScreen) { int i; dmxScreen->beNumDefColormaps = dmxScreen->beNumVisuals; dmxScreen->beDefColormaps = xalloc(dmxScreen->beNumDefColormaps * sizeof(*dmxScreen->beDefColormaps)); for (i = 0; i < dmxScreen->beNumDefColormaps; i++) dmxScreen->beDefColormaps[i] = XCreateColormap(dmxScreen->beDisplay, DefaultRootWindow(dmxScreen->beDisplay), dmxScreen->beVisuals[i].visual, AllocNone); dmxScreen->beBlackPixel = BlackPixel(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay)); dmxScreen->beWhitePixel = WhitePixel(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay)); } void dmxGetPixmapFormats(DMXScreenInfo *dmxScreen) { dmxScreen->beDepths = XListDepths(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay), &dmxScreen->beNumDepths); dmxScreen->bePixmapFormats = XListPixmapFormats(dmxScreen->beDisplay, &dmxScreen->beNumPixmapFormats); } static Bool dmxSetPixmapFormats(ScreenInfo *pScreenInfo, DMXScreenInfo *dmxScreen) { XPixmapFormatValues *bePixmapFormat; PixmapFormatRec *format; int i, j; pScreenInfo->imageByteOrder = ImageByteOrder(dmxScreen->beDisplay); pScreenInfo->bitmapScanlineUnit = BitmapUnit(dmxScreen->beDisplay); pScreenInfo->bitmapScanlinePad = BitmapPad(dmxScreen->beDisplay); pScreenInfo->bitmapBitOrder = BitmapBitOrder(dmxScreen->beDisplay); pScreenInfo->numPixmapFormats = 0; for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) { bePixmapFormat = &dmxScreen->bePixmapFormats[i]; for (j = 0; j < dmxScreen->beNumDepths; j++) if ((bePixmapFormat->depth == 1) || (bePixmapFormat->depth == dmxScreen->beDepths[j])) { format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats]; format->depth = bePixmapFormat->depth; format->bitsPerPixel = bePixmapFormat->bits_per_pixel; format->scanlinePad = bePixmapFormat->scanline_pad; pScreenInfo->numPixmapFormats++; break; } } return TRUE; } /** Initialize the display and collect relevant information about the * display properties */ static Bool dmxDisplayInit(DMXScreenInfo *dmxScreen) { if (!dmxOpenDisplay(dmxScreen)) { if (dmxScreen->display && *dmxScreen->display) dmxLog(dmxWarning, "dmxOpenDisplay: Unable to open display %s\n", dmxScreen->display); dmxScreen->scrnWidth = 1; dmxScreen->scrnHeight = 1; #ifdef PANORAMIX if (!noPanoramiXExtension) { dmxScreen->scrnWidth = dmxScreens[0].scrnWidth; dmxScreen->scrnHeight = dmxScreens[0].scrnHeight; } #endif dmxScreen->beWidth = 1; dmxScreen->beHeight = 1; dmxScreen->beXDPI = 96; dmxScreen->beYDPI = 96; dmxScreen->beDepth = 24; dmxScreen->beBPP = 32; return FALSE; } else { if (!dmxScreen->scrnWin) dmxScreen->scrnWin = DefaultRootWindow (dmxScreen->beDisplay); dmxSetErrorHandler(dmxScreen); dmxGetScreenAttribs(dmxScreen); if (!dmxGetVisualInfo(dmxScreen)) { dmxLog(dmxWarning, "dmxGetVisualInfo: No matching visuals found\n"); XLIB_PROLOGUE (dmxScreen); XCloseDisplay(dmxScreen->beDisplay); XLIB_EPILOGUE (dmxScreen); dmxScreen->beDisplay = NULL; return FALSE; } else { dmxGetColormaps(dmxScreen); dmxGetPixmapFormats(dmxScreen); } } return TRUE; } /* If this doesn't compile, just add || defined(yoursystem) to the line * below. This information is to help with bug reports and is not * critical. */ #if !defined(_POSIX_SOURCE) static const char *dmxExecOS(void) { return ""; } #else #include static const char *dmxExecOS(void) { static char buffer[128]; static int initialized = 0; struct utsname u; if (!initialized++) { memset(buffer, 0, sizeof(buffer)); uname(&u); XmuSnprintf(buffer, sizeof(buffer)-1, "%s %s %s", u.sysname, u.release, u.version); } return buffer; } #endif static const char *dmxBuildCompiler(void) { static char buffer[128]; static int initialized = 0; if (!initialized++) { memset(buffer, 0, sizeof(buffer)); #if defined(__GNUC__) && defined(__GNUC_MINOR__) &&defined(__GNUC_PATCHLEVEL__) XmuSnprintf(buffer, sizeof(buffer)-1, "gcc %d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); #endif } return buffer; } static const char *dmxExecHost(void) { static char buffer[128]; static int initialized = 0; if (!initialized++) { memset(buffer, 0, sizeof(buffer)); XmuGetHostname(buffer, sizeof(buffer) - 1); } return buffer; } /** This routine is called in Xserver/dix/main.c from \a main(). */ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[]) { int i; static unsigned long dmxGeneration = 0; #ifdef GLXEXT Bool glxSupported = TRUE; #endif if (dmxGeneration != serverGeneration) { int vendrel = VENDOR_RELEASE; int major, minor, year, month, day; dmxGeneration = serverGeneration; major = vendrel / 100000000; vendrel -= major * 100000000; minor = vendrel / 1000000; vendrel -= minor * 1000000; year = vendrel / 10000; vendrel -= year * 10000; month = vendrel / 100; vendrel -= month * 100; day = vendrel; /* Add other epoch tests here */ if (major > 0 && minor > 0) year += 2000; dmxLog(dmxInfo, "Generation: %d\n", dmxGeneration); dmxLog(dmxInfo, "DMX version: %d.%d.%02d%02d%02d (%s)\n", major, minor, year, month, day, VENDOR_STRING); SetVendorRelease(VENDOR_RELEASE); SetVendorString(VENDOR_STRING); if (dmxGeneration == 1) { dmxLog(dmxInfo, "DMX Build OS: %s (%s)\n", OSNAME, OSVENDOR); dmxLog(dmxInfo, "DMX Build Compiler: %s\n", dmxBuildCompiler()); dmxLog(dmxInfo, "DMX Execution OS: %s\n", dmxExecOS()); dmxLog(dmxInfo, "DMX Execution Host: %s\n", dmxExecHost()); } dmxLog(dmxInfo, "MAXSCREENS: %d\n", MAXSCREENS); for (i = 0; i < dmxNumScreens; i++) { if (dmxScreens[i].beDisplay) dmxLog(dmxWarning, "Display \"%s\" still open\n", dmxScreens[i].display); dmxStatFree(dmxScreens[i].stat); dmxScreens[i].stat = NULL; } for (i = 0; i < dmxNumInputs; i++) dmxInputFree(&dmxInputs[i]); if (dmxScreens) free(dmxScreens); if (dmxInputs) free(dmxInputs); dmxScreens = NULL; dmxInputs = NULL; dmxNumScreens = 0; dmxNumInputs = 0; } /* Make sure that the command-line arguments are sane. */ if (dmxAddRemoveScreens && dmxGLXProxy) { /* Currently it is not possible to support GLX and Render * extensions with dynamic screen addition/removal due to the * state that each extension keeps, which cannot be restored. */ dmxLog(dmxWarning, "GLX Proxy and Render extensions do not yet support dynamic\n"); dmxLog(dmxWarning, "screen addition and removal. Please specify -noglxproxy\n"); dmxLog(dmxWarning, "and -norender on the command line or in the configuration\n"); dmxLog(dmxWarning, "file to disable these two extensions if you wish to use\n"); dmxLog(dmxWarning, "the dynamic addition and removal of screens support.\n"); dmxLog(dmxFatal, "Dynamic screen addition/removal error (see above).\n"); } for (i = 0; i < dmxPropTransNum; i++) dmxPropTrans[i].type = MakeAtom ((char *) dmxPropTrans[i].name, strlen (dmxPropTrans[i].name), TRUE); if (!dmxConfigDisplaysFromCommandLine ()) dmxLaunchDisplay (argc, argv, dmxLaunchIndex, dmxLaunchVT); /* ddxProcessArgument has been called at this point, but any data * from the configuration file has not been applied. Do so, and be * sure we have at least one back-end display. */ dmxConfigConfigure(); if (!dmxNumScreens) dmxLog(dmxFatal, "InitOutput: no back-end displays found\n"); /* Disable lazy window creation optimization if offscreen * optimization is disabled */ if (!dmxOffScreenOpt && dmxLazyWindowCreation) { dmxLog(dmxInfo, "InitOutput: Disabling lazy window creation optimization\n"); dmxLog(dmxInfo, " since it requires the offscreen optimization\n"); dmxLog(dmxInfo, " to function properly.\n"); dmxLazyWindowCreation = FALSE; } /* Open each display and gather information about it. */ for (i = 0; i < dmxNumScreens; i++) if (!dmxDisplayInit(&dmxScreens[i]) && i == 0) dmxLog(dmxFatal, "dmxOpenDisplay: Unable to open display %s\n", dmxScreens[i].display); #if PANORAMIX /* Register a Xinerama callback which will run from within * PanoramiXCreateConnectionBlock. We can use the callback to * determine if Xinerama is loaded and to check the visuals * determined by PanoramiXConsolidate. */ XineramaRegisterConnectionBlockCallback(dmxConnectionBlockCallback); #endif /* Since we only have a single screen thus far, we only need to set the pixmap formats to match that screen. FIXME: this isn't true.*/ if (!dmxSetPixmapFormats(pScreenInfo, &dmxScreens[0])) return; /* Might want to install a signal handler to allow cleaning up after * unexpected signals. The DIX/OS layer already handles SIGINT and * SIGTERM, so everything is OK for expected signals. --DD * * SIGHUP, SIGINT, and SIGTERM are trapped in os/connection.c * SIGQUIT is another common signal that is sent from the keyboard. * Trap it here, to ensure that the keyboard modifier map and other * state for the input devices are restored. (This makes the * behavior of SIGQUIT somewhat unexpected, since it will be the * same as the behavior of SIGINT. However, leaving the modifier * map of the input devices empty is even more unexpected.) --RF */ OsSignal (SIGQUIT, GiveUp); OsSignal (SIGSEGV, dmxSigHandler); OsSignal (SIGILL, dmxSigHandler); OsSignal (SIGFPE, dmxSigHandler); OsSignal (SIGABRT, dmxSigHandler); #ifdef GLXEXT /* Check if GLX extension exists on all back-end servers */ for (i = 0; i < dmxNumScreens; i++) glxSupported &= (dmxScreens[i].glxMajorOpcode > 0); #endif /* Tell dix layer about the backend displays */ for (i = 0; i < dmxNumScreens; i++) { #ifdef GLXEXT if (glxSupported) { /* * Builds GLX configurations from the list of visuals * supported by the back-end server, and give that * configuration list to the glx layer - so that he will * build the visuals accordingly. */ DMXScreenInfo *dmxScreen = &dmxScreens[i]; __GLXvisualConfig *configs = NULL; dmxGlxVisualPrivate **configprivs = NULL; int nconfigs = 0; int (*oldErrorHandler)(Display *, XErrorEvent *); int i; /* Catch errors if when using an older GLX w/o FBconfigs */ oldErrorHandler = XSetErrorHandler(dmxNOPErrorHandler); /* Get FBConfigs of the back-end server */ dmxScreen->fbconfigs = GetGLXFBConfigs(dmxScreen->beDisplay, dmxScreen->glxMajorOpcode, &dmxScreen->numFBConfigs); XSetErrorHandler(oldErrorHandler); dmxScreen->glxVisuals = GetGLXVisualConfigs(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay), &dmxScreen->numGlxVisuals); if (dmxScreen->fbconfigs) { configs = GetGLXVisualConfigsFromFBConfigs(dmxScreen->fbconfigs, dmxScreen->numFBConfigs, dmxScreen->beVisuals, dmxScreen->beNumVisuals, dmxScreen->glxVisuals, dmxScreen->numGlxVisuals, &nconfigs); } else { configs = dmxScreen->glxVisuals; nconfigs = dmxScreen->numGlxVisuals; } configprivs = xalloc(nconfigs * sizeof(dmxGlxVisualPrivate*)); if (configs != NULL && configprivs != NULL) { /* Initialize our private info for each visual * (currently only x_visual_depth and x_visual_class) */ for (i = 0; i < nconfigs; i++) { configprivs[i] = (dmxGlxVisualPrivate *) xalloc(sizeof(dmxGlxVisualPrivate)); configprivs[i]->x_visual_depth = 0; configprivs[i]->x_visual_class = 0; /* Find the visual depth */ if (configs[i].vid > 0) { int j; for (j = 0; j < dmxScreen->beNumVisuals; j++) { if (dmxScreen->beVisuals[j].visualid == configs[i].vid) { configprivs[i]->x_visual_depth = dmxScreen->beVisuals[j].depth; configprivs[i]->x_visual_class = dmxScreen->beVisuals[j].class; break; } } } } /* Hand out the glx configs to glx extension */ GlxSetVisualConfigs(nconfigs, configs, (void**)configprivs); XFlush(dmxScreen->beDisplay); } } #endif /* GLXEXT */ AddScreen(dmxScreenInit, argc, argv); } /* Make sure there is a global width/height available */ dmxComputeWidthHeight (); dmxInitFonts(); dmxInitProps(); dmxInitGrabs(); dmxInitSelections(); #ifdef MITSHM dmxInitShm(); #endif #ifdef RENDER /* Initialize the render extension */ if (!noRenderExtension) dmxInitRender(); #endif #ifdef COMPOSITE /* Initialize the composite extension */ if (!noCompositeExtension) dmxInitComposite(); #endif /* Initialized things that need timer hooks */ dmxStatInit(); dmxSyncInit(); /* Calls RegisterBlockAndWakeupHandlers */ dmxLog(dmxInfo, "Shadow framebuffer support %s\n", dmxShadowFB ? "enabled" : "disabled"); } /* RATS: Assuming the fp string (which comes from the command-line argv vector) is NULL-terminated, the buffer is large enough for the strcpy. */ static void dmxSetDefaultFontPath(char *fp) { int fplen = strlen(fp) + 1; if (dmxFontPath) { int len; len = strlen(dmxFontPath); dmxFontPath = xrealloc(dmxFontPath, len+fplen+1); dmxFontPath[len] = ','; strncpy(&dmxFontPath[len+1], fp, fplen); } else { dmxFontPath = xalloc(fplen); strncpy(dmxFontPath, fp, fplen); } defaultFontPath = dmxFontPath; } /** This function is called in Xserver/os/utils.c from \a AbortServer(). * We must ensure that backend and console state is restored in the * event the server shutdown wasn't clean. */ void AbortDDX(void) { int i; for (i=0; i < dmxNumScreens; i++) { DMXScreenInfo *dmxScreen = &dmxScreens[i]; if (dmxScreen->beDisplay) XCloseDisplay(dmxScreen->beDisplay); dmxScreen->beDisplay = NULL; } dmxAbortDisplay (); } /** This function is called in Xserver/dix/main.c from \a main() when * dispatchException & DE_TERMINATE (which is the only way to exit the * main loop without an interruption. */ void ddxGiveUp(void) { AbortDDX(); } /** This function is called in Xserver/os/osinit.c from \a OsInit(). */ void OsVendorInit(void) { } /** This function is called in Xserver/os/utils.c from \a FatalError() * and \a VFatalError(). (Note that setting the function pointer \a * OsVendorVErrorFProc will cause \a VErrorF() (which is called by the * two routines mentioned here, as well as by others) to use the * referenced routine instead of \a vfprintf().) */ void OsVendorFatalError(void) { } /** Process our command line arguments. */ int ddxProcessArgument(int argc, char *argv[], int i) { int retval = 0; if (i == 1) { defaultFontPath = "built-ins"; #ifdef PANORAMIX noPanoramiXExtension = FALSE; PanoramiXExtensionDisabledHack = TRUE; #endif } if (!strcmp(argv[i], "-display")) { if (++i < argc) dmxConfigStoreDisplay(argv[i], argv[i], NULL, 0, NULL, 0, 0); retval = 2; } else if (!strcmp(argv[i], "-numDetached")) { if (++i < argc) dmxConfigStoreNumDetached(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-inputfrom") || !strcmp(argv[i], "-input")) { if (++i < argc) dmxConfigStoreInput(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-xinputfrom") || !strcmp(argv[i],"-xinput")) { if (++i < argc) dmxConfigStoreXInput(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-noshadowfb")) { dmxLog(dmxWarning, "-noshadowfb has been deprecated " "since it is now the default\n"); dmxShadowFB = FALSE; retval = 1; } else if (!strcmp(argv[i], "-shadowfb")) { dmxShadowFB = TRUE; retval = 1; } else if (!strcmp(argv[i], "-configfile")) { if (++i < argc) dmxConfigStoreFile(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-config")) { if (++i < argc) dmxConfigStoreConfig(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-fontpath")) { if (++i < argc) dmxSetDefaultFontPath(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-stat")) { if ((i += 2) < argc) dmxStatActivate(argv[i-1], argv[i]); retval = 3; } else if (!strcmp(argv[i], "-syncbatch")) { if (++i < argc) dmxSyncActivate(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-offscreenopt")) { dmxOffScreenOpt = TRUE; retval = 1; } else if (!strcmp(argv[i], "-nosubdivprims")) { dmxSubdividePrimitives = FALSE; retval = 1; } else if (!strcmp(argv[i], "-windowopt")) { dmxLazyWindowCreation = TRUE; retval = 1; } else if (!strcmp(argv[i], "-noxkb")) { dmxUseXKB = FALSE; retval = 1; } else if (!strcmp(argv[i], "-depth")) { if (++i < argc) dmxDepth = atoi(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-norender")) { noRenderExtension = TRUE; retval = 1; #ifdef GLXEXT } else if (!strcmp(argv[i], "-noglxproxy")) { dmxGLXProxy = FALSE; retval = 1; } else if (!strcmp(argv[i], "-noglxswapgroup")) { dmxGLXSwapGroupSupport = FALSE; retval = 1; } else if (!strcmp(argv[i], "-glxsyncswap")) { dmxGLXSyncSwap = TRUE; retval = 1; } else if (!strcmp(argv[i], "-glxfinishswap")) { dmxGLXFinishSwap = TRUE; retval = 1; #endif } else if (!strcmp(argv[i], "-ignorebadfontpaths")) { dmxIgnoreBadFontPaths = TRUE; retval = 1; } else if (!strcmp(argv[i], "-noaddremovescreens")) { dmxAddRemoveScreens = FALSE; retval = 1; #ifdef DMXVNC } else if (!strcmp(argv[i], "-novnc")) { dmxVnc = FALSE; retval = 1; #endif #ifdef RANDR } else if (!strcmp(argv[i], "-outputs")) { if (++i < argc) xRROutputsPerScreen = atoi(argv[i]); retval = 2; } else if (!strcmp(argv[i], "-crtcs")) { if (++i < argc) xRRCrtcsPerScreen = atoi(argv[i]); retval = 2; #endif } else if (!strcmp(argv[i], "-param")) { if ((i += 2) < argc) { if (!strcasecmp(argv[i-1], "xkbrules")) dmxConfigSetXkbRules(argv[i]); else if (!strcasecmp(argv[i-1], "xkbmodel")) dmxConfigSetXkbModel(argv[i]); else if (!strcasecmp(argv[i-1], "xkblayout")) dmxConfigSetXkbLayout(argv[i]); else if (!strcasecmp(argv[i-1], "xkbvariant")) dmxConfigSetXkbVariant(argv[i]); else if (!strcasecmp(argv[i-1], "xkboptions")) dmxConfigSetXkbOptions(argv[i]); else dmxLog(dmxWarning, "-param requires: XkbRules, XkbModel, XkbLayout," " XkbVariant, or XkbOptions\n"); } retval = 3; } else if (!strcmp (argv[i], "-prop")) { if ((i + 2) < argc) { DMXPropTrans *prop; prop = xrealloc (dmxPropTrans, sizeof (DMXPropTrans) * (dmxPropTransNum + 1)); if (prop) { prop[dmxPropTransNum].name = argv[i + 1]; prop[dmxPropTransNum].format = argv[i + 2]; prop[dmxPropTransNum].type = 0; dmxPropTransNum++; dmxPropTrans = prop; } } retval = 3; } #ifdef XV else if (!strcmp (argv[i], "-xvimage")) { if (++i < argc) { char **formats; formats = xrealloc (dmxXvImageFormats, sizeof (char *) * (dmxXvImageFormatsNum + 1)); if (formats) { formats[dmxXvImageFormatsNum] = argv[i]; dmxXvImageFormatsNum++; dmxXvImageFormats = formats; } } retval = 2; } #endif else if ((argv[i][0] == 'v') && (argv[i][1] == 't')) { dmxLaunchVT = argv[i]; retval = 1; } else if (!strcmp(argv[i], "--")) { dmxLaunchIndex = i + 1; retval = argc - i; } if (i == (argc - 1)) { if (!dmxPropTrans) { dmxPropTrans = xalloc (sizeof (DMXPropTrans)); dmxPropTrans->name = "_COMPIZ_WINDOW_DECOR"; dmxPropTrans->format = "xP"; dmxPropTrans->type = 0; dmxPropTransNum = 1; } #ifdef XV if (!dmxXvImageFormats) { dmxXvImageFormats = xalloc (sizeof (char *) * 2); dmxXvImageFormats[0] = "YV12"; dmxXvImageFormats[1] = "YUY2"; dmxXvImageFormatsNum = 2; } #endif } if (!serverGeneration) dmxConfigSetMaxScreens(); return retval; } /** Provide succinct usage information for the DMX server. */ void ddxUseMsg(void) { ErrorF("\n\nDevice Dependent Usage:\n"); ErrorF("-display string Specify the back-end display(s)\n"); ErrorF("-numDetached num Specify detached back-end display(s)\n"); ErrorF("-input string Specify input source for core device\n"); ErrorF("-xinput string Specify input source for XInput device\n"); ErrorF("-shadowfb Enable shadow frame buffer\n"); ErrorF("-configfile file Read from a configuration file\n"); ErrorF("-config config Select a specific configuration\n"); ErrorF("-fontpath Sets the default font path\n"); ErrorF("-stat inter scrns Print out performance statistics\n"); ErrorF("-syncbatch inter Set interval for XSync batching\n"); ErrorF("-offscreenopt Enable offscreen optimization\n"); ErrorF("-nosubdivprims Disable primitive subdivision\n"); ErrorF(" optimization\n"); ErrorF("-windowopt Enable lazy window creation optimization\n"); ErrorF("-noxkb Disable use of the XKB extension with\n"); ErrorF(" backend displays (cf. -kb).\n"); ErrorF("-depth Specify the default root window depth\n"); ErrorF("-norender Disable RENDER extension support\n"); #ifdef GLXEXT ErrorF("-glxproxy Enable GLX Proxy\n"); ErrorF("-noglxswapgroup Disable swap group and swap barrier\n"); ErrorF(" extensions in GLX proxy\n"); ErrorF("-glxsyncswap Force XSync after swap buffers\n"); ErrorF("-glxfinishswap Force glFinish after swap buffers\n"); #endif ErrorF("-ignorebadfontpaths Ignore bad font paths during initialization\n"); ErrorF("-noaddremovescreens Disable dynamic screen addition/removal\n"); #ifdef DMXVNC ErrorF("-vnc Enable VNC\n"); #endif #ifdef RANDR ErrorF("-outputs num RANDR outputs for each back-end display\n"); ErrorF("-crtcs num RANDR crtcs for each back-end display\n"); #endif ErrorF("-param ... Specify configuration parameters (e.g.,\n"); ErrorF(" XkbRules, XkbModel, XkbLayout, etc.)\n"); ErrorF("-prop name format Specify property translation\n"); #ifdef XV ErrorF("-xvimage fourcc Enable XVideo image format\n"); #endif ErrorF("\n"); ErrorF(" If the -input string matches a -display string, then input\n" " is taken from that backend display. (XInput cannot be taken\n" " from a backend display.) Placing \",console\" after the\n" " display name will force a console window to be opened on\n" " that display in addition to the backend input. This is\n" " useful if the backend window does not cover the whole\n" " physical display.\n\n"); ErrorF(" Otherwise, if the -input or -xinput string specifies another\n" " X display, then a console window will be created on that\n" " display. Placing \",windows\" or \",nowindows\" after the\n" " display name will control the display of window outlines in\n" " the console.\n\n"); ErrorF(" -input or -xinput dummy specifies no input.\n"); ErrorF(" -input or -xinput local specifies the use of a raw keyboard,\n" " mouse, or other (extension) device:\n" " -input local,kbd,ps2 will use a ps2 mouse\n" " -input local,kbd,ms will use a serial mouse\n" " -input local,usb-kbd,usb-mou will use USB devices \n" " -xinput local,usb-oth will use a non-mouse and\n" " non-keyboard USB device with XInput\n\n"); ErrorF(" Special Keys:\n"); ErrorF(" Ctrl-Alt-g Server grab/ungrab (console only)\n"); ErrorF(" Ctrl-Alt-f Fine (1-pixel) mouse mode (console only)\n"); ErrorF(" Ctrl-Alt-q Quit (core devices only)\n"); ErrorF(" Ctrl-Alt-F* Switch to VC (local only)\n\n"); ErrorF("-- [ server ] [ display ] [ options ]\n"); }