Imported Upstream version 1.15.1
[deb_xorg-server.git] / composite / compinit.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright (c) 2006, Oracle and/or its affiliates. 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(ScreenPtr pScreen)
57{
58 CompScreenPtr cs = GetCompScreen(pScreen);
59 Bool ret;
60
61 free(cs->alternateVisuals);
62
63 pScreen->CloseScreen = cs->CloseScreen;
64 pScreen->InstallColormap = cs->InstallColormap;
65 pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
66 pScreen->ReparentWindow = cs->ReparentWindow;
67 pScreen->ConfigNotify = cs->ConfigNotify;
68 pScreen->MoveWindow = cs->MoveWindow;
69 pScreen->ResizeWindow = cs->ResizeWindow;
70 pScreen->ChangeBorderWidth = cs->ChangeBorderWidth;
71
72 pScreen->ClipNotify = cs->ClipNotify;
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 pScreen->GetImage = cs->GetImage;
81 pScreen->SourceValidate = cs->SourceValidate;
82
83 free(cs);
84 dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, NULL);
85 ret = (*pScreen->CloseScreen) (pScreen);
86
87 return ret;
88}
89
90static void
91compInstallColormap(ColormapPtr pColormap)
92{
93 VisualPtr pVisual = pColormap->pVisual;
94 ScreenPtr pScreen = pColormap->pScreen;
95 CompScreenPtr cs = GetCompScreen(pScreen);
96 int a;
97
98 for (a = 0; a < cs->numAlternateVisuals; a++)
99 if (pVisual->vid == cs->alternateVisuals[a])
100 return;
101 pScreen->InstallColormap = cs->InstallColormap;
102 (*pScreen->InstallColormap) (pColormap);
103 cs->InstallColormap = pScreen->InstallColormap;
104 pScreen->InstallColormap = compInstallColormap;
105}
106
107/* Fake backing store via automatic redirection */
108static Bool
109compChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
110{
111 ScreenPtr pScreen = pWin->drawable.pScreen;
112 CompScreenPtr cs = GetCompScreen(pScreen);
113 Bool ret;
114
115 pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
116 ret = pScreen->ChangeWindowAttributes(pWin, mask);
117
118 if (ret && (mask & CWBackingStore) &&
119 pScreen->backingStoreSupport != NotUseful) {
120 if (pWin->backingStore != NotUseful && !pWin->backStorage) {
121 compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic);
122 pWin->backStorage = (pointer) (intptr_t) 1;
123 }
124 else if (pWin->backingStore == NotUseful && pWin->backStorage) {
125 compUnredirectWindow(serverClient, pWin,
126 CompositeRedirectAutomatic);
127 pWin->backStorage = NULL;
128 }
129 }
130
131 pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
132
133 return ret;
134}
135
136static void
137compGetImage(DrawablePtr pDrawable,
138 int sx, int sy,
139 int w, int h,
140 unsigned int format, unsigned long planemask, char *pdstLine)
141{
142 ScreenPtr pScreen = pDrawable->pScreen;
143 CompScreenPtr cs = GetCompScreen(pScreen);
144
145 pScreen->GetImage = cs->GetImage;
146 if (pDrawable->type == DRAWABLE_WINDOW)
147 compPaintChildrenToWindow((WindowPtr) pDrawable);
148 (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine);
149 cs->GetImage = pScreen->GetImage;
150 pScreen->GetImage = compGetImage;
151}
152
153static void
154compSourceValidate(DrawablePtr pDrawable,
155 int x, int y,
156 int width, int height, unsigned int subWindowMode)
157{
158 ScreenPtr pScreen = pDrawable->pScreen;
159 CompScreenPtr cs = GetCompScreen(pScreen);
160
161 pScreen->SourceValidate = cs->SourceValidate;
162 if (pDrawable->type == DRAWABLE_WINDOW && subWindowMode == IncludeInferiors)
163 compPaintChildrenToWindow((WindowPtr) pDrawable);
164 if (pScreen->SourceValidate)
165 (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
166 subWindowMode);
167 cs->SourceValidate = pScreen->SourceValidate;
168 pScreen->SourceValidate = compSourceValidate;
169}
170
171/*
172 * Add alternate visuals -- always expose an ARGB32 and RGB24 visual
173 */
174
175static DepthPtr
176compFindVisuallessDepth(ScreenPtr pScreen, int d)
177{
178 int i;
179
180 for (i = 0; i < pScreen->numDepths; i++) {
181 DepthPtr depth = &pScreen->allowedDepths[i];
182
183 if (depth->depth == d) {
184 /*
185 * Make sure it doesn't have visuals already
186 */
187 if (depth->numVids)
188 return 0;
189 /*
190 * looks fine
191 */
192 return depth;
193 }
194 }
195 /*
196 * If there isn't one, then it's gonna be hard to have
197 * an associated visual
198 */
199 return 0;
200}
201
202/*
203 * Add a list of visual IDs to the list of visuals to implicitly redirect.
204 */
205static Bool
206compRegisterAlternateVisuals(CompScreenPtr cs, VisualID * vids, int nVisuals)
207{
208 VisualID *p;
209
210 p = realloc(cs->alternateVisuals,
211 sizeof(VisualID) * (cs->numAlternateVisuals + nVisuals));
212 if (p == NULL)
213 return FALSE;
214
215 memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals);
216
217 cs->alternateVisuals = p;
218 cs->numAlternateVisuals += nVisuals;
219
220 return TRUE;
221}
222
223Bool
224CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids,
225 int nVisuals)
226{
227 CompScreenPtr cs = GetCompScreen(pScreen);
228
229 return compRegisterAlternateVisuals(cs, vids, nVisuals);
230}
231
232typedef struct _alternateVisual {
233 int depth;
234 CARD32 format;
235} CompAlternateVisual;
236
237static CompAlternateVisual altVisuals[] = {
238#if COMP_INCLUDE_RGB24_VISUAL
239 {24, PICT_r8g8b8},
240#endif
241 {32, PICT_a8r8g8b8},
242};
243
244static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) /
245 sizeof(CompAlternateVisual);
246
247static Bool
248compAddAlternateVisual(ScreenPtr pScreen, CompScreenPtr cs,
249 CompAlternateVisual * alt)
250{
251 VisualPtr visual;
252 DepthPtr depth;
253 PictFormatPtr pPictFormat;
254 unsigned long alphaMask;
255
256 /*
257 * The ARGB32 visual is always available. Other alternate depth visuals
258 * are only provided if their depth is less than the root window depth.
259 * There's no deep reason for this.
260 */
261 if (alt->depth >= pScreen->rootDepth && alt->depth != 32)
262 return FALSE;
263
264 depth = compFindVisuallessDepth(pScreen, alt->depth);
265 if (!depth)
266 /* alt->depth doesn't exist or already has alternate visuals. */
267 return TRUE;
268
269 pPictFormat = PictureMatchFormat(pScreen, alt->depth, alt->format);
270 if (!pPictFormat)
271 return FALSE;
272
273 if (ResizeVisualArray(pScreen, 1, depth) == FALSE) {
274 return FALSE;
275 }
276
277 visual = pScreen->visuals + (pScreen->numVisuals - 1); /* the new one */
278
279 /* Initialize the visual */
280 visual->bitsPerRGBValue = 8;
281 if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) {
282 visual->class = PseudoColor;
283 visual->nplanes = PICT_FORMAT_BPP(alt->format);
284 visual->ColormapEntries = 1 << visual->nplanes;
285 }
286 else {
287 DirectFormatRec *direct = &pPictFormat->direct;
288
289 visual->class = TrueColor;
290 visual->redMask = ((unsigned long) direct->redMask) << direct->red;
291 visual->greenMask =
292 ((unsigned long) direct->greenMask) << direct->green;
293 visual->blueMask = ((unsigned long) direct->blueMask) << direct->blue;
294 alphaMask = ((unsigned long) direct->alphaMask) << direct->alpha;
295 visual->offsetRed = direct->red;
296 visual->offsetGreen = direct->green;
297 visual->offsetBlue = direct->blue;
298 /*
299 * Include A bits in this (unlike GLX which includes only RGB)
300 * This lets DIX compute suitable masks for colormap allocations
301 */
302 visual->nplanes = Ones(visual->redMask |
303 visual->greenMask |
304 visual->blueMask | alphaMask);
305 /* find widest component */
306 visual->ColormapEntries = (1 << max(Ones(visual->redMask),
307 max(Ones(visual->greenMask),
308 Ones(visual->blueMask))));
309 }
310
311 /* remember the visual ID to detect auto-update windows */
312 compRegisterAlternateVisuals(cs, &visual->vid, 1);
313
314 return TRUE;
315}
316
317static Bool
318compAddAlternateVisuals(ScreenPtr pScreen, CompScreenPtr cs)
319{
320 int alt, ret = 0;
321
322 for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++)
323 ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt);
324
325 return ! !ret;
326}
327
328Bool
329compScreenInit(ScreenPtr pScreen)
330{
331 CompScreenPtr cs;
332
333 if (!dixRegisterPrivateKey(&CompScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
334 return FALSE;
335 if (!dixRegisterPrivateKey(&CompWindowPrivateKeyRec, PRIVATE_WINDOW, 0))
336 return FALSE;
337 if (!dixRegisterPrivateKey(&CompSubwindowsPrivateKeyRec, PRIVATE_WINDOW, 0))
338 return FALSE;
339
340 if (GetCompScreen(pScreen))
341 return TRUE;
342 cs = (CompScreenPtr) malloc(sizeof(CompScreenRec));
343 if (!cs)
344 return FALSE;
345
346 cs->overlayWid = FakeClientID(0);
347 cs->pOverlayWin = NULL;
348 cs->pOverlayClients = NULL;
349
350 cs->numAlternateVisuals = 0;
351 cs->alternateVisuals = NULL;
352
353 if (!compAddAlternateVisuals(pScreen, cs)) {
354 free(cs);
355 return FALSE;
356 }
357
358 if (!disableBackingStore)
359 pScreen->backingStoreSupport = WhenMapped;
360
361 cs->PositionWindow = pScreen->PositionWindow;
362 pScreen->PositionWindow = compPositionWindow;
363
364 cs->CopyWindow = pScreen->CopyWindow;
365 pScreen->CopyWindow = compCopyWindow;
366
367 cs->CreateWindow = pScreen->CreateWindow;
368 pScreen->CreateWindow = compCreateWindow;
369
370 cs->DestroyWindow = pScreen->DestroyWindow;
371 pScreen->DestroyWindow = compDestroyWindow;
372
373 cs->RealizeWindow = pScreen->RealizeWindow;
374 pScreen->RealizeWindow = compRealizeWindow;
375
376 cs->UnrealizeWindow = pScreen->UnrealizeWindow;
377 pScreen->UnrealizeWindow = compUnrealizeWindow;
378
379 cs->ClipNotify = pScreen->ClipNotify;
380 pScreen->ClipNotify = compClipNotify;
381
382 cs->ConfigNotify = pScreen->ConfigNotify;
383 pScreen->ConfigNotify = compConfigNotify;
384
385 cs->MoveWindow = pScreen->MoveWindow;
386 pScreen->MoveWindow = compMoveWindow;
387
388 cs->ResizeWindow = pScreen->ResizeWindow;
389 pScreen->ResizeWindow = compResizeWindow;
390
391 cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
392 pScreen->ChangeBorderWidth = compChangeBorderWidth;
393
394 cs->ReparentWindow = pScreen->ReparentWindow;
395 pScreen->ReparentWindow = compReparentWindow;
396
397 cs->InstallColormap = pScreen->InstallColormap;
398 pScreen->InstallColormap = compInstallColormap;
399
400 cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
401 pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
402
403 cs->BlockHandler = NULL;
404
405 cs->CloseScreen = pScreen->CloseScreen;
406 pScreen->CloseScreen = compCloseScreen;
407
408 cs->GetImage = pScreen->GetImage;
409 pScreen->GetImage = compGetImage;
410
411 cs->SourceValidate = pScreen->SourceValidate;
412 pScreen->SourceValidate = compSourceValidate;
413
414 dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, cs);
415
416 RegisterRealChildHeadProc(CompositeRealChildHead);
417
418 return TRUE;
419}