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 *
33706f2543Smrg */
34706f2543Smrg
35706f2543Smrg/** \file
36706f2543Smrg * This file provides support for screen initialization. */
37706f2543Smrg
38706f2543Smrg#ifdef HAVE_DMX_CONFIG_H
39706f2543Smrg#include <dmx-config.h>
40706f2543Smrg#endif
41706f2543Smrg
42706f2543Smrg#include "dmx.h"
43706f2543Smrg#include "dmxsync.h"
44706f2543Smrg#include "dmxshadow.h"
45706f2543Smrg#include "dmxscrinit.h"
46706f2543Smrg#include "dmxcursor.h"
47706f2543Smrg#include "dmxgc.h"
48706f2543Smrg#include "dmxgcops.h"
49706f2543Smrg#include "dmxwindow.h"
50706f2543Smrg#include "dmxpixmap.h"
51706f2543Smrg#include "dmxfont.h"
52706f2543Smrg#include "dmxcmap.h"
53706f2543Smrg#include "dmxprop.h"
54706f2543Smrg#include "dmxdpms.h"
55706f2543Smrg
56706f2543Smrg#include "dmxpict.h"
57706f2543Smrg
58706f2543Smrg#include "fb.h"
59706f2543Smrg#include "mipointer.h"
60706f2543Smrg#include "micmap.h"
61706f2543Smrg
62706f2543Smrgextern Bool dmxCloseScreen(int idx, ScreenPtr pScreen);
63706f2543Smrgstatic Bool dmxSaveScreen(ScreenPtr pScreen, int what);
64706f2543Smrg
65706f2543Smrgstatic unsigned long dmxGeneration;
66706f2543Smrgstatic unsigned long *dmxCursorGeneration;
67706f2543Smrg
68706f2543SmrgDevPrivateKeyRec dmxGCPrivateKeyRec;
69706f2543SmrgDevPrivateKeyRec dmxWinPrivateKeyRec;
70706f2543SmrgDevPrivateKeyRec dmxPixPrivateKeyRec;
71706f2543Smrgint dmxFontPrivateIndex;        /**< Private index for Fonts     */
72706f2543SmrgDevPrivateKeyRec dmxScreenPrivateKeyRec;
73706f2543SmrgDevPrivateKeyRec dmxColormapPrivateKeyRec;
74706f2543SmrgDevPrivateKeyRec dmxPictPrivateKeyRec;
75706f2543SmrgDevPrivateKeyRec dmxGlyphSetPrivateKeyRec;
76706f2543Smrg
77706f2543Smrg/** Initialize the parts of screen \a idx that require access to the
78706f2543Smrg *  back-end server. */
79706f2543Smrgvoid dmxBEScreenInit(int idx, ScreenPtr pScreen)
80706f2543Smrg{
81706f2543Smrg    DMXScreenInfo        *dmxScreen = &dmxScreens[idx];
82706f2543Smrg    XSetWindowAttributes  attribs;
83706f2543Smrg    XGCValues             gcvals;
84706f2543Smrg    unsigned long         mask;
85706f2543Smrg    int                   i, j;
86706f2543Smrg
87706f2543Smrg    /* FIXME: The dmxScreenInit() code currently assumes that it will
88706f2543Smrg     * not be called if the Xdmx server is started with this screen
89706f2543Smrg     * detached -- i.e., it assumes that dmxScreen->beDisplay is always
90706f2543Smrg     * valid.  This is not necessarily a valid assumption when full
91706f2543Smrg     * addition/removal of screens is implemented, but when this code is
92706f2543Smrg     * broken out for screen reattachment, then we will reevaluate this
93706f2543Smrg     * assumption.
94706f2543Smrg     */
95706f2543Smrg
96706f2543Smrg    pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay,
97706f2543Smrg				      DefaultScreen(dmxScreen->beDisplay));
98706f2543Smrg    pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay,
99706f2543Smrg					DefaultScreen(dmxScreen->beDisplay));
100706f2543Smrg
101706f2543Smrg    pScreen->whitePixel = dmxScreen->beWhitePixel;
102706f2543Smrg    pScreen->blackPixel = dmxScreen->beBlackPixel;
103706f2543Smrg
104706f2543Smrg    /* Handle screen savers and DPMS on the backend */
105706f2543Smrg    dmxDPMSInit(dmxScreen);
106706f2543Smrg
107706f2543Smrg    /* Create root window for screen */
108706f2543Smrg    mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
109706f2543Smrg    attribs.background_pixel = dmxScreen->beBlackPixel;
110706f2543Smrg    attribs.event_mask = (KeyPressMask
111706f2543Smrg                          | KeyReleaseMask
112706f2543Smrg                          | ButtonPressMask
113706f2543Smrg                          | ButtonReleaseMask
114706f2543Smrg                          | EnterWindowMask
115706f2543Smrg                          | LeaveWindowMask
116706f2543Smrg                          | PointerMotionMask
117706f2543Smrg                          | KeymapStateMask
118706f2543Smrg                          | FocusChangeMask);
119706f2543Smrg    attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex];
120706f2543Smrg    attribs.override_redirect = True;
121706f2543Smrg
122706f2543Smrg    dmxScreen->scrnWin =
123706f2543Smrg	XCreateWindow(dmxScreen->beDisplay,
124706f2543Smrg		      DefaultRootWindow(dmxScreen->beDisplay),
125706f2543Smrg		      dmxScreen->scrnX,
126706f2543Smrg		      dmxScreen->scrnY,
127706f2543Smrg		      dmxScreen->scrnWidth,
128706f2543Smrg		      dmxScreen->scrnHeight,
129706f2543Smrg		      0,
130706f2543Smrg		      pScreen->rootDepth,
131706f2543Smrg		      InputOutput,
132706f2543Smrg		      dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
133706f2543Smrg		      mask,
134706f2543Smrg		      &attribs);
135706f2543Smrg    dmxPropertyWindow(dmxScreen);
136706f2543Smrg
137706f2543Smrg    /*
138706f2543Smrg     * This turns off the cursor by defining a cursor with no visible
139706f2543Smrg     * components.
140706f2543Smrg     */
141706f2543Smrg    {
142706f2543Smrg	char noCursorData[] = {0, 0, 0, 0,
143706f2543Smrg			       0, 0, 0, 0};
144706f2543Smrg	Pixmap pixmap;
145706f2543Smrg	XColor color, tmp;
146706f2543Smrg
147706f2543Smrg	pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin,
148706f2543Smrg				       noCursorData, 8, 8);
149706f2543Smrg	XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0],
150706f2543Smrg			 "black", &color, &tmp);
151706f2543Smrg	dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay,
152706f2543Smrg						  pixmap, pixmap,
153706f2543Smrg						  &color, &color, 0, 0);
154706f2543Smrg	XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
155706f2543Smrg		      dmxScreen->noCursor);
156706f2543Smrg
157706f2543Smrg	XFreePixmap(dmxScreen->beDisplay, pixmap);
158706f2543Smrg    }
159706f2543Smrg
160706f2543Smrg    XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
161706f2543Smrg
162706f2543Smrg    if (dmxShadowFB) {
163706f2543Smrg	mask = (GCFunction
164706f2543Smrg		| GCPlaneMask
165706f2543Smrg		| GCClipMask);
166706f2543Smrg	gcvals.function = GXcopy;
167706f2543Smrg	gcvals.plane_mask = AllPlanes;
168706f2543Smrg	gcvals.clip_mask = None;
169706f2543Smrg
170706f2543Smrg	dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay,
171706f2543Smrg					dmxScreen->scrnWin,
172706f2543Smrg					mask, &gcvals);
173706f2543Smrg
174706f2543Smrg	dmxScreen->shadowFBImage =
175706f2543Smrg	    XCreateImage(dmxScreen->beDisplay,
176706f2543Smrg			 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
177706f2543Smrg			 dmxScreen->beDepth,
178706f2543Smrg			 ZPixmap,
179706f2543Smrg			 0,
180706f2543Smrg			 (char *)dmxScreen->shadow,
181706f2543Smrg			 dmxScreen->scrnWidth, dmxScreen->scrnHeight,
182706f2543Smrg			 dmxScreen->beBPP,
183706f2543Smrg			 PixmapBytePad(dmxScreen->scrnWidth,
184706f2543Smrg				       dmxScreen->beBPP));
185706f2543Smrg    } else {
186706f2543Smrg	/* Create default drawables (used during GC creation) */
187706f2543Smrg	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++)
188706f2543Smrg	    for (j = 0; j < dmxScreen->beNumDepths; j++)
189706f2543Smrg		if ((dmxScreen->bePixmapFormats[i].depth == 1) ||
190706f2543Smrg		    (dmxScreen->bePixmapFormats[i].depth ==
191706f2543Smrg		     dmxScreen->beDepths[j])) {
192706f2543Smrg		    dmxScreen->scrnDefDrawables[i] = (Drawable)
193706f2543Smrg			XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
194706f2543Smrg				      1, 1, dmxScreen->bePixmapFormats[i].depth);
195706f2543Smrg		    break;
196706f2543Smrg		}
197706f2543Smrg    }
198706f2543Smrg}
199706f2543Smrg
200706f2543Smrg/** Initialize screen number \a idx. */
201706f2543SmrgBool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[])
202706f2543Smrg{
203706f2543Smrg    DMXScreenInfo        *dmxScreen = &dmxScreens[idx];
204706f2543Smrg    int                   i, j;
205706f2543Smrg
206706f2543Smrg    if (!dixRegisterPrivateKey(&dmxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
207706f2543Smrg	return FALSE;
208706f2543Smrg    if (!dixRegisterPrivateKey(&dmxColormapPrivateKeyRec, PRIVATE_COLORMAP, 0))
209706f2543Smrg	return FALSE;
210706f2543Smrg    if (!dixRegisterPrivateKey(&dmxGlyphSetPrivateKeyRec, PRIVATE_GLYPHSET, 0))
211706f2543Smrg	return FALSE;
212706f2543Smrg
213706f2543Smrg    if (dmxGeneration != serverGeneration) {
214706f2543Smrg	/* Allocate font private index */
215706f2543Smrg	dmxFontPrivateIndex = AllocateFontPrivateIndex();
216706f2543Smrg	if (dmxFontPrivateIndex == -1)
217706f2543Smrg	    return FALSE;
218706f2543Smrg
219706f2543Smrg	dmxGeneration = serverGeneration;
220706f2543Smrg    }
221706f2543Smrg
222706f2543Smrg    if (dmxShadowFB) {
223706f2543Smrg	dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth,
224706f2543Smrg					dmxScreen->scrnHeight,
225706f2543Smrg					dmxScreen->beBPP);
226706f2543Smrg    } else {
227706f2543Smrg	if (!dmxInitGC(pScreen)) return FALSE;
228706f2543Smrg	if (!dmxInitWindow(pScreen)) return FALSE;
229706f2543Smrg	if (!dmxInitPixmap(pScreen)) return FALSE;
230706f2543Smrg    }
231706f2543Smrg
232706f2543Smrg    /*
233706f2543Smrg     * Initalise the visual types.  miSetVisualTypesAndMasks() requires
234706f2543Smrg     * that all of the types for each depth be collected together.  It's
235706f2543Smrg     * intended for slightly different usage to what we would like here.
236706f2543Smrg     * Maybe a miAddVisualTypeAndMask() function will be added to make
237706f2543Smrg     * things easier here.
238706f2543Smrg     */
239706f2543Smrg    for (i = 0; i < dmxScreen->beNumDepths; i++) {
240706f2543Smrg	int    depth;
241706f2543Smrg	int    visuals        = 0;
242706f2543Smrg	int    bitsPerRgb     = 0;
243706f2543Smrg	int    preferredClass = -1;
244706f2543Smrg	Pixel  redMask        = 0;
245706f2543Smrg	Pixel  greenMask      = 0;
246706f2543Smrg	Pixel  blueMask       = 0;
247706f2543Smrg
248706f2543Smrg	depth = dmxScreen->beDepths[i];
249706f2543Smrg	for (j = 0; j < dmxScreen->beNumVisuals; j++) {
250706f2543Smrg	    XVisualInfo *vi;
251706f2543Smrg
252706f2543Smrg	    vi = &dmxScreen->beVisuals[j];
253706f2543Smrg	    if (vi->depth == depth) {
254706f2543Smrg		/* Assume the masks are all the same. */
255706f2543Smrg		visuals |= (1 << vi->class);
256706f2543Smrg		bitsPerRgb = vi->bits_per_rgb;
257706f2543Smrg		redMask = vi->red_mask;
258706f2543Smrg		greenMask = vi->green_mask;
259706f2543Smrg		blueMask = vi->blue_mask;
260706f2543Smrg		if (j == dmxScreen->beDefVisualIndex) {
261706f2543Smrg		    preferredClass = vi->class;
262706f2543Smrg		}
263706f2543Smrg	    }
264706f2543Smrg	}
265706f2543Smrg	miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass,
266706f2543Smrg				 redMask, greenMask, blueMask);
267706f2543Smrg    }
268706f2543Smrg
269706f2543Smrg    fbScreenInit(pScreen,
270706f2543Smrg		 dmxShadowFB ? dmxScreen->shadow : NULL,
271706f2543Smrg		 dmxScreen->scrnWidth,
272706f2543Smrg		 dmxScreen->scrnHeight,
273706f2543Smrg		 dmxScreen->beXDPI,
274706f2543Smrg		 dmxScreen->beXDPI,
275706f2543Smrg		 dmxScreen->scrnWidth,
276706f2543Smrg		 dmxScreen->beBPP);
277706f2543Smrg    (void)dmxPictureInit(pScreen, 0, 0);
278706f2543Smrg
279706f2543Smrg    /* Not yet... */
280706f2543Smrg    pScreen->GetWindowPixmap = NULL;
281706f2543Smrg    pScreen->SetWindowPixmap = NULL;
282706f2543Smrg
283706f2543Smrg    if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL))
284706f2543Smrg	return FALSE;
285706f2543Smrg
286706f2543Smrg    if (dmxShadowFB) {
287706f2543Smrg	miDCInitialize(pScreen, &dmxPointerCursorFuncs);
288706f2543Smrg    } else {
289706f2543Smrg        MAXSCREENSALLOC(dmxCursorGeneration);
290706f2543Smrg	if (dmxCursorGeneration[idx] != serverGeneration) {
291706f2543Smrg	    if (!(miPointerInitialize(pScreen,
292706f2543Smrg				      &dmxPointerSpriteFuncs,
293706f2543Smrg				      &dmxPointerCursorFuncs,
294706f2543Smrg				      FALSE)))
295706f2543Smrg		return FALSE;
296706f2543Smrg
297706f2543Smrg	    dmxCursorGeneration[idx] = serverGeneration;
298706f2543Smrg	}
299706f2543Smrg    }
300706f2543Smrg
301706f2543Smrg    DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen);
302706f2543Smrg    DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen);
303706f2543Smrg
304706f2543Smrg    dmxBEScreenInit(idx, pScreen);
305706f2543Smrg
306706f2543Smrg    if (!dmxShadowFB) {
307706f2543Smrg	/* Wrap GC functions */
308706f2543Smrg	DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
309706f2543Smrg
310706f2543Smrg	/* Wrap Window functions */
311706f2543Smrg	DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
312706f2543Smrg	DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
313706f2543Smrg	DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
314706f2543Smrg	DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
315706f2543Smrg		 pScreen);
316706f2543Smrg	DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
317706f2543Smrg	DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
318706f2543Smrg	DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
319706f2543Smrg	DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
320706f2543Smrg	DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
321706f2543Smrg
322706f2543Smrg	DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
323706f2543Smrg	DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
324706f2543Smrg
325706f2543Smrg	DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
326706f2543Smrg
327706f2543Smrg	/* Wrap Image functions */
328706f2543Smrg	DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen);
329706f2543Smrg	DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen);
330706f2543Smrg
331706f2543Smrg	/* Wrap Pixmap functions */
332706f2543Smrg	DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
333706f2543Smrg	DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
334706f2543Smrg	DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen);
335706f2543Smrg
336706f2543Smrg	/* Wrap Font functions */
337706f2543Smrg	DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen);
338706f2543Smrg	DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen);
339706f2543Smrg
340706f2543Smrg	/* Wrap Colormap functions */
341706f2543Smrg	DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
342706f2543Smrg	DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
343706f2543Smrg	DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
344706f2543Smrg	DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
345706f2543Smrg
346706f2543Smrg	/* Wrap Shape functions */
347706f2543Smrg	DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
348706f2543Smrg    }
349706f2543Smrg
350706f2543Smrg    if (!dmxCreateDefColormap(pScreen))
351706f2543Smrg	return FALSE;
352706f2543Smrg
353706f2543Smrg    return TRUE;
354706f2543Smrg}
355706f2543Smrg
356706f2543Smrg/** Close the \a pScreen resources on the back-end server. */
357706f2543Smrgvoid dmxBECloseScreen(ScreenPtr pScreen)
358706f2543Smrg{
359706f2543Smrg    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
360706f2543Smrg    int            i;
361706f2543Smrg
362706f2543Smrg    /* Restore the back-end screen-saver and DPMS state. */
363706f2543Smrg    dmxDPMSTerm(dmxScreen);
364706f2543Smrg
365706f2543Smrg    /* Free the screen resources */
366706f2543Smrg
367706f2543Smrg    XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor);
368706f2543Smrg    dmxScreen->noCursor = (Cursor)0;
369706f2543Smrg
370706f2543Smrg    XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
371706f2543Smrg    XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
372706f2543Smrg    dmxScreen->scrnWin = (Window)0;
373706f2543Smrg
374706f2543Smrg    if (dmxShadowFB) {
375706f2543Smrg	/* Free the shadow GC and image assocated with the back-end server */
376706f2543Smrg	XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC);
377706f2543Smrg	dmxScreen->shadowGC = NULL;
378706f2543Smrg	XFree(dmxScreen->shadowFBImage);
379706f2543Smrg	dmxScreen->shadowFBImage = NULL;
380706f2543Smrg    } else {
381706f2543Smrg	/* Free the default drawables */
382706f2543Smrg	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
383706f2543Smrg	    if (dmxScreen->scrnDefDrawables[i]) {
384706f2543Smrg		XFreePixmap(dmxScreen->beDisplay,
385706f2543Smrg			    dmxScreen->scrnDefDrawables[i]);
386706f2543Smrg		dmxScreen->scrnDefDrawables[i] = (Drawable)0;
387706f2543Smrg	    }
388706f2543Smrg	}
389706f2543Smrg    }
390706f2543Smrg
391706f2543Smrg    /* Free resources allocated during initialization (in dmxinit.c) */
392706f2543Smrg    for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
393706f2543Smrg	XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]);
394706f2543Smrg    free(dmxScreen->beDefColormaps);
395706f2543Smrg    dmxScreen->beDefColormaps = NULL;
396706f2543Smrg
397706f2543Smrg#if 0
398706f2543Smrg    /* Do not free visuals, depths and pixmap formats here.  Free them
399706f2543Smrg     * in dmxCloseScreen() instead -- see comment below. */
400706f2543Smrg    XFree(dmxScreen->beVisuals);
401706f2543Smrg    dmxScreen->beVisuals = NULL;
402706f2543Smrg
403706f2543Smrg    XFree(dmxScreen->beDepths);
404706f2543Smrg    dmxScreen->beDepths = NULL;
405706f2543Smrg
406706f2543Smrg    XFree(dmxScreen->bePixmapFormats);
407706f2543Smrg    dmxScreen->bePixmapFormats = NULL;
408706f2543Smrg#endif
409706f2543Smrg
410706f2543Smrg#ifdef GLXEXT
411706f2543Smrg    if (dmxScreen->glxVisuals) {
412706f2543Smrg	XFree(dmxScreen->glxVisuals);
413706f2543Smrg	dmxScreen->glxVisuals = NULL;
414706f2543Smrg	dmxScreen->numGlxVisuals = 0;
415706f2543Smrg    }
416706f2543Smrg#endif
417706f2543Smrg
418706f2543Smrg    /* Close display */
419706f2543Smrg    XCloseDisplay(dmxScreen->beDisplay);
420706f2543Smrg    dmxScreen->beDisplay = NULL;
421706f2543Smrg}
422706f2543Smrg
423706f2543Smrg/** Close screen number \a idx. */
424706f2543SmrgBool dmxCloseScreen(int idx, ScreenPtr pScreen)
425706f2543Smrg{
426706f2543Smrg    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
427706f2543Smrg
428706f2543Smrg    /* Reset the proc vectors */
429706f2543Smrg    if (idx == 0) {
430706f2543Smrg	dmxResetRender();
431706f2543Smrg	dmxResetFonts();
432706f2543Smrg    }
433706f2543Smrg
434706f2543Smrg    if (dmxShadowFB) {
435706f2543Smrg	/* Free the shadow framebuffer */
436706f2543Smrg	free(dmxScreen->shadow);
437706f2543Smrg    } else {
438706f2543Smrg
439706f2543Smrg	/* Unwrap Shape functions */
440706f2543Smrg	DMX_UNWRAP(SetShape, dmxScreen, pScreen);
441706f2543Smrg
442706f2543Smrg	/* Unwrap the pScreen functions */
443706f2543Smrg	DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
444706f2543Smrg
445706f2543Smrg	DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
446706f2543Smrg	DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
447706f2543Smrg	DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
448706f2543Smrg	DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
449706f2543Smrg	DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
450706f2543Smrg	DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
451706f2543Smrg	DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
452706f2543Smrg	DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
453706f2543Smrg	DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
454706f2543Smrg
455706f2543Smrg	DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
456706f2543Smrg	DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
457706f2543Smrg
458706f2543Smrg	DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
459706f2543Smrg
460706f2543Smrg	DMX_UNWRAP(GetImage, dmxScreen, pScreen);
461706f2543Smrg	DMX_UNWRAP(GetSpans, dmxScreen, pScreen);
462706f2543Smrg
463706f2543Smrg	DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
464706f2543Smrg	DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
465706f2543Smrg	DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen);
466706f2543Smrg
467706f2543Smrg	DMX_UNWRAP(RealizeFont, dmxScreen, pScreen);
468706f2543Smrg	DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen);
469706f2543Smrg
470706f2543Smrg	DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
471706f2543Smrg	DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
472706f2543Smrg	DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
473706f2543Smrg	DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
474706f2543Smrg    }
475706f2543Smrg
476706f2543Smrg    DMX_UNWRAP(SaveScreen, dmxScreen, pScreen);
477706f2543Smrg
478706f2543Smrg    if (dmxScreen->beDisplay) {
479706f2543Smrg	dmxBECloseScreen(pScreen);
480706f2543Smrg
481706f2543Smrg#if 1
482706f2543Smrg	/* Free visuals, depths and pixmap formats here so that they
483706f2543Smrg	 * won't be freed when a screen is detached, thereby allowing
484706f2543Smrg	 * the screen to be reattached to be compared to the one
485706f2543Smrg	 * previously removed.
486706f2543Smrg	 */
487706f2543Smrg	XFree(dmxScreen->beVisuals);
488706f2543Smrg	dmxScreen->beVisuals = NULL;
489706f2543Smrg
490706f2543Smrg	XFree(dmxScreen->beDepths);
491706f2543Smrg	dmxScreen->beDepths = NULL;
492706f2543Smrg
493706f2543Smrg	XFree(dmxScreen->bePixmapFormats);
494706f2543Smrg	dmxScreen->bePixmapFormats = NULL;
495706f2543Smrg#endif
496706f2543Smrg    }
497706f2543Smrg
498706f2543Smrg    DMX_UNWRAP(CloseScreen, dmxScreen, pScreen);
499706f2543Smrg    return pScreen->CloseScreen(idx, pScreen);
500706f2543Smrg}
501706f2543Smrg
502706f2543Smrgstatic Bool dmxSaveScreen(ScreenPtr pScreen, int what)
503706f2543Smrg{
504706f2543Smrg    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
505706f2543Smrg
506706f2543Smrg    if (dmxScreen->beDisplay) {
507706f2543Smrg	switch (what) {
508706f2543Smrg	case SCREEN_SAVER_OFF:
509706f2543Smrg	case SCREEN_SAVER_FORCER:
510706f2543Smrg	    XResetScreenSaver(dmxScreen->beDisplay);
511706f2543Smrg	    dmxSync(dmxScreen, FALSE);
512706f2543Smrg	    break;
513706f2543Smrg	case SCREEN_SAVER_ON:
514706f2543Smrg	case SCREEN_SAVER_CYCLE:
515706f2543Smrg	    XActivateScreenSaver(dmxScreen->beDisplay);
516706f2543Smrg	    dmxSync(dmxScreen, FALSE);
517706f2543Smrg	    break;
518706f2543Smrg	}
519706f2543Smrg    }
520706f2543Smrg
521706f2543Smrg    return TRUE;
522706f2543Smrg}
523