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