compinit.c revision 6747b715
1/*
2 * Copyright © 2006 Sun Microsystems, Inc.  All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Copyright © 2003 Keith Packard
24 *
25 * Permission to use, copy, modify, distribute, and sell this software and its
26 * documentation for any purpose is hereby granted without fee, provided that
27 * the above copyright notice appear in all copies and that both that
28 * copyright notice and this permission notice appear in supporting
29 * documentation, and that the name of Keith Packard not be used in
30 * advertising or publicity pertaining to distribution of the software without
31 * specific, written prior permission.  Keith Packard makes no
32 * representations about the suitability of this software for any purpose.  It
33 * is provided "as is" without express or implied warranty.
34 *
35 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
36 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
37 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
39 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
40 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
41 * PERFORMANCE OF THIS SOFTWARE.
42 */
43
44#ifdef HAVE_DIX_CONFIG_H
45#include <dix-config.h>
46#endif
47
48#include "compint.h"
49#include "compositeext.h"
50
51DevPrivateKeyRec CompScreenPrivateKeyRec;
52DevPrivateKeyRec CompWindowPrivateKeyRec;
53DevPrivateKeyRec CompSubwindowsPrivateKeyRec;
54
55static Bool
56compCloseScreen (int index, ScreenPtr pScreen)
57{
58    CompScreenPtr   cs = GetCompScreen (pScreen);
59    Bool	    ret;
60
61    free(cs->alternateVisuals);
62
63    pScreen->CloseScreen = cs->CloseScreen;
64    pScreen->BlockHandler = cs->BlockHandler;
65    pScreen->InstallColormap = cs->InstallColormap;
66    pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
67    pScreen->ReparentWindow = cs->ReparentWindow;
68    pScreen->ConfigNotify = cs->ConfigNotify;
69    pScreen->MoveWindow = cs->MoveWindow;
70    pScreen->ResizeWindow = cs->ResizeWindow;
71    pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
72
73    pScreen->ClipNotify = cs->ClipNotify;
74    pScreen->UnrealizeWindow = cs->UnrealizeWindow;
75    pScreen->RealizeWindow = cs->RealizeWindow;
76    pScreen->DestroyWindow = cs->DestroyWindow;
77    pScreen->CreateWindow = cs->CreateWindow;
78    pScreen->CopyWindow = cs->CopyWindow;
79    pScreen->PositionWindow = cs->PositionWindow;
80
81    free(cs);
82    dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, NULL);
83    ret = (*pScreen->CloseScreen) (index, pScreen);
84
85    return ret;
86}
87
88static void
89compInstallColormap (ColormapPtr pColormap)
90{
91    VisualPtr	    pVisual = pColormap->pVisual;
92    ScreenPtr	    pScreen = pColormap->pScreen;
93    CompScreenPtr   cs = GetCompScreen (pScreen);
94    int		    a;
95
96    for (a = 0; a < cs->numAlternateVisuals; a++)
97	if (pVisual->vid == cs->alternateVisuals[a])
98	    return;
99    pScreen->InstallColormap = cs->InstallColormap;
100    (*pScreen->InstallColormap) (pColormap);
101    cs->InstallColormap = pScreen->InstallColormap;
102    pScreen->InstallColormap = compInstallColormap;
103}
104
105/* Fake backing store via automatic redirection */
106static Bool
107compChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
108{
109    ScreenPtr pScreen = pWin->drawable.pScreen;
110    CompScreenPtr cs = GetCompScreen (pScreen);
111    Bool ret;
112
113    pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
114    ret = pScreen->ChangeWindowAttributes(pWin, mask);
115
116    if (ret && (mask & CWBackingStore) &&
117	    pScreen->backingStoreSupport != NotUseful) {
118	if (pWin->backingStore != NotUseful) {
119	    compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
120	    pWin->backStorage = (pointer) (intptr_t) 1;
121	} else {
122	    compUnredirectWindow(serverClient, pWin,
123				 CompositeRedirectAutomatic);
124	    pWin->backStorage = NULL;
125	}
126    }
127
128    pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
129
130    return ret;
131}
132
133static void
134compScreenUpdate (ScreenPtr pScreen)
135{
136    CompScreenPtr   cs = GetCompScreen (pScreen);
137
138    compCheckTree (pScreen);
139    if (cs->damaged)
140    {
141	compWindowUpdate (pScreen->root);
142	cs->damaged = FALSE;
143    }
144}
145
146static void
147compBlockHandler (int	    i,
148		  pointer   blockData,
149		  pointer   pTimeout,
150		  pointer   pReadmask)
151{
152    ScreenPtr	    pScreen = screenInfo.screens[i];
153    CompScreenPtr   cs = GetCompScreen (pScreen);
154
155    pScreen->BlockHandler = cs->BlockHandler;
156    compScreenUpdate (pScreen);
157    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
158    cs->BlockHandler = pScreen->BlockHandler;
159    pScreen->BlockHandler = compBlockHandler;
160}
161
162/*
163 * Add alternate visuals -- always expose an ARGB32 and RGB24 visual
164 */
165
166static DepthPtr
167compFindVisuallessDepth (ScreenPtr pScreen, int d)
168{
169    int		i;
170
171    for (i = 0; i < pScreen->numDepths; i++)
172    {
173	DepthPtr    depth = &pScreen->allowedDepths[i];
174	if (depth->depth == d)
175	{
176	    /*
177	     * Make sure it doesn't have visuals already
178	     */
179	    if (depth->numVids)
180		return 0;
181	    /*
182	     * looks fine
183	     */
184	    return depth;
185	}
186    }
187    /*
188     * If there isn't one, then it's gonna be hard to have
189     * an associated visual
190     */
191    return 0;
192}
193
194/*
195 * Add a list of visual IDs to the list of visuals to implicitly redirect.
196 */
197static Bool
198compRegisterAlternateVisuals (CompScreenPtr cs, VisualID *vids, int nVisuals)
199{
200    VisualID *p;
201
202    p = realloc(cs->alternateVisuals,
203		 sizeof(VisualID) * (cs->numAlternateVisuals + nVisuals));
204    if(p == NULL)
205	return FALSE;
206
207    memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals);
208
209    cs->alternateVisuals = p;
210    cs->numAlternateVisuals += nVisuals;
211
212    return TRUE;
213}
214
215Bool CompositeRegisterAlternateVisuals (ScreenPtr pScreen, VisualID *vids,
216					int nVisuals)
217{
218    CompScreenPtr cs = GetCompScreen (pScreen);
219    return compRegisterAlternateVisuals(cs, vids, nVisuals);
220}
221
222typedef struct _alternateVisual {
223    int		depth;
224    CARD32	format;
225} CompAlternateVisual;
226
227static CompAlternateVisual  altVisuals[] = {
228#if COMP_INCLUDE_RGB24_VISUAL
229    {	24,	PICT_r8g8b8 },
230#endif
231    {	32,	PICT_a8r8g8b8 },
232};
233
234static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) /
235					      sizeof(CompAlternateVisual);
236
237static Bool
238compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs,
239		       CompAlternateVisual *alt)
240{
241    VisualPtr	    visual;
242    DepthPtr	    depth;
243    PictFormatPtr   pPictFormat;
244    unsigned long   alphaMask;
245
246    /*
247     * The ARGB32 visual is always available.  Other alternate depth visuals
248     * are only provided if their depth is less than the root window depth.
249     * There's no deep reason for this.
250     */
251    if (alt->depth >= pScreen->rootDepth && alt->depth != 32)
252	return FALSE;
253
254    depth = compFindVisuallessDepth (pScreen, alt->depth);
255    if (!depth)
256	/* alt->depth doesn't exist or already has alternate visuals. */
257	return TRUE;
258
259    pPictFormat = PictureMatchFormat (pScreen, alt->depth, alt->format);
260    if (!pPictFormat)
261	return FALSE;
262
263    if (ResizeVisualArray(pScreen, 1, depth) == FALSE) {
264        return FALSE;
265    }
266
267    visual = pScreen->visuals + (pScreen->numVisuals - 1); /* the new one */
268
269    /* Initialize the visual */
270    visual->bitsPerRGBValue = 8;
271    if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) {
272	visual->class = PseudoColor;
273	visual->nplanes = PICT_FORMAT_BPP(alt->format);
274	visual->ColormapEntries = 1 << visual->nplanes;
275    } else {
276	DirectFormatRec *direct = &pPictFormat->direct;
277	visual->class = TrueColor;
278	visual->redMask   = ((unsigned long)direct->redMask) << direct->red;
279	visual->greenMask = ((unsigned long)direct->greenMask) << direct->green;
280	visual->blueMask  = ((unsigned long)direct->blueMask) << direct->blue;
281	alphaMask = ((unsigned long)direct->alphaMask) << direct->alpha;
282	visual->offsetRed   = direct->red;
283	visual->offsetGreen = direct->green;
284	visual->offsetBlue  = direct->blue;
285	/*
286	 * Include A bits in this (unlike GLX which includes only RGB)
287	 * This lets DIX compute suitable masks for colormap allocations
288	 */
289	visual->nplanes = Ones (visual->redMask |
290		visual->greenMask |
291		visual->blueMask |
292		alphaMask);
293	/* find widest component */
294	visual->ColormapEntries = (1 << max (Ones (visual->redMask),
295		    max (Ones (visual->greenMask),
296			Ones (visual->blueMask))));
297    }
298
299    /* remember the visual ID to detect auto-update windows */
300    compRegisterAlternateVisuals(cs, &visual->vid, 1);
301
302    return TRUE;
303}
304
305static Bool
306compAddAlternateVisuals (ScreenPtr pScreen, CompScreenPtr cs)
307{
308    int alt, ret = 0;
309
310    for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++)
311	ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt);
312
313    return !!ret;
314}
315
316Bool
317compScreenInit (ScreenPtr pScreen)
318{
319    CompScreenPtr   cs;
320
321    if (!dixRegisterPrivateKey(&CompScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
322	return FALSE;
323    if (!dixRegisterPrivateKey(&CompWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
324	return FALSE;
325    if (!dixRegisterPrivateKey(&CompSubwindowsPrivateKeyRec, PRIVATE_WINDOW, 0))
326	return FALSE;
327
328    if (GetCompScreen (pScreen))
329	return TRUE;
330    cs = (CompScreenPtr) malloc(sizeof (CompScreenRec));
331    if (!cs)
332	return FALSE;
333
334    cs->damaged = FALSE;
335    cs->overlayWid = FakeClientID(0);
336    cs->pOverlayWin = NULL;
337    cs->pOverlayClients = NULL;
338
339    cs->numAlternateVisuals = 0;
340    cs->alternateVisuals = NULL;
341
342    if (!compAddAlternateVisuals (pScreen, cs))
343    {
344	free(cs);
345	return FALSE;
346    }
347
348    cs->PositionWindow = pScreen->PositionWindow;
349    pScreen->PositionWindow = compPositionWindow;
350
351    cs->CopyWindow = pScreen->CopyWindow;
352    pScreen->CopyWindow = compCopyWindow;
353
354    cs->CreateWindow = pScreen->CreateWindow;
355    pScreen->CreateWindow = compCreateWindow;
356
357    cs->DestroyWindow = pScreen->DestroyWindow;
358    pScreen->DestroyWindow = compDestroyWindow;
359
360    cs->RealizeWindow = pScreen->RealizeWindow;
361    pScreen->RealizeWindow = compRealizeWindow;
362
363    cs->UnrealizeWindow = pScreen->UnrealizeWindow;
364    pScreen->UnrealizeWindow = compUnrealizeWindow;
365
366    cs->ClipNotify = pScreen->ClipNotify;
367    pScreen->ClipNotify = compClipNotify;
368
369    cs->ConfigNotify = pScreen->ConfigNotify;
370    pScreen->ConfigNotify = compConfigNotify;
371
372    cs->MoveWindow = pScreen->MoveWindow;
373    pScreen->MoveWindow = compMoveWindow;
374
375    cs->ResizeWindow = pScreen->ResizeWindow;
376    pScreen->ResizeWindow = compResizeWindow;
377
378    cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
379    pScreen->ChangeBorderWidth = compChangeBorderWidth;
380
381    cs->ReparentWindow = pScreen->ReparentWindow;
382    pScreen->ReparentWindow = compReparentWindow;
383
384    cs->InstallColormap = pScreen->InstallColormap;
385    pScreen->InstallColormap = compInstallColormap;
386
387    cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
388    pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
389
390    cs->BlockHandler = pScreen->BlockHandler;
391    pScreen->BlockHandler = compBlockHandler;
392
393    cs->CloseScreen = pScreen->CloseScreen;
394    pScreen->CloseScreen = compCloseScreen;
395
396    dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, cs);
397
398    RegisterRealChildHeadProc(CompositeRealChildHead);
399
400    return TRUE;
401}
402