dmxscrinit.c revision 706f2543
1/*
2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation on the rights to use, copy, modify, merge,
10 * publish, distribute, sublicense, and/or sell copies of the Software,
11 * and to permit persons to whom the Software is furnished to do so,
12 * subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28/*
29 * Authors:
30 *   Kevin E. Martin <kem@redhat.com>
31 *   David H. Dawes <dawes@xfree86.org>
32 *
33 */
34
35/** \file
36 * This file provides support for screen initialization. */
37
38#ifdef HAVE_DMX_CONFIG_H
39#include <dmx-config.h>
40#endif
41
42#include "dmx.h"
43#include "dmxsync.h"
44#include "dmxshadow.h"
45#include "dmxscrinit.h"
46#include "dmxcursor.h"
47#include "dmxgc.h"
48#include "dmxgcops.h"
49#include "dmxwindow.h"
50#include "dmxpixmap.h"
51#include "dmxfont.h"
52#include "dmxcmap.h"
53#include "dmxprop.h"
54#include "dmxdpms.h"
55
56#include "dmxpict.h"
57
58#include "fb.h"
59#include "mipointer.h"
60#include "micmap.h"
61
62extern Bool dmxCloseScreen(int idx, ScreenPtr pScreen);
63static Bool dmxSaveScreen(ScreenPtr pScreen, int what);
64
65static unsigned long dmxGeneration;
66static unsigned long *dmxCursorGeneration;
67
68DevPrivateKeyRec dmxGCPrivateKeyRec;
69DevPrivateKeyRec dmxWinPrivateKeyRec;
70DevPrivateKeyRec dmxPixPrivateKeyRec;
71int dmxFontPrivateIndex;        /**< Private index for Fonts     */
72DevPrivateKeyRec dmxScreenPrivateKeyRec;
73DevPrivateKeyRec dmxColormapPrivateKeyRec;
74DevPrivateKeyRec dmxPictPrivateKeyRec;
75DevPrivateKeyRec dmxGlyphSetPrivateKeyRec;
76
77/** Initialize the parts of screen \a idx that require access to the
78 *  back-end server. */
79void dmxBEScreenInit(int idx, ScreenPtr pScreen)
80{
81    DMXScreenInfo        *dmxScreen = &dmxScreens[idx];
82    XSetWindowAttributes  attribs;
83    XGCValues             gcvals;
84    unsigned long         mask;
85    int                   i, j;
86
87    /* FIXME: The dmxScreenInit() code currently assumes that it will
88     * not be called if the Xdmx server is started with this screen
89     * detached -- i.e., it assumes that dmxScreen->beDisplay is always
90     * valid.  This is not necessarily a valid assumption when full
91     * addition/removal of screens is implemented, but when this code is
92     * broken out for screen reattachment, then we will reevaluate this
93     * assumption.
94     */
95
96    pScreen->mmWidth = DisplayWidthMM(dmxScreen->beDisplay,
97				      DefaultScreen(dmxScreen->beDisplay));
98    pScreen->mmHeight = DisplayHeightMM(dmxScreen->beDisplay,
99					DefaultScreen(dmxScreen->beDisplay));
100
101    pScreen->whitePixel = dmxScreen->beWhitePixel;
102    pScreen->blackPixel = dmxScreen->beBlackPixel;
103
104    /* Handle screen savers and DPMS on the backend */
105    dmxDPMSInit(dmxScreen);
106
107    /* Create root window for screen */
108    mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
109    attribs.background_pixel = dmxScreen->beBlackPixel;
110    attribs.event_mask = (KeyPressMask
111                          | KeyReleaseMask
112                          | ButtonPressMask
113                          | ButtonReleaseMask
114                          | EnterWindowMask
115                          | LeaveWindowMask
116                          | PointerMotionMask
117                          | KeymapStateMask
118                          | FocusChangeMask);
119    attribs.colormap = dmxScreen->beDefColormaps[dmxScreen->beDefVisualIndex];
120    attribs.override_redirect = True;
121
122    dmxScreen->scrnWin =
123	XCreateWindow(dmxScreen->beDisplay,
124		      DefaultRootWindow(dmxScreen->beDisplay),
125		      dmxScreen->scrnX,
126		      dmxScreen->scrnY,
127		      dmxScreen->scrnWidth,
128		      dmxScreen->scrnHeight,
129		      0,
130		      pScreen->rootDepth,
131		      InputOutput,
132		      dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
133		      mask,
134		      &attribs);
135    dmxPropertyWindow(dmxScreen);
136
137    /*
138     * This turns off the cursor by defining a cursor with no visible
139     * components.
140     */
141    {
142	char noCursorData[] = {0, 0, 0, 0,
143			       0, 0, 0, 0};
144	Pixmap pixmap;
145	XColor color, tmp;
146
147	pixmap = XCreateBitmapFromData(dmxScreen->beDisplay, dmxScreen->scrnWin,
148				       noCursorData, 8, 8);
149	XAllocNamedColor(dmxScreen->beDisplay, dmxScreen->beDefColormaps[0],
150			 "black", &color, &tmp);
151	dmxScreen->noCursor = XCreatePixmapCursor(dmxScreen->beDisplay,
152						  pixmap, pixmap,
153						  &color, &color, 0, 0);
154	XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
155		      dmxScreen->noCursor);
156
157	XFreePixmap(dmxScreen->beDisplay, pixmap);
158    }
159
160    XMapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
161
162    if (dmxShadowFB) {
163	mask = (GCFunction
164		| GCPlaneMask
165		| GCClipMask);
166	gcvals.function = GXcopy;
167	gcvals.plane_mask = AllPlanes;
168	gcvals.clip_mask = None;
169
170	dmxScreen->shadowGC = XCreateGC(dmxScreen->beDisplay,
171					dmxScreen->scrnWin,
172					mask, &gcvals);
173
174	dmxScreen->shadowFBImage =
175	    XCreateImage(dmxScreen->beDisplay,
176			 dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
177			 dmxScreen->beDepth,
178			 ZPixmap,
179			 0,
180			 (char *)dmxScreen->shadow,
181			 dmxScreen->scrnWidth, dmxScreen->scrnHeight,
182			 dmxScreen->beBPP,
183			 PixmapBytePad(dmxScreen->scrnWidth,
184				       dmxScreen->beBPP));
185    } else {
186	/* Create default drawables (used during GC creation) */
187	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++)
188	    for (j = 0; j < dmxScreen->beNumDepths; j++)
189		if ((dmxScreen->bePixmapFormats[i].depth == 1) ||
190		    (dmxScreen->bePixmapFormats[i].depth ==
191		     dmxScreen->beDepths[j])) {
192		    dmxScreen->scrnDefDrawables[i] = (Drawable)
193			XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
194				      1, 1, dmxScreen->bePixmapFormats[i].depth);
195		    break;
196		}
197    }
198}
199
200/** Initialize screen number \a idx. */
201Bool dmxScreenInit(int idx, ScreenPtr pScreen, int argc, char *argv[])
202{
203    DMXScreenInfo        *dmxScreen = &dmxScreens[idx];
204    int                   i, j;
205
206    if (!dixRegisterPrivateKey(&dmxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
207	return FALSE;
208    if (!dixRegisterPrivateKey(&dmxColormapPrivateKeyRec, PRIVATE_COLORMAP, 0))
209	return FALSE;
210    if (!dixRegisterPrivateKey(&dmxGlyphSetPrivateKeyRec, PRIVATE_GLYPHSET, 0))
211	return FALSE;
212
213    if (dmxGeneration != serverGeneration) {
214	/* Allocate font private index */
215	dmxFontPrivateIndex = AllocateFontPrivateIndex();
216	if (dmxFontPrivateIndex == -1)
217	    return FALSE;
218
219	dmxGeneration = serverGeneration;
220    }
221
222    if (dmxShadowFB) {
223	dmxScreen->shadow = shadowAlloc(dmxScreen->scrnWidth,
224					dmxScreen->scrnHeight,
225					dmxScreen->beBPP);
226    } else {
227	if (!dmxInitGC(pScreen)) return FALSE;
228	if (!dmxInitWindow(pScreen)) return FALSE;
229	if (!dmxInitPixmap(pScreen)) return FALSE;
230    }
231
232    /*
233     * Initalise the visual types.  miSetVisualTypesAndMasks() requires
234     * that all of the types for each depth be collected together.  It's
235     * intended for slightly different usage to what we would like here.
236     * Maybe a miAddVisualTypeAndMask() function will be added to make
237     * things easier here.
238     */
239    for (i = 0; i < dmxScreen->beNumDepths; i++) {
240	int    depth;
241	int    visuals        = 0;
242	int    bitsPerRgb     = 0;
243	int    preferredClass = -1;
244	Pixel  redMask        = 0;
245	Pixel  greenMask      = 0;
246	Pixel  blueMask       = 0;
247
248	depth = dmxScreen->beDepths[i];
249	for (j = 0; j < dmxScreen->beNumVisuals; j++) {
250	    XVisualInfo *vi;
251
252	    vi = &dmxScreen->beVisuals[j];
253	    if (vi->depth == depth) {
254		/* Assume the masks are all the same. */
255		visuals |= (1 << vi->class);
256		bitsPerRgb = vi->bits_per_rgb;
257		redMask = vi->red_mask;
258		greenMask = vi->green_mask;
259		blueMask = vi->blue_mask;
260		if (j == dmxScreen->beDefVisualIndex) {
261		    preferredClass = vi->class;
262		}
263	    }
264	}
265	miSetVisualTypesAndMasks(depth, visuals, bitsPerRgb, preferredClass,
266				 redMask, greenMask, blueMask);
267    }
268
269    fbScreenInit(pScreen,
270		 dmxShadowFB ? dmxScreen->shadow : NULL,
271		 dmxScreen->scrnWidth,
272		 dmxScreen->scrnHeight,
273		 dmxScreen->beXDPI,
274		 dmxScreen->beXDPI,
275		 dmxScreen->scrnWidth,
276		 dmxScreen->beBPP);
277    (void)dmxPictureInit(pScreen, 0, 0);
278
279    /* Not yet... */
280    pScreen->GetWindowPixmap = NULL;
281    pScreen->SetWindowPixmap = NULL;
282
283    if (dmxShadowFB && !shadowInit(pScreen, dmxShadowUpdateProc, NULL))
284	return FALSE;
285
286    if (dmxShadowFB) {
287	miDCInitialize(pScreen, &dmxPointerCursorFuncs);
288    } else {
289        MAXSCREENSALLOC(dmxCursorGeneration);
290	if (dmxCursorGeneration[idx] != serverGeneration) {
291	    if (!(miPointerInitialize(pScreen,
292				      &dmxPointerSpriteFuncs,
293				      &dmxPointerCursorFuncs,
294				      FALSE)))
295		return FALSE;
296
297	    dmxCursorGeneration[idx] = serverGeneration;
298	}
299    }
300
301    DMX_WRAP(CloseScreen, dmxCloseScreen, dmxScreen, pScreen);
302    DMX_WRAP(SaveScreen, dmxSaveScreen, dmxScreen, pScreen);
303
304    dmxBEScreenInit(idx, pScreen);
305
306    if (!dmxShadowFB) {
307	/* Wrap GC functions */
308	DMX_WRAP(CreateGC, dmxCreateGC, dmxScreen, pScreen);
309
310	/* Wrap Window functions */
311	DMX_WRAP(CreateWindow, dmxCreateWindow, dmxScreen, pScreen);
312	DMX_WRAP(DestroyWindow, dmxDestroyWindow, dmxScreen, pScreen);
313	DMX_WRAP(PositionWindow, dmxPositionWindow, dmxScreen, pScreen);
314	DMX_WRAP(ChangeWindowAttributes, dmxChangeWindowAttributes, dmxScreen,
315		 pScreen);
316	DMX_WRAP(RealizeWindow, dmxRealizeWindow, dmxScreen, pScreen);
317	DMX_WRAP(UnrealizeWindow, dmxUnrealizeWindow, dmxScreen, pScreen);
318	DMX_WRAP(RestackWindow, dmxRestackWindow, dmxScreen, pScreen);
319	DMX_WRAP(WindowExposures, dmxWindowExposures, dmxScreen, pScreen);
320	DMX_WRAP(CopyWindow, dmxCopyWindow, dmxScreen, pScreen);
321
322	DMX_WRAP(ResizeWindow, dmxResizeWindow, dmxScreen, pScreen);
323	DMX_WRAP(ReparentWindow, dmxReparentWindow, dmxScreen, pScreen);
324
325	DMX_WRAP(ChangeBorderWidth, dmxChangeBorderWidth, dmxScreen, pScreen);
326
327	/* Wrap Image functions */
328	DMX_WRAP(GetImage, dmxGetImage, dmxScreen, pScreen);
329	DMX_WRAP(GetSpans, dmxGetSpans, dmxScreen, pScreen);
330
331	/* Wrap Pixmap functions */
332	DMX_WRAP(CreatePixmap, dmxCreatePixmap, dmxScreen, pScreen);
333	DMX_WRAP(DestroyPixmap, dmxDestroyPixmap, dmxScreen, pScreen);
334	DMX_WRAP(BitmapToRegion, dmxBitmapToRegion, dmxScreen, pScreen);
335
336	/* Wrap Font functions */
337	DMX_WRAP(RealizeFont, dmxRealizeFont, dmxScreen, pScreen);
338	DMX_WRAP(UnrealizeFont, dmxUnrealizeFont, dmxScreen, pScreen);
339
340	/* Wrap Colormap functions */
341	DMX_WRAP(CreateColormap, dmxCreateColormap, dmxScreen, pScreen);
342	DMX_WRAP(DestroyColormap, dmxDestroyColormap, dmxScreen, pScreen);
343	DMX_WRAP(InstallColormap, dmxInstallColormap, dmxScreen, pScreen);
344	DMX_WRAP(StoreColors, dmxStoreColors, dmxScreen, pScreen);
345
346	/* Wrap Shape functions */
347	DMX_WRAP(SetShape, dmxSetShape, dmxScreen, pScreen);
348    }
349
350    if (!dmxCreateDefColormap(pScreen))
351	return FALSE;
352
353    return TRUE;
354}
355
356/** Close the \a pScreen resources on the back-end server. */
357void dmxBECloseScreen(ScreenPtr pScreen)
358{
359    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
360    int            i;
361
362    /* Restore the back-end screen-saver and DPMS state. */
363    dmxDPMSTerm(dmxScreen);
364
365    /* Free the screen resources */
366
367    XFreeCursor(dmxScreen->beDisplay, dmxScreen->noCursor);
368    dmxScreen->noCursor = (Cursor)0;
369
370    XUnmapWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
371    XDestroyWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
372    dmxScreen->scrnWin = (Window)0;
373
374    if (dmxShadowFB) {
375	/* Free the shadow GC and image assocated with the back-end server */
376	XFreeGC(dmxScreen->beDisplay, dmxScreen->shadowGC);
377	dmxScreen->shadowGC = NULL;
378	XFree(dmxScreen->shadowFBImage);
379	dmxScreen->shadowFBImage = NULL;
380    } else {
381	/* Free the default drawables */
382	for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
383	    if (dmxScreen->scrnDefDrawables[i]) {
384		XFreePixmap(dmxScreen->beDisplay,
385			    dmxScreen->scrnDefDrawables[i]);
386		dmxScreen->scrnDefDrawables[i] = (Drawable)0;
387	    }
388	}
389    }
390
391    /* Free resources allocated during initialization (in dmxinit.c) */
392    for (i = 0; i < dmxScreen->beNumDefColormaps; i++)
393	XFreeColormap(dmxScreen->beDisplay, dmxScreen->beDefColormaps[i]);
394    free(dmxScreen->beDefColormaps);
395    dmxScreen->beDefColormaps = NULL;
396
397#if 0
398    /* Do not free visuals, depths and pixmap formats here.  Free them
399     * in dmxCloseScreen() instead -- see comment below. */
400    XFree(dmxScreen->beVisuals);
401    dmxScreen->beVisuals = NULL;
402
403    XFree(dmxScreen->beDepths);
404    dmxScreen->beDepths = NULL;
405
406    XFree(dmxScreen->bePixmapFormats);
407    dmxScreen->bePixmapFormats = NULL;
408#endif
409
410#ifdef GLXEXT
411    if (dmxScreen->glxVisuals) {
412	XFree(dmxScreen->glxVisuals);
413	dmxScreen->glxVisuals = NULL;
414	dmxScreen->numGlxVisuals = 0;
415    }
416#endif
417
418    /* Close display */
419    XCloseDisplay(dmxScreen->beDisplay);
420    dmxScreen->beDisplay = NULL;
421}
422
423/** Close screen number \a idx. */
424Bool dmxCloseScreen(int idx, ScreenPtr pScreen)
425{
426    DMXScreenInfo *dmxScreen = &dmxScreens[idx];
427
428    /* Reset the proc vectors */
429    if (idx == 0) {
430	dmxResetRender();
431	dmxResetFonts();
432    }
433
434    if (dmxShadowFB) {
435	/* Free the shadow framebuffer */
436	free(dmxScreen->shadow);
437    } else {
438
439	/* Unwrap Shape functions */
440	DMX_UNWRAP(SetShape, dmxScreen, pScreen);
441
442	/* Unwrap the pScreen functions */
443	DMX_UNWRAP(CreateGC, dmxScreen, pScreen);
444
445	DMX_UNWRAP(CreateWindow, dmxScreen, pScreen);
446	DMX_UNWRAP(DestroyWindow, dmxScreen, pScreen);
447	DMX_UNWRAP(PositionWindow, dmxScreen, pScreen);
448	DMX_UNWRAP(ChangeWindowAttributes, dmxScreen, pScreen);
449	DMX_UNWRAP(RealizeWindow, dmxScreen, pScreen);
450	DMX_UNWRAP(UnrealizeWindow, dmxScreen, pScreen);
451	DMX_UNWRAP(RestackWindow, dmxScreen, pScreen);
452	DMX_UNWRAP(WindowExposures, dmxScreen, pScreen);
453	DMX_UNWRAP(CopyWindow, dmxScreen, pScreen);
454
455	DMX_UNWRAP(ResizeWindow, dmxScreen, pScreen);
456	DMX_UNWRAP(ReparentWindow, dmxScreen, pScreen);
457
458	DMX_UNWRAP(ChangeBorderWidth, dmxScreen, pScreen);
459
460	DMX_UNWRAP(GetImage, dmxScreen, pScreen);
461	DMX_UNWRAP(GetSpans, dmxScreen, pScreen);
462
463	DMX_UNWRAP(CreatePixmap, dmxScreen, pScreen);
464	DMX_UNWRAP(DestroyPixmap, dmxScreen, pScreen);
465	DMX_UNWRAP(BitmapToRegion, dmxScreen, pScreen);
466
467	DMX_UNWRAP(RealizeFont, dmxScreen, pScreen);
468	DMX_UNWRAP(UnrealizeFont, dmxScreen, pScreen);
469
470	DMX_UNWRAP(CreateColormap, dmxScreen, pScreen);
471	DMX_UNWRAP(DestroyColormap, dmxScreen, pScreen);
472	DMX_UNWRAP(InstallColormap, dmxScreen, pScreen);
473	DMX_UNWRAP(StoreColors, dmxScreen, pScreen);
474    }
475
476    DMX_UNWRAP(SaveScreen, dmxScreen, pScreen);
477
478    if (dmxScreen->beDisplay) {
479	dmxBECloseScreen(pScreen);
480
481#if 1
482	/* Free visuals, depths and pixmap formats here so that they
483	 * won't be freed when a screen is detached, thereby allowing
484	 * the screen to be reattached to be compared to the one
485	 * previously removed.
486	 */
487	XFree(dmxScreen->beVisuals);
488	dmxScreen->beVisuals = NULL;
489
490	XFree(dmxScreen->beDepths);
491	dmxScreen->beDepths = NULL;
492
493	XFree(dmxScreen->bePixmapFormats);
494	dmxScreen->bePixmapFormats = NULL;
495#endif
496    }
497
498    DMX_UNWRAP(CloseScreen, dmxScreen, pScreen);
499    return pScreen->CloseScreen(idx, pScreen);
500}
501
502static Bool dmxSaveScreen(ScreenPtr pScreen, int what)
503{
504    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
505
506    if (dmxScreen->beDisplay) {
507	switch (what) {
508	case SCREEN_SAVER_OFF:
509	case SCREEN_SAVER_FORCER:
510	    XResetScreenSaver(dmxScreen->beDisplay);
511	    dmxSync(dmxScreen, FALSE);
512	    break;
513	case SCREEN_SAVER_ON:
514	case SCREEN_SAVER_CYCLE:
515	    XActivateScreenSaver(dmxScreen->beDisplay);
516	    dmxSync(dmxScreen, FALSE);
517	    break;
518	}
519    }
520
521    return TRUE;
522}
523