Commit | Line | Data |
---|---|---|
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 | ||
51 | DevPrivateKeyRec CompScreenPrivateKeyRec; | |
52 | DevPrivateKeyRec CompWindowPrivateKeyRec; | |
53 | DevPrivateKeyRec CompSubwindowsPrivateKeyRec; | |
54 | ||
55 | static Bool | |
56 | compCloseScreen(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 | ||
90 | static void | |
91 | compInstallColormap(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 */ | |
108 | static Bool | |
109 | compChangeWindowAttributes(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 | ||
136 | static void | |
137 | compGetImage(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 | ||
153 | static void | |
154 | compSourceValidate(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 | ||
175 | static DepthPtr | |
176 | compFindVisuallessDepth(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 | */ | |
205 | static Bool | |
206 | compRegisterAlternateVisuals(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 | ||
223 | Bool | |
224 | CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids, | |
225 | int nVisuals) | |
226 | { | |
227 | CompScreenPtr cs = GetCompScreen(pScreen); | |
228 | ||
229 | return compRegisterAlternateVisuals(cs, vids, nVisuals); | |
230 | } | |
231 | ||
232 | typedef struct _alternateVisual { | |
233 | int depth; | |
234 | CARD32 format; | |
235 | } CompAlternateVisual; | |
236 | ||
237 | static CompAlternateVisual altVisuals[] = { | |
238 | #if COMP_INCLUDE_RGB24_VISUAL | |
239 | {24, PICT_r8g8b8}, | |
240 | #endif | |
241 | {32, PICT_a8r8g8b8}, | |
242 | }; | |
243 | ||
244 | static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) / | |
245 | sizeof(CompAlternateVisual); | |
246 | ||
247 | static Bool | |
248 | compAddAlternateVisual(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 | ||
317 | static Bool | |
318 | compAddAlternateVisuals(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 | ||
328 | Bool | |
329 | compScreenInit(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 | } |