1706f2543Smrg/*
2706f2543Smrg * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3706f2543Smrg *
4706f2543Smrg * All Rights Reserved.
5706f2543Smrg *
6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining
7706f2543Smrg * a copy of this software and associated documentation files (the
8706f2543Smrg * "Software"), to deal in the Software without restriction, including
9706f2543Smrg * without limitation on the rights to use, copy, modify, merge,
10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
11706f2543Smrg * and to permit persons to whom the Software is furnished to do so,
12706f2543Smrg * subject to the following conditions:
13706f2543Smrg *
14706f2543Smrg * The above copyright notice and this permission notice (including the
15706f2543Smrg * next paragraph) shall be included in all copies or substantial
16706f2543Smrg * portions of the Software.
17706f2543Smrg *
18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21706f2543Smrg * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25706f2543Smrg * SOFTWARE.
26706f2543Smrg */
27706f2543Smrg
28706f2543Smrg/*
29706f2543Smrg * Authors:
30706f2543Smrg *   Kevin E. Martin <kem@redhat.com>
31706f2543Smrg *   David H. Dawes <dawes@xfree86.org>
32706f2543Smrg *   Rickard E. (Rik) Faith <faith@redhat.com>
33706f2543Smrg *
34706f2543Smrg */
35706f2543Smrg
36706f2543Smrg/** \file
37706f2543Smrg * Provide expected functions for initialization from the ddx layer and
38706f2543Smrg * global variables for the DMX server. */
39706f2543Smrg
40706f2543Smrg#ifdef HAVE_DMX_CONFIG_H
41706f2543Smrg#include <dmx-config.h>
42706f2543Smrg#endif
43706f2543Smrg
44706f2543Smrg#include "dmx.h"
45706f2543Smrg#include "dmxinit.h"
46706f2543Smrg#include "dmxsync.h"
47706f2543Smrg#include "dmxlog.h"
48706f2543Smrg#include "dmxinput.h"
49706f2543Smrg#include "dmxscrinit.h"
50706f2543Smrg#include "dmxcursor.h"
51706f2543Smrg#include "dmxfont.h"
52706f2543Smrg#include "config/dmxconfig.h"
53706f2543Smrg#include "dmxcb.h"
54706f2543Smrg#include "dmxprop.h"
55706f2543Smrg#include "dmxstat.h"
56706f2543Smrg#include "dmxpict.h"
57706f2543Smrg
58706f2543Smrg#include <X11/Xos.h>                /* For gettimeofday */
59706f2543Smrg#include "dixstruct.h"
60706f2543Smrg#ifdef PANORAMIX
61706f2543Smrg#include "panoramiXsrv.h"
62706f2543Smrg#endif
63706f2543Smrg
64706f2543Smrg#include <signal.h>             /* For SIGQUIT */
65706f2543Smrg
66706f2543Smrg#ifdef GLXEXT
67706f2543Smrg#include <GL/glx.h>
68706f2543Smrg#include <GL/glxint.h>
69706f2543Smrg#include "dmx_glxvisuals.h"
70706f2543Smrg#include <X11/extensions/Xext.h>
71706f2543Smrg#include <X11/extensions/extutil.h>
72706f2543Smrg#endif /* GLXEXT */
73706f2543Smrg
74706f2543Smrg/* Global variables available to all Xserver/hw/dmx routines. */
75706f2543Smrgint             dmxNumScreens;
76706f2543SmrgDMXScreenInfo  *dmxScreens;
77706f2543Smrg
78706f2543Smrgint             dmxNumInputs;
79706f2543SmrgDMXInputInfo   *dmxInputs;
80706f2543Smrg
81706f2543Smrgint             dmxShadowFB = FALSE;
82706f2543Smrg
83706f2543SmrgXErrorEvent     dmxLastErrorEvent;
84706f2543SmrgBool            dmxErrorOccurred = FALSE;
85706f2543Smrg
86706f2543Smrgchar           *dmxFontPath = NULL;
87706f2543Smrg
88706f2543SmrgBool            dmxOffScreenOpt = TRUE;
89706f2543Smrg
90706f2543SmrgBool            dmxSubdividePrimitives = TRUE;
91706f2543Smrg
92706f2543SmrgBool            dmxLazyWindowCreation = TRUE;
93706f2543Smrg
94706f2543SmrgBool            dmxUseXKB = TRUE;
95706f2543Smrg
96706f2543Smrgint             dmxDepth = 0;
97706f2543Smrg
98706f2543Smrg#ifndef GLXEXT
99706f2543Smrgstatic Bool     dmxGLXProxy = FALSE;
100706f2543Smrg#else
101706f2543SmrgBool            dmxGLXProxy = TRUE;
102706f2543Smrg
103706f2543SmrgBool            dmxGLXSwapGroupSupport = TRUE;
104706f2543Smrg
105706f2543SmrgBool            dmxGLXSyncSwap = FALSE;
106706f2543Smrg
107706f2543SmrgBool            dmxGLXFinishSwap = FALSE;
108706f2543Smrg#endif
109706f2543Smrg
110706f2543SmrgBool            dmxIgnoreBadFontPaths = FALSE;
111706f2543Smrg
112706f2543SmrgBool            dmxAddRemoveScreens = FALSE;
113706f2543Smrg
114706f2543Smrg/* dmxErrorHandler catches errors that occur when calling one of the
115706f2543Smrg * back-end servers.  Some of this code is based on _XPrintDefaultError
116706f2543Smrg * in xc/lib/X11/XlibInt.c */
117706f2543Smrgstatic int dmxErrorHandler(Display *dpy, XErrorEvent *ev)
118706f2543Smrg{
119706f2543Smrg#define DMX_ERROR_BUF_SIZE 256
120706f2543Smrg                                /* RATS: these buffers are only used in
121706f2543Smrg                                 * length-limited calls. */
122706f2543Smrg    char        buf[DMX_ERROR_BUF_SIZE];
123706f2543Smrg    char        request[DMX_ERROR_BUF_SIZE];
124706f2543Smrg    _XExtension *ext = NULL;
125706f2543Smrg
126706f2543Smrg    dmxErrorOccurred  = TRUE;
127706f2543Smrg    dmxLastErrorEvent = *ev;
128706f2543Smrg
129706f2543Smrg    XGetErrorText(dpy, ev->error_code, buf, sizeof(buf));
130706f2543Smrg    dmxLog(dmxWarning, "dmxErrorHandler: %s\n", buf);
131706f2543Smrg
132706f2543Smrg                                /* Find major opcode name */
133706f2543Smrg    if (ev->request_code < 128) {
134706f2543Smrg        XmuSnprintf(request, sizeof(request), "%d", ev->request_code);
135706f2543Smrg        XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
136706f2543Smrg    } else {
137706f2543Smrg        for (ext = dpy->ext_procs;
138706f2543Smrg             ext && ext->codes.major_opcode != ev->request_code;
139706f2543Smrg             ext = ext->next);
140706f2543Smrg        if (ext) strncpy(buf, ext->name, sizeof(buf));
141706f2543Smrg        else     buf[0] = '\0';
142706f2543Smrg    }
143706f2543Smrg    dmxLog(dmxWarning, "                 Major opcode: %d (%s)\n",
144706f2543Smrg           ev->request_code, buf);
145706f2543Smrg
146706f2543Smrg                                /* Find minor opcode name */
147706f2543Smrg    if (ev->request_code >= 128 && ext) {
148706f2543Smrg        XmuSnprintf(request, sizeof(request), "%d", ev->request_code);
149706f2543Smrg        XmuSnprintf(request, sizeof(request), "%s.%d",
150706f2543Smrg                    ext->name, ev->minor_code);
151706f2543Smrg        XGetErrorDatabaseText(dpy, "XRequest", request, "", buf, sizeof(buf));
152706f2543Smrg        dmxLog(dmxWarning, "                 Minor opcode: %d (%s)\n",
153706f2543Smrg               ev->minor_code, buf);
154706f2543Smrg    }
155706f2543Smrg
156706f2543Smrg                                /* Provide value information */
157706f2543Smrg    switch (ev->error_code) {
158706f2543Smrg    case BadValue:
159706f2543Smrg        dmxLog(dmxWarning, "                 Value:        0x%x\n",
160706f2543Smrg               ev->resourceid);
161706f2543Smrg        break;
162706f2543Smrg    case BadAtom:
163706f2543Smrg        dmxLog(dmxWarning, "                 AtomID:       0x%x\n",
164706f2543Smrg               ev->resourceid);
165706f2543Smrg        break;
166706f2543Smrg    default:
167706f2543Smrg        dmxLog(dmxWarning, "                 ResourceID:   0x%x\n",
168706f2543Smrg               ev->resourceid);
169706f2543Smrg        break;
170706f2543Smrg    }
171706f2543Smrg
172706f2543Smrg                                /* Provide serial number information */
173706f2543Smrg    dmxLog(dmxWarning, "                 Failed serial number:  %d\n",
174706f2543Smrg           ev->serial);
175706f2543Smrg    dmxLog(dmxWarning, "                 Current serial number: %d\n",
176706f2543Smrg           dpy->request);
177706f2543Smrg    return 0;
178706f2543Smrg}
179706f2543Smrg
180706f2543Smrg#ifdef GLXEXT
181706f2543Smrgstatic int dmxNOPErrorHandler(Display *dpy, XErrorEvent *ev)
182706f2543Smrg{
183706f2543Smrg    return 0;
184706f2543Smrg}
185706f2543Smrg#endif
186706f2543Smrg
187706f2543SmrgBool dmxOpenDisplay(DMXScreenInfo *dmxScreen)
188706f2543Smrg{
189706f2543Smrg    if (!(dmxScreen->beDisplay = XOpenDisplay(dmxScreen->name)))
190706f2543Smrg	return FALSE;
191706f2543Smrg
192706f2543Smrg    dmxPropertyDisplay(dmxScreen);
193706f2543Smrg    return TRUE;
194706f2543Smrg}
195706f2543Smrg
196706f2543Smrgvoid dmxSetErrorHandler(DMXScreenInfo *dmxScreen)
197706f2543Smrg{
198706f2543Smrg    XSetErrorHandler(dmxErrorHandler);
199706f2543Smrg}
200706f2543Smrg
201706f2543Smrgstatic void dmxPrintScreenInfo(DMXScreenInfo *dmxScreen)
202706f2543Smrg{
203706f2543Smrg    XWindowAttributes attribs;
204706f2543Smrg    int               ndepths = 0, *depths = NULL;
205706f2543Smrg    int               i;
206706f2543Smrg    Display           *dpy   = dmxScreen->beDisplay;
207706f2543Smrg    Screen            *s     = DefaultScreenOfDisplay(dpy);
208706f2543Smrg    int               scr    = DefaultScreen(dpy);
209706f2543Smrg
210706f2543Smrg    XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs);
211706f2543Smrg    if (!(depths = XListDepths(dpy, scr, &ndepths))) ndepths = 0;
212706f2543Smrg
213706f2543Smrg    dmxLogOutput(dmxScreen, "Name of display: %s\n", DisplayString(dpy));
214706f2543Smrg    dmxLogOutput(dmxScreen, "Version number:  %d.%d\n",
215706f2543Smrg                 ProtocolVersion(dpy), ProtocolRevision(dpy));
216706f2543Smrg    dmxLogOutput(dmxScreen, "Vendor string:   %s\n", ServerVendor(dpy));
217706f2543Smrg    if (!strstr(ServerVendor(dpy), "XFree86")) {
218706f2543Smrg        dmxLogOutput(dmxScreen, "Vendor release:  %d\n", VendorRelease(dpy));
219706f2543Smrg    } else {
220706f2543Smrg                                /* This code based on xdpyinfo.c */
221706f2543Smrg    	int v = VendorRelease(dpy);
222706f2543Smrg        int major = -1, minor = -1, patch = -1, subpatch = -1;
223706f2543Smrg
224706f2543Smrg        if (v < 336)
225706f2543Smrg            major = v / 100, minor = (v / 10) % 10, patch = v % 10;
226706f2543Smrg        else if (v < 3900) {
227706f2543Smrg            major = v / 1000;
228706f2543Smrg            minor = (v / 100) % 10;
229706f2543Smrg            if (((v / 10) % 10) || (v % 10)) {
230706f2543Smrg                patch = (v / 10) % 10;
231706f2543Smrg                if (v % 10) subpatch = v % 10;
232706f2543Smrg            }
233706f2543Smrg        } else if (v < 40000000) {
234706f2543Smrg            major = v / 1000;
235706f2543Smrg            minor = (v / 10) % 10;
236706f2543Smrg            if (v % 10) patch = v % 10;
237706f2543Smrg	} else {
238706f2543Smrg            major = v / 10000000;
239706f2543Smrg            minor = (v / 100000) % 100;
240706f2543Smrg            patch = (v / 1000) % 100;
241706f2543Smrg            if (v % 1000) subpatch = v % 1000;
242706f2543Smrg	}
243706f2543Smrg        dmxLogOutput(dmxScreen, "Vendor release:  %d (XFree86 version: %d.%d",
244706f2543Smrg                     v, major, minor);
245706f2543Smrg        if (patch > 0)    dmxLogOutputCont(dmxScreen, ".%d", patch);
246706f2543Smrg        if (subpatch > 0) dmxLogOutputCont(dmxScreen, ".%d", subpatch);
247706f2543Smrg        dmxLogOutputCont(dmxScreen, ")\n");
248706f2543Smrg    }
249706f2543Smrg
250706f2543Smrg
251706f2543Smrg    dmxLogOutput(dmxScreen, "Dimensions:      %dx%d pixels\n",
252706f2543Smrg                 attribs.width, attribs.height);
253706f2543Smrg    dmxLogOutput(dmxScreen, "%d depths on screen %d: ", ndepths, scr);
254706f2543Smrg    for (i = 0; i < ndepths; i++)
255706f2543Smrg        dmxLogOutputCont(dmxScreen, "%c%d", i ? ',' : ' ', depths[i]);
256706f2543Smrg    dmxLogOutputCont(dmxScreen, "\n");
257706f2543Smrg    dmxLogOutput(dmxScreen, "Depth of root window:  %d plane%s (%d)\n",
258706f2543Smrg                 attribs.depth, attribs.depth == 1 ? "" : "s",
259706f2543Smrg                 DisplayPlanes(dpy, scr));
260706f2543Smrg    dmxLogOutput(dmxScreen, "Number of colormaps:   %d min, %d max\n",
261706f2543Smrg                 MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
262706f2543Smrg    dmxLogOutput(dmxScreen, "Options: backing-store %s, save-unders %s\n",
263706f2543Smrg                 (DoesBackingStore (s) == NotUseful) ? "no" :
264706f2543Smrg                 ((DoesBackingStore (s) == Always) ? "yes" : "when mapped"),
265706f2543Smrg                 DoesSaveUnders (s) ? "yes" : "no");
266706f2543Smrg    dmxLogOutput(dmxScreen, "Window Manager running: %s\n",
267706f2543Smrg		 (dmxScreen->WMRunningOnBE) ? "yes" : "no");
268706f2543Smrg
269706f2543Smrg    if (dmxScreen->WMRunningOnBE) {
270706f2543Smrg	dmxLogOutputWarning(dmxScreen,
271706f2543Smrg			    "Window manager running "
272706f2543Smrg			    "-- colormaps not supported\n");
273706f2543Smrg    }
274706f2543Smrg    XFree(depths);
275706f2543Smrg}
276706f2543Smrg
277706f2543Smrgvoid dmxGetScreenAttribs(DMXScreenInfo *dmxScreen)
278706f2543Smrg{
279706f2543Smrg    XWindowAttributes attribs;
280706f2543Smrg    Display           *dpy   = dmxScreen->beDisplay;
281706f2543Smrg#ifdef GLXEXT
282706f2543Smrg    int               dummy;
283706f2543Smrg#endif
284706f2543Smrg
285706f2543Smrg    XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &attribs);
286706f2543Smrg
287706f2543Smrg    dmxScreen->beWidth  = attribs.width;
288706f2543Smrg    dmxScreen->beHeight = attribs.height;
289706f2543Smrg
290706f2543Smrg                                /* Fill in missing geometry information */
291706f2543Smrg    if (dmxScreen->scrnXSign < 0) {
292706f2543Smrg        if (dmxScreen->scrnWidth) {
293706f2543Smrg            dmxScreen->scrnX   = (attribs.width - dmxScreen->scrnWidth
294706f2543Smrg				  - dmxScreen->scrnX);
295706f2543Smrg        } else {
296706f2543Smrg            dmxScreen->scrnWidth  = attribs.width - dmxScreen->scrnX;
297706f2543Smrg            dmxScreen->scrnX   = 0;
298706f2543Smrg        }
299706f2543Smrg    }
300706f2543Smrg    if (dmxScreen->scrnYSign < 0) {
301706f2543Smrg        if (dmxScreen->scrnHeight) {
302706f2543Smrg            dmxScreen->scrnY   = (attribs.height - dmxScreen->scrnHeight
303706f2543Smrg				  - dmxScreen->scrnY);
304706f2543Smrg        } else {
305706f2543Smrg            dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
306706f2543Smrg            dmxScreen->scrnY   = 0;
307706f2543Smrg        }
308706f2543Smrg    }
309706f2543Smrg    if (!dmxScreen->scrnWidth)
310706f2543Smrg        dmxScreen->scrnWidth  = attribs.width  - dmxScreen->scrnX;
311706f2543Smrg    if (!dmxScreen->scrnHeight)
312706f2543Smrg        dmxScreen->scrnHeight = attribs.height - dmxScreen->scrnY;
313706f2543Smrg
314706f2543Smrg    if (!dmxScreen->rootWidth)  dmxScreen->rootWidth  = dmxScreen->scrnWidth;
315706f2543Smrg    if (!dmxScreen->rootHeight) dmxScreen->rootHeight = dmxScreen->scrnHeight;
316706f2543Smrg    if (dmxScreen->rootWidth + dmxScreen->rootX > dmxScreen->scrnWidth)
317706f2543Smrg        dmxScreen->rootWidth = dmxScreen->scrnWidth - dmxScreen->rootX;
318706f2543Smrg    if (dmxScreen->rootHeight + dmxScreen->rootY > dmxScreen->scrnHeight)
319706f2543Smrg        dmxScreen->rootHeight = dmxScreen->scrnHeight - dmxScreen->rootY;
320706f2543Smrg
321706f2543Smrg    /* FIXME: Get these from the back-end server */
322706f2543Smrg    dmxScreen->beXDPI = 75;
323706f2543Smrg    dmxScreen->beYDPI = 75;
324706f2543Smrg
325706f2543Smrg    dmxScreen->beDepth  = attribs.depth; /* FIXME: verify that this
326706f2543Smrg					  * works always.  In
327706f2543Smrg					  * particular, this will work
328706f2543Smrg					  * well for depth=16, will fail
329706f2543Smrg					  * because of colormap issues
330706f2543Smrg					  * at depth 8.  More work needs
331706f2543Smrg					  * to be done here. */
332706f2543Smrg
333706f2543Smrg    if (dmxScreen->beDepth <= 8)       dmxScreen->beBPP = 8;
334706f2543Smrg    else if (dmxScreen->beDepth <= 16) dmxScreen->beBPP = 16;
335706f2543Smrg    else                               dmxScreen->beBPP = 32;
336706f2543Smrg
337706f2543Smrg#ifdef GLXEXT
338706f2543Smrg    /* get the majorOpcode for the back-end GLX extension */
339706f2543Smrg    XQueryExtension(dpy, "GLX", &dmxScreen->glxMajorOpcode,
340706f2543Smrg		    &dummy, &dmxScreen->glxErrorBase);
341706f2543Smrg#endif
342706f2543Smrg
343706f2543Smrg    dmxPrintScreenInfo(dmxScreen);
344706f2543Smrg    dmxLogOutput(dmxScreen, "%dx%d+%d+%d on %dx%d at depth=%d, bpp=%d\n",
345706f2543Smrg                 dmxScreen->scrnWidth, dmxScreen->scrnHeight,
346706f2543Smrg                 dmxScreen->scrnX, dmxScreen->scrnY,
347706f2543Smrg                 dmxScreen->beWidth, dmxScreen->beHeight,
348706f2543Smrg                 dmxScreen->beDepth, dmxScreen->beBPP);
349706f2543Smrg    if (dmxScreen->beDepth == 8)
350706f2543Smrg        dmxLogOutputWarning(dmxScreen,
351706f2543Smrg                            "Support for depth == 8 is not complete\n");
352706f2543Smrg}
353706f2543Smrg
354706f2543SmrgBool dmxGetVisualInfo(DMXScreenInfo *dmxScreen)
355706f2543Smrg{
356706f2543Smrg    int i;
357706f2543Smrg    XVisualInfo visinfo;
358706f2543Smrg
359706f2543Smrg    visinfo.screen = DefaultScreen(dmxScreen->beDisplay);
360706f2543Smrg    dmxScreen->beVisuals = XGetVisualInfo(dmxScreen->beDisplay,
361706f2543Smrg					  VisualScreenMask,
362706f2543Smrg					  &visinfo,
363706f2543Smrg					  &dmxScreen->beNumVisuals);
364706f2543Smrg
365706f2543Smrg    dmxScreen->beDefVisualIndex = -1;
366706f2543Smrg
367706f2543Smrg    if (defaultColorVisualClass >= 0 || dmxDepth > 0) {
368706f2543Smrg	for (i = 0; i < dmxScreen->beNumVisuals; i++)
369706f2543Smrg	    if (defaultColorVisualClass >= 0) {
370706f2543Smrg		if (dmxScreen->beVisuals[i].class == defaultColorVisualClass) {
371706f2543Smrg		    if (dmxDepth > 0) {
372706f2543Smrg			if (dmxScreen->beVisuals[i].depth == dmxDepth) {
373706f2543Smrg			    dmxScreen->beDefVisualIndex = i;
374706f2543Smrg			    break;
375706f2543Smrg			}
376706f2543Smrg		    } else {
377706f2543Smrg			dmxScreen->beDefVisualIndex = i;
378706f2543Smrg			break;
379706f2543Smrg		    }
380706f2543Smrg		}
381706f2543Smrg	    } else if (dmxScreen->beVisuals[i].depth == dmxDepth) {
382706f2543Smrg		dmxScreen->beDefVisualIndex = i;
383706f2543Smrg		break;
384706f2543Smrg	    }
385706f2543Smrg    } else {
386706f2543Smrg	visinfo.visualid =
387706f2543Smrg	    XVisualIDFromVisual(DefaultVisual(dmxScreen->beDisplay,
388706f2543Smrg					      visinfo.screen));
389706f2543Smrg
390706f2543Smrg	for (i = 0; i < dmxScreen->beNumVisuals; i++)
391706f2543Smrg	    if (visinfo.visualid == dmxScreen->beVisuals[i].visualid) {
392706f2543Smrg		dmxScreen->beDefVisualIndex = i;
393706f2543Smrg		break;
394706f2543Smrg	    }
395706f2543Smrg    }
396706f2543Smrg
397706f2543Smrg    for (i = 0; i < dmxScreen->beNumVisuals; i++)
398706f2543Smrg        dmxLogVisual(dmxScreen, &dmxScreen->beVisuals[i],
399706f2543Smrg                     (i == dmxScreen->beDefVisualIndex));
400706f2543Smrg
401706f2543Smrg    return dmxScreen->beDefVisualIndex >= 0;
402706f2543Smrg}
403706f2543Smrg
404706f2543Smrgvoid dmxGetColormaps(DMXScreenInfo *dmxScreen)
405706f2543Smrg{
406706f2543Smrg    int i;
407706f2543Smrg
408706f2543Smrg    dmxScreen->beNumDefColormaps = dmxScreen->beNumVisuals;
409706f2543Smrg    dmxScreen->beDefColormaps = malloc(dmxScreen->beNumDefColormaps *
410706f2543Smrg				       sizeof(*dmxScreen->beDefColormaps));
411706f2543Smrg
412706f2543Smrg    for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
413706f2543Smrg	dmxScreen->beDefColormaps[i] =
414706f2543Smrg	    XCreateColormap(dmxScreen->beDisplay,
415706f2543Smrg			    DefaultRootWindow(dmxScreen->beDisplay),
416706f2543Smrg			    dmxScreen->beVisuals[i].visual,
417706f2543Smrg			    AllocNone);
418706f2543Smrg
419706f2543Smrg    dmxScreen->beBlackPixel = BlackPixel(dmxScreen->beDisplay,
420706f2543Smrg					 DefaultScreen(dmxScreen->beDisplay));
421706f2543Smrg    dmxScreen->beWhitePixel = WhitePixel(dmxScreen->beDisplay,
422706f2543Smrg					 DefaultScreen(dmxScreen->beDisplay));
423706f2543Smrg}
424706f2543Smrg
425706f2543Smrgvoid dmxGetPixmapFormats(DMXScreenInfo *dmxScreen)
426706f2543Smrg{
427706f2543Smrg    dmxScreen->beDepths =
428706f2543Smrg	XListDepths(dmxScreen->beDisplay, DefaultScreen(dmxScreen->beDisplay),
429706f2543Smrg		    &dmxScreen->beNumDepths);
430706f2543Smrg
431706f2543Smrg    dmxScreen->bePixmapFormats =
432706f2543Smrg	XListPixmapFormats(dmxScreen->beDisplay,
433706f2543Smrg			   &dmxScreen->beNumPixmapFormats);
434706f2543Smrg}
435706f2543Smrg
436706f2543Smrgstatic Bool dmxSetPixmapFormats(ScreenInfo *pScreenInfo,
437706f2543Smrg				DMXScreenInfo *dmxScreen)
438706f2543Smrg{
439706f2543Smrg    XPixmapFormatValues *bePixmapFormat;
440706f2543Smrg    PixmapFormatRec     *format;
441706f2543Smrg    int                  i, j;
442706f2543Smrg
443706f2543Smrg    pScreenInfo->imageByteOrder = ImageByteOrder(dmxScreen->beDisplay);
444706f2543Smrg    pScreenInfo->bitmapScanlineUnit = BitmapUnit(dmxScreen->beDisplay);
445706f2543Smrg    pScreenInfo->bitmapScanlinePad = BitmapPad(dmxScreen->beDisplay);
446706f2543Smrg    pScreenInfo->bitmapBitOrder = BitmapBitOrder(dmxScreen->beDisplay);
447706f2543Smrg
448706f2543Smrg    pScreenInfo->numPixmapFormats = 0;
449706f2543Smrg    for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
450706f2543Smrg	bePixmapFormat = &dmxScreen->bePixmapFormats[i];
451706f2543Smrg	for (j = 0; j < dmxScreen->beNumDepths; j++)
452706f2543Smrg	    if ((bePixmapFormat->depth == 1) ||
453706f2543Smrg		(bePixmapFormat->depth == dmxScreen->beDepths[j])) {
454706f2543Smrg		format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats];
455706f2543Smrg
456706f2543Smrg		format->depth        = bePixmapFormat->depth;
457706f2543Smrg		format->bitsPerPixel = bePixmapFormat->bits_per_pixel;
458706f2543Smrg		format->scanlinePad  = bePixmapFormat->scanline_pad;
459706f2543Smrg
460706f2543Smrg		pScreenInfo->numPixmapFormats++;
461706f2543Smrg		break;
462706f2543Smrg	    }
463706f2543Smrg    }
464706f2543Smrg
465706f2543Smrg    return TRUE;
466706f2543Smrg}
467706f2543Smrg
468706f2543Smrgvoid dmxCheckForWM(DMXScreenInfo *dmxScreen)
469706f2543Smrg{
470706f2543Smrg    Status status;
471706f2543Smrg    XWindowAttributes xwa;
472706f2543Smrg
473706f2543Smrg    status = XGetWindowAttributes(dmxScreen->beDisplay,
474706f2543Smrg				  DefaultRootWindow(dmxScreen->beDisplay),
475706f2543Smrg				  &xwa);
476706f2543Smrg    dmxScreen->WMRunningOnBE =
477706f2543Smrg	(status &&
478706f2543Smrg	 ((xwa.all_event_masks & SubstructureRedirectMask) ||
479706f2543Smrg	  (xwa.all_event_masks & SubstructureNotifyMask)));
480706f2543Smrg}
481706f2543Smrg
482706f2543Smrg/** Initialize the display and collect relevant information about the
483706f2543Smrg *  display properties */
484706f2543Smrgstatic void dmxDisplayInit(DMXScreenInfo *dmxScreen)
485706f2543Smrg{
486706f2543Smrg    if (!dmxOpenDisplay(dmxScreen))
487706f2543Smrg	dmxLog(dmxFatal,
488706f2543Smrg               "dmxOpenDisplay: Unable to open display %s\n",
489706f2543Smrg               dmxScreen->name);
490706f2543Smrg
491706f2543Smrg    dmxSetErrorHandler(dmxScreen);
492706f2543Smrg    dmxCheckForWM(dmxScreen);
493706f2543Smrg    dmxGetScreenAttribs(dmxScreen);
494706f2543Smrg
495706f2543Smrg    if (!dmxGetVisualInfo(dmxScreen))
496706f2543Smrg	dmxLog(dmxFatal, "dmxGetVisualInfo: No matching visuals found\n");
497706f2543Smrg
498706f2543Smrg    dmxGetColormaps(dmxScreen);
499706f2543Smrg    dmxGetPixmapFormats(dmxScreen);
500706f2543Smrg}
501706f2543Smrg
502706f2543Smrg/* If this doesn't compile, just add || defined(yoursystem) to the line
503706f2543Smrg * below.  This information is to help with bug reports and is not
504706f2543Smrg * critical. */
505706f2543Smrg#if !defined(_POSIX_SOURCE)
506706f2543Smrgstatic const char *dmxExecOS(void) { return ""; }
507706f2543Smrg#else
508706f2543Smrg#include <sys/utsname.h>
509706f2543Smrgstatic const char *dmxExecOS(void)
510706f2543Smrg{
511706f2543Smrg    static char buffer[128];
512706f2543Smrg    static int  initialized = 0;
513706f2543Smrg    struct utsname u;
514706f2543Smrg
515706f2543Smrg    if (!initialized++) {
516706f2543Smrg        memset(buffer, 0, sizeof(buffer));
517706f2543Smrg        uname(&u);
518706f2543Smrg        XmuSnprintf(buffer, sizeof(buffer)-1, "%s %s %s",
519706f2543Smrg                    u.sysname, u.release, u.version);
520706f2543Smrg    }
521706f2543Smrg    return buffer;
522706f2543Smrg}
523706f2543Smrg#endif
524706f2543Smrg
525706f2543Smrgstatic const char *dmxBuildCompiler(void)
526706f2543Smrg{
527706f2543Smrg    static char buffer[128];
528706f2543Smrg    static int  initialized = 0;
529706f2543Smrg
530706f2543Smrg    if (!initialized++) {
531706f2543Smrg        memset(buffer, 0, sizeof(buffer));
532706f2543Smrg#if defined(__GNUC__) && defined(__GNUC_MINOR__) &&defined(__GNUC_PATCHLEVEL__)
533706f2543Smrg        XmuSnprintf(buffer, sizeof(buffer)-1, "gcc %d.%d.%d",
534706f2543Smrg                    __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
535706f2543Smrg#endif
536706f2543Smrg    }
537706f2543Smrg    return buffer;
538706f2543Smrg}
539706f2543Smrg
540706f2543Smrgstatic const char *dmxExecHost(void)
541706f2543Smrg{
542706f2543Smrg    static char buffer[128];
543706f2543Smrg    static int  initialized = 0;
544706f2543Smrg
545706f2543Smrg    if (!initialized++) {
546706f2543Smrg        memset(buffer, 0, sizeof(buffer));
547706f2543Smrg        XmuGetHostname(buffer, sizeof(buffer) - 1);
548706f2543Smrg    }
549706f2543Smrg    return buffer;
550706f2543Smrg}
551706f2543Smrg
552706f2543Smrg/** This routine is called in Xserver/dix/main.c from \a main(). */
553706f2543Smrgvoid InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
554706f2543Smrg{
555706f2543Smrg    int                  i;
556706f2543Smrg    static unsigned long dmxGeneration = 0;
557706f2543Smrg#ifdef GLXEXT
558706f2543Smrg    Bool                 glxSupported  = TRUE;
559706f2543Smrg#endif
560706f2543Smrg
561706f2543Smrg    if (dmxGeneration != serverGeneration) {
562706f2543Smrg	int vendrel = VENDOR_RELEASE;
563706f2543Smrg        int major, minor, year, month, day;
564706f2543Smrg
565706f2543Smrg        dmxGeneration = serverGeneration;
566706f2543Smrg
567706f2543Smrg        major    = vendrel / 100000000;
568706f2543Smrg        vendrel -= major   * 100000000;
569706f2543Smrg        minor    = vendrel /   1000000;
570706f2543Smrg        vendrel -= minor   *   1000000;
571706f2543Smrg        year     = vendrel /     10000;
572706f2543Smrg        vendrel -= year    *     10000;
573706f2543Smrg        month    = vendrel /       100;
574706f2543Smrg        vendrel -= month   *       100;
575706f2543Smrg        day      = vendrel;
576706f2543Smrg
577706f2543Smrg                                /* Add other epoch tests here */
578706f2543Smrg        if (major > 0 && minor > 0) year += 2000;
579706f2543Smrg
580706f2543Smrg        dmxLog(dmxInfo, "Generation:         %d\n", dmxGeneration);
581706f2543Smrg        dmxLog(dmxInfo, "DMX version:        %d.%d.%02d%02d%02d (%s)\n",
582706f2543Smrg               major, minor, year, month, day, VENDOR_STRING);
583706f2543Smrg
584706f2543Smrg        SetVendorRelease(VENDOR_RELEASE);
585706f2543Smrg        SetVendorString(VENDOR_STRING);
586706f2543Smrg
587706f2543Smrg        if (dmxGeneration == 1) {
588706f2543Smrg            dmxLog(dmxInfo, "DMX Build OS:       %s (%s)\n", OSNAME, OSVENDOR);
589706f2543Smrg            dmxLog(dmxInfo, "DMX Build Compiler: %s\n", dmxBuildCompiler());
590706f2543Smrg            dmxLog(dmxInfo, "DMX Execution OS:   %s\n", dmxExecOS());
591706f2543Smrg            dmxLog(dmxInfo, "DMX Execution Host: %s\n", dmxExecHost());
592706f2543Smrg        }
593706f2543Smrg        dmxLog(dmxInfo, "MAXSCREENS:         %d\n", MAXSCREENS);
594706f2543Smrg
595706f2543Smrg        for (i = 0; i < dmxNumScreens; i++) {
596706f2543Smrg            if (dmxScreens[i].beDisplay)
597706f2543Smrg                dmxLog(dmxWarning, "Display \"%s\" still open\n",
598706f2543Smrg                       dmxScreens[i].name);
599706f2543Smrg            dmxStatFree(dmxScreens[i].stat);
600706f2543Smrg            dmxScreens[i].stat = NULL;
601706f2543Smrg        }
602706f2543Smrg        for (i = 0; i < dmxNumInputs; i++) dmxInputFree(&dmxInputs[i]);
603706f2543Smrg        free(dmxScreens);
604706f2543Smrg        free(dmxInputs);
605706f2543Smrg        dmxScreens    = NULL;
606706f2543Smrg        dmxInputs     = NULL;
607706f2543Smrg        dmxNumScreens = 0;
608706f2543Smrg        dmxNumInputs  = 0;
609706f2543Smrg    }
610706f2543Smrg
611706f2543Smrg    /* Make sure that the command-line arguments are sane. */
612706f2543Smrg    if (dmxAddRemoveScreens && dmxGLXProxy) {
613706f2543Smrg	/* Currently it is not possible to support GLX and Render
614706f2543Smrg	 * extensions with dynamic screen addition/removal due to the
615706f2543Smrg	 * state that each extension keeps, which cannot be restored. */
616706f2543Smrg        dmxLog(dmxWarning,
617706f2543Smrg	       "GLX Proxy and Render extensions do not yet support dynamic\n");
618706f2543Smrg        dmxLog(dmxWarning,
619706f2543Smrg	       "screen addition and removal.  Please specify -noglxproxy\n");
620706f2543Smrg        dmxLog(dmxWarning,
621706f2543Smrg	       "and -norender on the command line or in the configuration\n");
622706f2543Smrg        dmxLog(dmxWarning,
623706f2543Smrg	       "file to disable these two extensions if you wish to use\n");
624706f2543Smrg        dmxLog(dmxWarning,
625706f2543Smrg	       "the dynamic addition and removal of screens support.\n");
626706f2543Smrg        dmxLog(dmxFatal,
627706f2543Smrg	       "Dynamic screen addition/removal error (see above).\n");
628706f2543Smrg    }
629706f2543Smrg
630706f2543Smrg    /* ddxProcessArgument has been called at this point, but any data
631706f2543Smrg     * from the configuration file has not been applied.  Do so, and be
632706f2543Smrg     * sure we have at least one back-end display. */
633706f2543Smrg    dmxConfigConfigure();
634706f2543Smrg    if (!dmxNumScreens)
635706f2543Smrg        dmxLog(dmxFatal, "InitOutput: no back-end displays found\n");
636706f2543Smrg    if (!dmxNumInputs)
637706f2543Smrg        dmxLog(dmxInfo, "InitOutput: no inputs found\n");
638706f2543Smrg
639706f2543Smrg    /* Disable lazy window creation optimization if offscreen
640706f2543Smrg     * optimization is disabled */
641706f2543Smrg    if (!dmxOffScreenOpt && dmxLazyWindowCreation) {
642706f2543Smrg        dmxLog(dmxInfo,
643706f2543Smrg	       "InitOutput: Disabling lazy window creation optimization\n");
644706f2543Smrg        dmxLog(dmxInfo,
645706f2543Smrg	       "            since it requires the offscreen optimization\n");
646706f2543Smrg        dmxLog(dmxInfo,
647706f2543Smrg	       "            to function properly.\n");
648706f2543Smrg	dmxLazyWindowCreation = FALSE;
649706f2543Smrg    }
650706f2543Smrg
651706f2543Smrg    /* Open each display and gather information about it. */
652706f2543Smrg    for (i = 0; i < dmxNumScreens; i++)
653706f2543Smrg        dmxDisplayInit(&dmxScreens[i]);
654706f2543Smrg
655706f2543Smrg#if PANORAMIX
656706f2543Smrg    /* Register a Xinerama callback which will run from within
657706f2543Smrg     * PanoramiXCreateConnectionBlock.  We can use the callback to
658706f2543Smrg     * determine if Xinerama is loaded and to check the visuals
659706f2543Smrg     * determined by PanoramiXConsolidate. */
660706f2543Smrg    XineramaRegisterConnectionBlockCallback(dmxConnectionBlockCallback);
661706f2543Smrg#endif
662706f2543Smrg
663706f2543Smrg    /* Since we only have a single screen thus far, we only need to set
664706f2543Smrg       the pixmap formats to match that screen.  FIXME: this isn't true.*/
665706f2543Smrg    if (!dmxSetPixmapFormats(pScreenInfo, &dmxScreens[0])) return;
666706f2543Smrg
667706f2543Smrg    /* Might want to install a signal handler to allow cleaning up after
668706f2543Smrg     * unexpected signals.  The DIX/OS layer already handles SIGINT and
669706f2543Smrg     * SIGTERM, so everything is OK for expected signals. --DD
670706f2543Smrg     *
671706f2543Smrg     * SIGHUP, SIGINT, and SIGTERM are trapped in os/connection.c
672706f2543Smrg     * SIGQUIT is another common signal that is sent from the keyboard.
673706f2543Smrg     * Trap it here, to ensure that the keyboard modifier map and other
674706f2543Smrg     * state for the input devices are restored. (This makes the
675706f2543Smrg     * behavior of SIGQUIT somewhat unexpected, since it will be the
676706f2543Smrg     * same as the behavior of SIGINT.  However, leaving the modifier
677706f2543Smrg     * map of the input devices empty is even more unexpected.) --RF
678706f2543Smrg     */
679706f2543Smrg    OsSignal(SIGQUIT, GiveUp);
680706f2543Smrg
681706f2543Smrg#ifdef GLXEXT
682706f2543Smrg    /* Check if GLX extension exists on all back-end servers */
683706f2543Smrg    for (i = 0; i < dmxNumScreens; i++)
684706f2543Smrg	glxSupported &= (dmxScreens[i].glxMajorOpcode > 0);
685706f2543Smrg#endif
686706f2543Smrg
687706f2543Smrg    /* Tell dix layer about the backend displays */
688706f2543Smrg    for (i = 0; i < dmxNumScreens; i++) {
689706f2543Smrg
690706f2543Smrg#ifdef GLXEXT
691706f2543Smrg	if (glxSupported) {
692706f2543Smrg	    /*
693706f2543Smrg	     * Builds GLX configurations from the list of visuals
694706f2543Smrg	     * supported by the back-end server, and give that
695706f2543Smrg	     * configuration list to the glx layer - so that he will
696706f2543Smrg	     * build the visuals accordingly.
697706f2543Smrg	     */
698706f2543Smrg
699706f2543Smrg	    DMXScreenInfo       *dmxScreen    = &dmxScreens[i];
700706f2543Smrg	    __GLXvisualConfig   *configs      = NULL;
701706f2543Smrg	    dmxGlxVisualPrivate **configprivs = NULL;
702706f2543Smrg	    int                 nconfigs      = 0;
703706f2543Smrg	    int                 (*oldErrorHandler)(Display *, XErrorEvent *);
704706f2543Smrg	    int                 i;
705706f2543Smrg
706706f2543Smrg	    /* Catch errors if when using an older GLX w/o FBconfigs */
707706f2543Smrg	    oldErrorHandler = XSetErrorHandler(dmxNOPErrorHandler);
708706f2543Smrg
709706f2543Smrg	    /* Get FBConfigs of the back-end server */
710706f2543Smrg	    dmxScreen->fbconfigs = GetGLXFBConfigs(dmxScreen->beDisplay,
711706f2543Smrg						   dmxScreen->glxMajorOpcode,
712706f2543Smrg						   &dmxScreen->numFBConfigs);
713706f2543Smrg
714706f2543Smrg	    XSetErrorHandler(oldErrorHandler);
715706f2543Smrg
716706f2543Smrg	    dmxScreen->glxVisuals =
717706f2543Smrg		GetGLXVisualConfigs(dmxScreen->beDisplay,
718706f2543Smrg				    DefaultScreen(dmxScreen->beDisplay),
719706f2543Smrg				    &dmxScreen->numGlxVisuals);
720706f2543Smrg
721706f2543Smrg	    if (dmxScreen->fbconfigs) {
722706f2543Smrg		configs =
723706f2543Smrg		    GetGLXVisualConfigsFromFBConfigs(dmxScreen->fbconfigs,
724706f2543Smrg						     dmxScreen->numFBConfigs,
725706f2543Smrg						     dmxScreen->beVisuals,
726706f2543Smrg						     dmxScreen->beNumVisuals,
727706f2543Smrg						     dmxScreen->glxVisuals,
728706f2543Smrg						     dmxScreen->numGlxVisuals,
729706f2543Smrg						     &nconfigs);
730706f2543Smrg	    } else {
731706f2543Smrg		configs = dmxScreen->glxVisuals;
732706f2543Smrg		nconfigs = dmxScreen->numGlxVisuals;
733706f2543Smrg	    }
734706f2543Smrg
735706f2543Smrg	    configprivs = malloc(nconfigs * sizeof(dmxGlxVisualPrivate*));
736706f2543Smrg
737706f2543Smrg	    if (configs != NULL && configprivs != NULL) {
738706f2543Smrg
739706f2543Smrg		/* Initialize our private info for each visual
740706f2543Smrg		 * (currently only x_visual_depth and x_visual_class)
741706f2543Smrg		 */
742706f2543Smrg		for (i = 0; i < nconfigs; i++) {
743706f2543Smrg
744706f2543Smrg		    configprivs[i] = (dmxGlxVisualPrivate *)
745706f2543Smrg			malloc(sizeof(dmxGlxVisualPrivate));
746706f2543Smrg		    configprivs[i]->x_visual_depth = 0;
747706f2543Smrg		    configprivs[i]->x_visual_class = 0;
748706f2543Smrg
749706f2543Smrg		    /* Find the visual depth */
750706f2543Smrg		    if (configs[i].vid > 0) {
751706f2543Smrg			int  j;
752706f2543Smrg			for (j = 0; j < dmxScreen->beNumVisuals; j++) {
753706f2543Smrg			    if (dmxScreen->beVisuals[j].visualid ==
754706f2543Smrg				configs[i].vid) {
755706f2543Smrg				configprivs[i]->x_visual_depth =
756706f2543Smrg				    dmxScreen->beVisuals[j].depth;
757706f2543Smrg				configprivs[i]->x_visual_class =
758706f2543Smrg				    dmxScreen->beVisuals[j].class;
759706f2543Smrg				break;
760706f2543Smrg			    }
761706f2543Smrg			}
762706f2543Smrg		    }
763706f2543Smrg		}
764706f2543Smrg
765706f2543Smrg                XFlush(dmxScreen->beDisplay);
766706f2543Smrg	    }
767706f2543Smrg	}
768706f2543Smrg#endif  /* GLXEXT */
769706f2543Smrg
770706f2543Smrg	AddScreen(dmxScreenInit, argc, argv);
771706f2543Smrg    }
772706f2543Smrg
773706f2543Smrg    /* Compute origin information. */
774706f2543Smrg    dmxInitOrigins();
775706f2543Smrg
776706f2543Smrg    /* Compute overlap information. */
777706f2543Smrg    dmxInitOverlap();
778706f2543Smrg
779706f2543Smrg    /* Make sure there is a global width/height available */
780706f2543Smrg    dmxComputeWidthHeight(DMX_NO_RECOMPUTE_BOUNDING_BOX);
781706f2543Smrg
782706f2543Smrg    /* FIXME: The following is temporarily placed here.  When the DMX
783706f2543Smrg     * extension is available, it will be move there.
784706f2543Smrg     */
785706f2543Smrg    dmxInitFonts();
786706f2543Smrg
787706f2543Smrg    /* Initialize the render extension */
788706f2543Smrg    if (!noRenderExtension)
789706f2543Smrg	dmxInitRender();
790706f2543Smrg
791706f2543Smrg    /* Initialized things that need timer hooks */
792706f2543Smrg    dmxStatInit();
793706f2543Smrg    dmxSyncInit();              /* Calls RegisterBlockAndWakeupHandlers */
794706f2543Smrg
795706f2543Smrg    dmxLog(dmxInfo, "Shadow framebuffer support %s\n",
796706f2543Smrg	   dmxShadowFB ? "enabled" : "disabled");
797706f2543Smrg}
798706f2543Smrg
799706f2543Smrg/* RATS: Assuming the fp string (which comes from the command-line argv
800706f2543Smrg         vector) is NULL-terminated, the buffer is large enough for the
801706f2543Smrg         strcpy. */
802706f2543Smrgstatic void dmxSetDefaultFontPath(char *fp)
803706f2543Smrg{
804706f2543Smrg    int fplen = strlen(fp) + 1;
805706f2543Smrg
806706f2543Smrg    if (dmxFontPath) {
807706f2543Smrg	int len;
808706f2543Smrg
809706f2543Smrg	len = strlen(dmxFontPath);
810706f2543Smrg	dmxFontPath = realloc(dmxFontPath, len+fplen+1);
811706f2543Smrg	dmxFontPath[len] = ',';
812706f2543Smrg	strncpy(&dmxFontPath[len+1], fp, fplen);
813706f2543Smrg    } else {
814706f2543Smrg	dmxFontPath = malloc(fplen);
815706f2543Smrg	strncpy(dmxFontPath, fp, fplen);
816706f2543Smrg    }
817706f2543Smrg
818706f2543Smrg    defaultFontPath = dmxFontPath;
819706f2543Smrg}
820706f2543Smrg
821706f2543Smrg/** This function is called in Xserver/os/utils.c from \a AbortServer().
822706f2543Smrg * We must ensure that backend and console state is restored in the
823706f2543Smrg * event the server shutdown wasn't clean. */
824706f2543Smrgvoid AbortDDX(void)
825706f2543Smrg{
826706f2543Smrg    int i;
827706f2543Smrg
828706f2543Smrg    for (i=0; i < dmxNumScreens; i++) {
829706f2543Smrg        DMXScreenInfo *dmxScreen = &dmxScreens[i];
830706f2543Smrg
831706f2543Smrg        if (dmxScreen->beDisplay) XCloseDisplay(dmxScreen->beDisplay);
832706f2543Smrg        dmxScreen->beDisplay = NULL;
833706f2543Smrg    }
834706f2543Smrg}
835706f2543Smrg
836706f2543Smrg#ifdef DDXBEFORERESET
837706f2543Smrgvoid ddxBeforeReset(void)
838706f2543Smrg{
839706f2543Smrg}
840706f2543Smrg#endif
841706f2543Smrg
842706f2543Smrg/** This function is called in Xserver/dix/main.c from \a main() when
843706f2543Smrg * dispatchException & DE_TERMINATE (which is the only way to exit the
844706f2543Smrg * main loop without an interruption. */
845706f2543Smrgvoid ddxGiveUp(void)
846706f2543Smrg{
847706f2543Smrg    AbortDDX();
848706f2543Smrg}
849706f2543Smrg
850706f2543Smrg/** This function is called in Xserver/os/osinit.c from \a OsInit(). */
851706f2543Smrgvoid OsVendorInit(void)
852706f2543Smrg{
853706f2543Smrg}
854706f2543Smrg
855706f2543Smrg/** This function is called in Xserver/os/utils.c from \a FatalError()
856706f2543Smrg * and \a VFatalError().  (Note that setting the function pointer \a
857706f2543Smrg * OsVendorVErrorFProc will cause \a VErrorF() (which is called by the
858706f2543Smrg * two routines mentioned here, as well as by others) to use the
859706f2543Smrg * referenced routine instead of \a vfprintf().) */
860706f2543Smrgvoid OsVendorFatalError(void)
861706f2543Smrg{
862706f2543Smrg}
863706f2543Smrg
864706f2543Smrg/** Process our command line arguments. */
865706f2543Smrgint ddxProcessArgument(int argc, char *argv[], int i)
866706f2543Smrg{
867706f2543Smrg    int retval = 0;
868706f2543Smrg
869706f2543Smrg    if (!strcmp(argv[i], "-display")) {
870706f2543Smrg	if (++i < argc) dmxConfigStoreDisplay(argv[i]);
871706f2543Smrg        retval = 2;
872706f2543Smrg    } else if (!strcmp(argv[i], "-inputfrom") || !strcmp(argv[i], "-input")) {
873706f2543Smrg	if (++i < argc) dmxConfigStoreInput(argv[i]);
874706f2543Smrg        retval = 2;
875706f2543Smrg    } else if (!strcmp(argv[i], "-xinputfrom") || !strcmp(argv[i],"-xinput")) {
876706f2543Smrg        if (++i < argc) dmxConfigStoreXInput(argv[i]);
877706f2543Smrg        retval = 2;
878706f2543Smrg    } else if (!strcmp(argv[i], "-noshadowfb")) {
879706f2543Smrg        dmxLog(dmxWarning,
880706f2543Smrg               "-noshadowfb has been deprecated "
881706f2543Smrg	       "since it is now the default\n");
882706f2543Smrg	dmxShadowFB = FALSE;
883706f2543Smrg	retval = 1;
884706f2543Smrg    } else if (!strcmp(argv[i], "-nomulticursor")) {
885706f2543Smrg        dmxCursorNoMulti();
886706f2543Smrg	retval = 1;
887706f2543Smrg    } else if (!strcmp(argv[i], "-shadowfb")) {
888706f2543Smrg	dmxShadowFB = TRUE;
889706f2543Smrg	retval = 1;
890706f2543Smrg    } else if (!strcmp(argv[i], "-configfile")) {
891706f2543Smrg        if (++i < argc) dmxConfigStoreFile(argv[i]);
892706f2543Smrg        retval = 2;
893706f2543Smrg    } else if (!strcmp(argv[i], "-config")) {
894706f2543Smrg        if (++i < argc) dmxConfigStoreConfig(argv[i]);
895706f2543Smrg        retval = 2;
896706f2543Smrg    } else if (!strcmp(argv[i], "-fontpath")) {
897706f2543Smrg        if (++i < argc) dmxSetDefaultFontPath(argv[i]);
898706f2543Smrg        retval = 2;
899706f2543Smrg    } else if (!strcmp(argv[i], "-stat")) {
900706f2543Smrg        if ((i += 2) < argc) dmxStatActivate(argv[i-1], argv[i]);
901706f2543Smrg        retval = 3;
902706f2543Smrg    } else if (!strcmp(argv[i], "-syncbatch")) {
903706f2543Smrg        if (++i < argc) dmxSyncActivate(argv[i]);
904706f2543Smrg        retval = 2;
905706f2543Smrg    } else if (!strcmp(argv[i], "-nooffscreenopt")) {
906706f2543Smrg	dmxOffScreenOpt = FALSE;
907706f2543Smrg        retval = 1;
908706f2543Smrg    } else if (!strcmp(argv[i], "-nosubdivprims")) {
909706f2543Smrg	dmxSubdividePrimitives = FALSE;
910706f2543Smrg        retval = 1;
911706f2543Smrg    } else if (!strcmp(argv[i], "-nowindowopt")) {
912706f2543Smrg	dmxLazyWindowCreation = FALSE;
913706f2543Smrg        retval = 1;
914706f2543Smrg    } else if (!strcmp(argv[i], "-noxkb")) {
915706f2543Smrg	dmxUseXKB = FALSE;
916706f2543Smrg        retval = 1;
917706f2543Smrg    } else if (!strcmp(argv[i], "-depth")) {
918706f2543Smrg        if (++i < argc) dmxDepth = atoi(argv[i]);
919706f2543Smrg        retval = 2;
920706f2543Smrg    } else if (!strcmp(argv[i], "-norender")) {
921706f2543Smrg	noRenderExtension = TRUE;
922706f2543Smrg        retval = 1;
923706f2543Smrg#ifdef GLXEXT
924706f2543Smrg    } else if (!strcmp(argv[i], "-noglxproxy")) {
925706f2543Smrg	dmxGLXProxy = FALSE;
926706f2543Smrg        retval = 1;
927706f2543Smrg    } else if (!strcmp(argv[i], "-noglxswapgroup")) {
928706f2543Smrg	dmxGLXSwapGroupSupport = FALSE;
929706f2543Smrg        retval = 1;
930706f2543Smrg    } else if (!strcmp(argv[i], "-glxsyncswap")) {
931706f2543Smrg	dmxGLXSyncSwap = TRUE;
932706f2543Smrg        retval = 1;
933706f2543Smrg    } else if (!strcmp(argv[i], "-glxfinishswap")) {
934706f2543Smrg	dmxGLXFinishSwap = TRUE;
935706f2543Smrg        retval = 1;
936706f2543Smrg#endif
937706f2543Smrg    } else if (!strcmp(argv[i], "-ignorebadfontpaths")) {
938706f2543Smrg	dmxIgnoreBadFontPaths = TRUE;
939706f2543Smrg        retval = 1;
940706f2543Smrg    } else if (!strcmp(argv[i], "-addremovescreens")) {
941706f2543Smrg	dmxAddRemoveScreens = TRUE;
942706f2543Smrg        retval = 1;
943706f2543Smrg    } else if (!strcmp(argv[i], "-param")) {
944706f2543Smrg        if ((i += 2) < argc) {
945706f2543Smrg            if (!strcasecmp(argv[i-1], "xkbrules"))
946706f2543Smrg                dmxConfigSetXkbRules(argv[i]);
947706f2543Smrg            else if (!strcasecmp(argv[i-1], "xkbmodel"))
948706f2543Smrg                dmxConfigSetXkbModel(argv[i]);
949706f2543Smrg            else if (!strcasecmp(argv[i-1], "xkblayout"))
950706f2543Smrg                dmxConfigSetXkbLayout(argv[i]);
951706f2543Smrg            else if (!strcasecmp(argv[i-1], "xkbvariant"))
952706f2543Smrg                dmxConfigSetXkbVariant(argv[i]);
953706f2543Smrg            else if (!strcasecmp(argv[i-1], "xkboptions"))
954706f2543Smrg                dmxConfigSetXkbOptions(argv[i]);
955706f2543Smrg            else
956706f2543Smrg                dmxLog(dmxWarning,
957706f2543Smrg                       "-param requires: XkbRules, XkbModel, XkbLayout,"
958706f2543Smrg                       " XkbVariant, or XkbOptions\n");
959706f2543Smrg        }
960706f2543Smrg        retval = 3;
961706f2543Smrg    }
962706f2543Smrg    if (!serverGeneration) dmxConfigSetMaxScreens();
963706f2543Smrg    return retval;
964706f2543Smrg}
965706f2543Smrg
966706f2543Smrg/** Provide succinct usage information for the DMX server. */
967706f2543Smrgvoid ddxUseMsg(void)
968706f2543Smrg{
969706f2543Smrg    ErrorF("\n\nDevice Dependent Usage:\n");
970706f2543Smrg    ErrorF("-display string      Specify the back-end display(s)\n");
971706f2543Smrg    ErrorF("-input string        Specify input source for core device\n");
972706f2543Smrg    ErrorF("-xinput string       Specify input source for XInput device\n");
973706f2543Smrg    ErrorF("-shadowfb            Enable shadow frame buffer\n");
974706f2543Smrg    ErrorF("-configfile file     Read from a configuration file\n");
975706f2543Smrg    ErrorF("-config config       Select a specific configuration\n");
976706f2543Smrg    ErrorF("-nomulticursor       Turn of multiple cursor support\n");
977706f2543Smrg    ErrorF("-fontpath            Sets the default font path\n");
978706f2543Smrg    ErrorF("-stat inter scrns    Print out performance statistics\n");
979706f2543Smrg    ErrorF("-syncbatch inter     Set interval for XSync batching\n");
980706f2543Smrg    ErrorF("-nooffscreenopt      Disable offscreen optimization\n");
981706f2543Smrg    ErrorF("-nosubdivprims       Disable primitive subdivision\n");
982706f2543Smrg    ErrorF("                     optimization\n");
983706f2543Smrg    ErrorF("-nowindowopt         Disable lazy window creation optimization\n");
984706f2543Smrg    ErrorF("-noxkb               Disable use of the XKB extension with\n");
985706f2543Smrg    ErrorF("                     backend displays (cf. -kb).\n");
986706f2543Smrg    ErrorF("-depth               Specify the default root window depth\n");
987706f2543Smrg    ErrorF("-norender            Disable RENDER extension support\n");
988706f2543Smrg#ifdef GLXEXT
989706f2543Smrg    ErrorF("-noglxproxy          Disable GLX Proxy\n");
990706f2543Smrg    ErrorF("-noglxswapgroup      Disable swap group and swap barrier\n");
991706f2543Smrg    ErrorF("                     extensions in GLX proxy\n");
992706f2543Smrg    ErrorF("-glxsyncswap         Force XSync after swap buffers\n");
993706f2543Smrg    ErrorF("-glxfinishswap       Force glFinish after swap buffers\n");
994706f2543Smrg#endif
995706f2543Smrg    ErrorF("-ignorebadfontpaths  Ignore bad font paths during initialization\n");
996706f2543Smrg    ErrorF("-addremovescreens    Enable dynamic screen addition/removal\n");
997706f2543Smrg    ErrorF("-param ...           Specify configuration parameters (e.g.,\n");
998706f2543Smrg    ErrorF("                     XkbRules, XkbModel, XkbLayout, etc.)\n");
999706f2543Smrg    ErrorF("\n");
1000706f2543Smrg    ErrorF("    If the -input string matches a -display string, then input\n"
1001706f2543Smrg           "    is taken from that backend display.  (XInput cannot be taken\n"
1002706f2543Smrg           "    from a backend display.)  Placing \",console\" after the\n"
1003706f2543Smrg           "    display name will force a console window to be opened on\n"
1004706f2543Smrg           "    that display in addition to the backend input.  This is\n"
1005706f2543Smrg           "    useful if the backend window does not cover the whole\n"
1006706f2543Smrg           "    physical display.\n\n");
1007706f2543Smrg
1008706f2543Smrg    ErrorF("    Otherwise, if the -input or -xinput string specifies another\n"
1009706f2543Smrg           "    X display, then a console window will be created on that\n"
1010706f2543Smrg           "    display.  Placing \",windows\" or \",nowindows\" after the\n"
1011706f2543Smrg           "    display name will control the display of window outlines in\n"
1012706f2543Smrg           "    the console.\n\n");
1013706f2543Smrg
1014706f2543Smrg    ErrorF("    -input or -xinput dummy specifies no input.\n");
1015706f2543Smrg    ErrorF("    -input or -xinput local specifies the use of a raw keyboard,\n"
1016706f2543Smrg           "    mouse, or other (extension) device:\n"
1017706f2543Smrg           "        -input local,kbd,ps2 will use a ps2 mouse\n"
1018706f2543Smrg           "        -input local,kbd,ms  will use a serial mouse\n"
1019706f2543Smrg           "        -input local,usb-kbd,usb-mou will use USB devices \n"
1020706f2543Smrg           "        -xinput local,usb-oth will use a non-mouse and\n"
1021706f2543Smrg           "                non-keyboard USB device with XInput\n\n");
1022706f2543Smrg
1023706f2543Smrg    ErrorF("    Special Keys:\n");
1024706f2543Smrg    ErrorF("        Ctrl-Alt-g    Server grab/ungrab (console only)\n");
1025706f2543Smrg    ErrorF("        Ctrl-Alt-f    Fine (1-pixel) mouse mode (console only)\n");
1026706f2543Smrg    ErrorF("        Ctrl-Alt-q    Quit (core devices only)\n");
1027706f2543Smrg    ErrorF("        Ctrl-Alt-F*   Switch to VC (local only)\n");
1028706f2543Smrg}
1029