/* * 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 "dmxpict.h" #include /* For gettimeofday */ #include /* For XmuGetHostname */ #include "dixstruct.h" #ifdef PANORAMIX #include "panoramiXsrv.h" #endif #include /* For SIGQUIT */ #ifdef GLXEXT #include #include #include "dmx_glxvisuals.h" #include "glx_extinit.h" #include #include #endif /* GLXEXT */ #include /* Global variables available to all Xserver/hw/dmx routines. */ int dmxNumScreens; DMXScreenInfo *dmxScreens; int dmxNumInputs; DMXInputInfo *dmxInputs; XErrorEvent dmxLastErrorEvent; Bool dmxErrorOccurred = FALSE; char *dmxFontPath = NULL; Bool dmxOffScreenOpt = TRUE; Bool dmxSubdividePrimitives = TRUE; Bool dmxLazyWindowCreation = TRUE; Bool dmxUseXKB = TRUE; int dmxDepth = 0; #ifndef GLXEXT static Bool dmxGLXProxy = FALSE; #else Bool dmxGLXProxy = TRUE; Bool dmxGLXSwapGroupSupport = TRUE; Bool dmxGLXSyncSwap = FALSE; Bool dmxGLXFinishSwap = FALSE; #endif RESTYPE RRProviderType = 0; Bool dmxIgnoreBadFontPaths = FALSE; Bool dmxAddRemoveScreens = FALSE; /* 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) { snprintf(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) strlcpy(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) { snprintf(request, sizeof(request), "%d", ev->request_code); snprintf(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", (unsigned int) ev->resourceid); break; case BadAtom: dmxLog(dmxWarning, " AtomID: 0x%x\n", (unsigned int) ev->resourceid); break; default: dmxLog(dmxWarning, " ResourceID: 0x%x\n", (unsigned int) ev->resourceid); break; } /* Provide serial number information */ dmxLog(dmxWarning, " Failed serial number: %d\n", (unsigned int) ev->serial); dmxLog(dmxWarning, " Current serial number: %d\n", (unsigned int) dpy->request); return 0; } #ifdef GLXEXT static int dmxNOPErrorHandler(Display * dpy, XErrorEvent * ev) { return 0; } #endif Bool dmxOpenDisplay(DMXScreenInfo * dmxScreen) { if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->name))) return FALSE; dmxPropertyDisplay(dmxScreen); return TRUE; } void dmxSetErrorHandler(DMXScreenInfo * dmxScreen) { XSetErrorHandler(dmxErrorHandler); } 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"); dmxLogOutput(dmxScreen, "Window Manager running: %s\n", (dmxScreen->WMRunningOnBE) ? "yes" : "no"); if (dmxScreen->WMRunningOnBE) { dmxLogOutputWarning(dmxScreen, "Window manager running " "-- colormaps not supported\n"); } 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; /* Fill in missing geometry information */ if (dmxScreen->scrnXSign < 0) { if (dmxScreen->scrnWidth) { dmxScreen->scrnX = (attribs.width - dmxScreen->scrnWidth - dmxScreen->scrnX); } else { dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX; dmxScreen->scrnX = 0; } } if (dmxScreen->scrnYSign < 0) { if (dmxScreen->scrnHeight) { dmxScreen->scrnY = (attribs.height - dmxScreen->scrnHeight - dmxScreen->scrnY); } else { dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY; dmxScreen->scrnY = 0; } } if (!dmxScreen->scrnWidth) dmxScreen->scrnWidth = attribs.width - dmxScreen->scrnX; if (!dmxScreen->scrnHeight) dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY; if (!dmxScreen->rootWidth) dmxScreen->rootWidth = dmxScreen->scrnWidth; if (!dmxScreen->rootHeight) dmxScreen->rootHeight = dmxScreen->scrnHeight; if (dmxScreen->rootWidth + dmxScreen->rootX > dmxScreen->scrnWidth) dmxScreen->rootWidth = dmxScreen->scrnWidth - dmxScreen->rootX; if (dmxScreen->rootHeight + dmxScreen->rootY > dmxScreen->scrnHeight) dmxScreen->rootHeight = dmxScreen->scrnHeight - dmxScreen->rootY; /* FIXME: Get these from the back-end server */ dmxScreen->beXDPI = 75; dmxScreen->beYDPI = 75; 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; #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+%d+%d on %dx%d at depth=%d, bpp=%d\n", dmxScreen->scrnWidth, dmxScreen->scrnHeight, dmxScreen->scrnX, dmxScreen->scrnY, 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 = xallocarray(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; } void dmxCheckForWM(DMXScreenInfo * dmxScreen) { Status status; XWindowAttributes xwa; status = XGetWindowAttributes(dmxScreen->beDisplay, DefaultRootWindow(dmxScreen->beDisplay), &xwa); dmxScreen->WMRunningOnBE = (status && ((xwa.all_event_masks & SubstructureRedirectMask) || (xwa.all_event_masks & SubstructureNotifyMask))); } /** Initialize the display and collect relevant information about the * display properties */ static void dmxDisplayInit(DMXScreenInfo * dmxScreen) { if (!dmxOpenDisplay(dmxScreen)) dmxLog(dmxFatal, "dmxOpenDisplay: Unable to open display %s\n", dmxScreen->name); dmxSetErrorHandler(dmxScreen); dmxCheckForWM(dmxScreen); dmxGetScreenAttribs(dmxScreen); if (!dmxGetVisualInfo(dmxScreen)) dmxLog(dmxFatal, "dmxGetVisualInfo: No matching visuals found\n"); dmxGetColormaps(dmxScreen); dmxGetPixmapFormats(dmxScreen); } static void dmxAddExtensions(void) { const ExtensionModule dmxExtensions[] = { { DMXExtensionInit, DMX_EXTENSION_NAME, NULL }, }; LoadExtensionList(dmxExtensions, ARRAY_SIZE(dmxExtensions), TRUE); } /** 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; 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: %lu\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); 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].name); dmxStatFree(dmxScreens[i].stat); dmxScreens[i].stat = NULL; } for (i = 0; i < dmxNumInputs; i++) dmxInputFree(&dmxInputs[i]); free(dmxScreens); 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"); } /* 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"); if (!dmxNumInputs) dmxLog(dmxInfo, "InitOutput: no inputs 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++) dmxDisplayInit(&dmxScreens[i]); #ifdef 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); #ifdef GLXEXT /* Check if GLX extension exists on all back-end servers */ for (i = 0; i < dmxNumScreens; i++) noGlxExtension |= (dmxScreens[i].glxMajorOpcode == 0); #endif if (serverGeneration == 1) dmxAddExtensions(); /* Tell dix layer about the backend displays */ for (i = 0; i < dmxNumScreens; i++) { #ifdef GLXEXT if (!noGlxExtension) { /* * 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 *); /* 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 = xallocarray(nconfigs, sizeof(dmxGlxVisualPrivate *)); if (configs != NULL && configprivs != NULL) { int j; /* Initialize our private info for each visual * (currently only x_visual_depth and x_visual_class) */ for (j = 0; j < nconfigs; j++) { configprivs[j] = (dmxGlxVisualPrivate *) malloc(sizeof(dmxGlxVisualPrivate)); configprivs[j]->x_visual_depth = 0; configprivs[j]->x_visual_class = 0; /* Find the visual depth */ if (configs[j].vid > 0) { int k; for (k = 0; k < dmxScreen->beNumVisuals; k++) { if (dmxScreen->beVisuals[k].visualid == configs[j].vid) { configprivs[j]->x_visual_depth = dmxScreen->beVisuals[k].depth; configprivs[j]->x_visual_class = dmxScreen->beVisuals[k].class; break; } } } } XFlush(dmxScreen->beDisplay); } } #endif /* GLXEXT */ AddScreen(dmxScreenInit, argc, argv); } /* Compute origin information. */ dmxInitOrigins(); /* Compute overlap information. */ dmxInitOverlap(); /* Make sure there is a global width/height available */ dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX); /* FIXME: The following is temporarily placed here. When the DMX * extension is available, it will be move there. */ dmxInitFonts(); /* Initialize the render extension */ if (!noRenderExtension) dmxInitRender(); /* Initialized things that need timer hooks */ dmxStatInit(); dmxSyncInit(); /* Calls RegisterBlockAndWakeupHandlers */ } /* 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(const char *fp) { if (dmxFontPath) { int fplen = strlen(fp) + 1; int len = strlen(dmxFontPath); dmxFontPath = realloc(dmxFontPath, len + fplen + 1); dmxFontPath[len] = ','; strncpy(&dmxFontPath[len + 1], fp, fplen); } else { dmxFontPath = strdup(fp); } 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(enum ExitCode error) { int i; for (i = 0; i < dmxNumScreens; i++) { DMXScreenInfo *dmxScreen = &dmxScreens[i]; if (dmxScreen->beDisplay) XCloseDisplay(dmxScreen->beDisplay); dmxScreen->beDisplay = NULL; } } #ifdef DDXBEFORERESET void ddxBeforeReset(void) { } #endif /** 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(enum ExitCode error) { AbortDDX(error); } /** 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(const char *f, va_list args) { } /** Process our command line arguments. */ int ddxProcessArgument(int argc, char *argv[], int i) { int retval = 0; if (!strcmp(argv[i], "-display")) { if (++i < argc) dmxConfigStoreDisplay(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")) { retval = 1; } else if (!strcmp(argv[i], "-nomulticursor")) { dmxCursorNoMulti(); retval = 1; } else if (!strcmp(argv[i], "-shadowfb")) { 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], "-nooffscreenopt")) { dmxOffScreenOpt = FALSE; retval = 1; } else if (!strcmp(argv[i], "-nosubdivprims")) { dmxSubdividePrimitives = FALSE; retval = 1; } else if (!strcmp(argv[i], "-nowindowopt")) { dmxLazyWindowCreation = FALSE; 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], "-addremovescreens")) { dmxAddRemoveScreens = TRUE; retval = 1; } 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; } 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("-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("-nomulticursor Turn of multiple cursor support\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("-nooffscreenopt Disable offscreen optimization\n"); ErrorF("-nosubdivprims Disable primitive subdivision\n"); ErrorF(" optimization\n"); ErrorF("-nowindowopt Disable 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("-noglxproxy Disable 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("-addremovescreens Enable dynamic screen addition/removal\n"); ErrorF("-param ... Specify configuration parameters (e.g.,\n"); ErrorF(" XkbRules, XkbModel, XkbLayout, etc.)\n"); 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"); }