compinit.c revision 05b261ec
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
49int	CompScreenPrivateIndex;
50int	CompWindowPrivateIndex;
51int	CompSubwindowsPrivateIndex;
52static int	CompGeneration;
53
54
55static Bool
56compCloseScreen (int index, ScreenPtr pScreen)
57{
58    CompScreenPtr   cs = GetCompScreen (pScreen);
59    Bool	    ret;
60
61    xfree (cs->alternateVisuals);
62
63    pScreen->CloseScreen = cs->CloseScreen;
64    pScreen->BlockHandler = cs->BlockHandler;
65    pScreen->InstallColormap = cs->InstallColormap;
66    pScreen->ReparentWindow = cs->ReparentWindow;
67    pScreen->MoveWindow = cs->MoveWindow;
68    pScreen->ResizeWindow = cs->ResizeWindow;
69    pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
70
71    pScreen->ClipNotify = cs->ClipNotify;
72    pScreen->PaintWindowBackground = cs->PaintWindowBackground;
73    pScreen->UnrealizeWindow = cs->UnrealizeWindow;
74    pScreen->RealizeWindow = cs->RealizeWindow;
75    pScreen->DestroyWindow = cs->DestroyWindow;
76    pScreen->CreateWindow = cs->CreateWindow;
77    pScreen->CopyWindow = cs->CopyWindow;
78    pScreen->PositionWindow = cs->PositionWindow;
79
80    deleteCompOverlayClientsForScreen(pScreen);
81
82    /*
83    ** Note: no need to call DeleteWindow; the server has
84    ** already destroyed it.
85    */
86    cs->pOverlayWin = NULL;
87
88    xfree (cs);
89    pScreen->devPrivates[CompScreenPrivateIndex].ptr = 0;
90    ret = (*pScreen->CloseScreen) (index, pScreen);
91
92    return ret;
93}
94
95static void
96compInstallColormap (ColormapPtr pColormap)
97{
98    VisualPtr	    pVisual = pColormap->pVisual;
99    ScreenPtr	    pScreen = pColormap->pScreen;
100    CompScreenPtr   cs = GetCompScreen (pScreen);
101    int		    a;
102
103    for (a = 0; a < cs->numAlternateVisuals; a++)
104	if (pVisual->vid == cs->alternateVisuals[a])
105	    return;
106    pScreen->InstallColormap = cs->InstallColormap;
107    (*pScreen->InstallColormap) (pColormap);
108    cs->InstallColormap = pScreen->InstallColormap;
109    pScreen->InstallColormap = compInstallColormap;
110}
111
112static void
113compScreenUpdate (ScreenPtr pScreen)
114{
115    CompScreenPtr   cs = GetCompScreen (pScreen);
116
117    compCheckTree (pScreen);
118    if (cs->damaged)
119    {
120	compWindowUpdate (WindowTable[pScreen->myNum]);
121	cs->damaged = FALSE;
122    }
123}
124
125static void
126compBlockHandler (int	    i,
127		  pointer   blockData,
128		  pointer   pTimeout,
129		  pointer   pReadmask)
130{
131    ScreenPtr	    pScreen = screenInfo.screens[i];
132    CompScreenPtr   cs = GetCompScreen (pScreen);
133
134    pScreen->BlockHandler = cs->BlockHandler;
135    compScreenUpdate (pScreen);
136    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
137    cs->BlockHandler = pScreen->BlockHandler;
138    pScreen->BlockHandler = compBlockHandler;
139}
140
141/*
142 * Add alternate visuals -- always expose an ARGB32 and RGB24 visual
143 */
144
145static DepthPtr
146compFindVisuallessDepth (ScreenPtr pScreen, int d)
147{
148    int		i;
149
150    for (i = 0; i < pScreen->numDepths; i++)
151    {
152	DepthPtr    depth = &pScreen->allowedDepths[i];
153	if (depth->depth == d)
154	{
155	    /*
156	     * Make sure it doesn't have visuals already
157	     */
158	    if (depth->numVids)
159		return 0;
160	    /*
161	     * looks fine
162	     */
163	    return depth;
164	}
165    }
166    /*
167     * If there isn't one, then it's gonna be hard to have
168     * an associated visual
169     */
170    return 0;
171}
172
173/*
174 * Add a list of visual IDs to the list of visuals to implicitly redirect.
175 */
176static Bool
177compRegisterAlternateVisuals (CompScreenPtr cs, VisualID *vids, int nVisuals)
178{
179    VisualID *p;
180
181    p = xrealloc(cs->alternateVisuals,
182		 sizeof(VisualID) * (cs->numAlternateVisuals + nVisuals));
183    if(p == NULL)
184	return FALSE;
185
186    memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals);
187
188    cs->alternateVisuals = p;
189    cs->numAlternateVisuals += nVisuals;
190
191    return TRUE;
192}
193
194_X_EXPORT
195Bool CompositeRegisterAlternateVisuals (ScreenPtr pScreen, VisualID *vids,
196					int nVisuals)
197{
198    CompScreenPtr cs = GetCompScreen (pScreen);
199    return compRegisterAlternateVisuals(cs, vids, nVisuals);
200}
201
202typedef struct _alternateVisual {
203    int		depth;
204    CARD32	format;
205} CompAlternateVisual;
206
207static CompAlternateVisual  altVisuals[] = {
208#if COMP_INCLUDE_RGB24_VISUAL
209    {	24,	PICT_r8g8b8 },
210#endif
211    {	32,	PICT_a8r8g8b8 },
212};
213
214static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) /
215					      sizeof(CompAlternateVisual);
216
217static Bool
218compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs,
219		       CompAlternateVisual *alt)
220{
221    VisualPtr	    visual, visuals;
222    int		    i;
223    int		    numVisuals;
224    XID		    *installedCmaps;
225    ColormapPtr	    installedCmap;
226    int		    numInstalledCmaps;
227    DepthPtr	    depth;
228    PictFormatPtr   pPictFormat;
229    VisualID	    *vid;
230    unsigned long   alphaMask;
231
232    /*
233     * The ARGB32 visual is always available.  Other alternate depth visuals
234     * are only provided if their depth is less than the root window depth.
235     * There's no deep reason for this.
236     */
237    if (alt->depth >= pScreen->rootDepth && alt->depth != 32)
238	return FALSE;
239
240    depth = compFindVisuallessDepth (pScreen, alt->depth);
241    if (!depth)
242	/* alt->depth doesn't exist or already has alternate visuals. */
243	return TRUE;
244
245    pPictFormat = PictureMatchFormat (pScreen, alt->depth, alt->format);
246    if (!pPictFormat)
247	return FALSE;
248
249    vid = xalloc(sizeof(VisualID));
250    if (!vid)
251	return FALSE;
252
253    /* Find the installed colormaps */
254    installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID));
255    if (!installedCmaps) {
256	xfree(vid);
257	return FALSE;
258    }
259    numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen,
260	    installedCmaps);
261
262    /* realloc the visual array to fit the new one in place */
263    numVisuals = pScreen->numVisuals;
264    visuals = xrealloc(pScreen->visuals, (numVisuals + 1) * sizeof(VisualRec));
265    if (!visuals) {
266	xfree(vid);
267	xfree(installedCmaps);
268	return FALSE;
269    }
270
271    /*
272     * Fix up any existing installed colormaps -- we'll assume that
273     * the only ones created so far have been installed.  If this
274     * isn't true, we'll have to walk the resource database looking
275     * for all colormaps.
276     */
277    for (i = 0; i < numInstalledCmaps; i++) {
278	int j;
279
280	installedCmap = LookupIDByType (installedCmaps[i], RT_COLORMAP);
281	if (!installedCmap)
282	    continue;
283	j = installedCmap->pVisual - pScreen->visuals;
284	installedCmap->pVisual = &visuals[j];
285    }
286
287    xfree(installedCmaps);
288
289    pScreen->visuals = visuals;
290    visual = visuals + pScreen->numVisuals; /* the new one */
291    pScreen->numVisuals++;
292
293    /* Initialize the visual */
294    visual->vid = FakeClientID (0);
295    visual->bitsPerRGBValue = 8;
296    if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) {
297	visual->class = PseudoColor;
298	visual->nplanes = PICT_FORMAT_BPP(alt->format);
299	visual->ColormapEntries = 1 << visual->nplanes;
300    } else {
301	DirectFormatRec *direct = &pPictFormat->direct;
302	visual->class = TrueColor;
303	visual->redMask   = ((unsigned long)direct->redMask) << direct->red;
304	visual->greenMask = ((unsigned long)direct->greenMask) << direct->green;
305	visual->blueMask  = ((unsigned long)direct->blueMask) << direct->blue;
306	alphaMask = ((unsigned long)direct->alphaMask) << direct->alpha;
307	visual->offsetRed   = direct->red;
308	visual->offsetGreen = direct->green;
309	visual->offsetBlue  = direct->blue;
310	/*
311	 * Include A bits in this (unlike GLX which includes only RGB)
312	 * This lets DIX compute suitable masks for colormap allocations
313	 */
314	visual->nplanes = Ones (visual->redMask |
315		visual->greenMask |
316		visual->blueMask |
317		alphaMask);
318	/* find widest component */
319	visual->ColormapEntries = (1 << max (Ones (visual->redMask),
320		    max (Ones (visual->greenMask),
321			Ones (visual->blueMask))));
322    }
323
324    /* remember the visual ID to detect auto-update windows */
325    compRegisterAlternateVisuals(cs, &visual->vid, 1);
326
327    /* Fix up the depth */
328    *vid = visual->vid;
329    depth->numVids = 1;
330    depth->vids = vid;
331    return TRUE;
332}
333
334static Bool
335compAddAlternateVisuals (ScreenPtr pScreen, CompScreenPtr cs)
336{
337    int alt, ret = 0;
338
339    for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++)
340	ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt);
341
342    return !!ret;
343}
344
345Bool
346compScreenInit (ScreenPtr pScreen)
347{
348    CompScreenPtr   cs;
349
350    if (CompGeneration != serverGeneration)
351    {
352	CompScreenPrivateIndex = AllocateScreenPrivateIndex ();
353	if (CompScreenPrivateIndex == -1)
354	    return FALSE;
355	CompWindowPrivateIndex = AllocateWindowPrivateIndex ();
356	if (CompWindowPrivateIndex == -1)
357	    return FALSE;
358	CompSubwindowsPrivateIndex = AllocateWindowPrivateIndex ();
359	if (CompSubwindowsPrivateIndex == -1)
360	    return FALSE;
361	CompGeneration = serverGeneration;
362    }
363    if (!AllocateWindowPrivate (pScreen, CompWindowPrivateIndex, 0))
364	return FALSE;
365
366    if (!AllocateWindowPrivate (pScreen, CompSubwindowsPrivateIndex, 0))
367	return FALSE;
368
369    if (GetCompScreen (pScreen))
370	return TRUE;
371    cs = (CompScreenPtr) xalloc (sizeof (CompScreenRec));
372    if (!cs)
373	return FALSE;
374
375    cs->damaged = FALSE;
376    cs->pOverlayWin = NULL;
377    cs->pOverlayClients = NULL;
378
379    cs->numAlternateVisuals = 0;
380    cs->alternateVisuals = NULL;
381
382    if (!compAddAlternateVisuals (pScreen, cs))
383    {
384	xfree (cs);
385	return FALSE;
386    }
387
388    cs->PositionWindow = pScreen->PositionWindow;
389    pScreen->PositionWindow = compPositionWindow;
390
391    cs->CopyWindow = pScreen->CopyWindow;
392    pScreen->CopyWindow = compCopyWindow;
393
394    cs->CreateWindow = pScreen->CreateWindow;
395    pScreen->CreateWindow = compCreateWindow;
396
397    cs->DestroyWindow = pScreen->DestroyWindow;
398    pScreen->DestroyWindow = compDestroyWindow;
399
400    cs->RealizeWindow = pScreen->RealizeWindow;
401    pScreen->RealizeWindow = compRealizeWindow;
402
403    cs->UnrealizeWindow = pScreen->UnrealizeWindow;
404    pScreen->UnrealizeWindow = compUnrealizeWindow;
405
406    cs->PaintWindowBackground = pScreen->PaintWindowBackground;
407    pScreen->PaintWindowBackground = compPaintWindowBackground;
408
409    cs->ClipNotify = pScreen->ClipNotify;
410    pScreen->ClipNotify = compClipNotify;
411
412    cs->MoveWindow = pScreen->MoveWindow;
413    pScreen->MoveWindow = compMoveWindow;
414
415    cs->ResizeWindow = pScreen->ResizeWindow;
416    pScreen->ResizeWindow = compResizeWindow;
417
418    cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
419    pScreen->ChangeBorderWidth = compChangeBorderWidth;
420
421    cs->ReparentWindow = pScreen->ReparentWindow;
422    pScreen->ReparentWindow = compReparentWindow;
423
424    cs->InstallColormap = pScreen->InstallColormap;
425    pScreen->InstallColormap = compInstallColormap;
426
427    cs->BlockHandler = pScreen->BlockHandler;
428    pScreen->BlockHandler = compBlockHandler;
429
430    cs->CloseScreen = pScreen->CloseScreen;
431    pScreen->CloseScreen = compCloseScreen;
432
433    pScreen->devPrivates[CompScreenPrivateIndex].ptr = (pointer) cs;
434
435    RegisterRealChildHeadProc(CompositeRealChildHead);
436
437    return TRUE;
438}
439