Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 2000 Keith Packard | |
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 Keith Packard not be used in | |
9 | * advertising or publicity pertaining to distribution of the software without | |
10 | * specific, written prior permission. Keith Packard 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 | * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
16 | * EVENT SHALL KEITH PACKARD 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 | ||
23 | #ifdef HAVE_DIX_CONFIG_H | |
24 | #include <dix-config.h> | |
25 | #endif | |
26 | ||
27 | #include <stdlib.h> | |
28 | ||
29 | #include <X11/X.h> | |
30 | #include "scrnintstr.h" | |
31 | #include "windowstr.h" | |
32 | #include "dixfontstr.h" | |
33 | #include "mi.h" | |
34 | #include "regionstr.h" | |
35 | #include "globals.h" | |
36 | #include "gcstruct.h" | |
37 | #include "shadow.h" | |
38 | ||
39 | static DevPrivateKeyRec shadowScrPrivateKeyRec; | |
40 | ||
41 | #define shadowScrPrivateKey (&shadowScrPrivateKeyRec) | |
42 | ||
43 | #define wrap(priv, real, mem) {\ | |
44 | priv->mem = real->mem; \ | |
45 | real->mem = shadow##mem; \ | |
46 | } | |
47 | ||
48 | #define unwrap(priv, real, mem) {\ | |
49 | real->mem = priv->mem; \ | |
50 | } | |
51 | ||
52 | static void | |
53 | shadowRedisplay(ScreenPtr pScreen) | |
54 | { | |
55 | shadowBuf(pScreen); | |
56 | RegionPtr pRegion; | |
57 | ||
58 | if (!pBuf || !pBuf->pDamage || !pBuf->update) | |
59 | return; | |
60 | pRegion = DamageRegion(pBuf->pDamage); | |
61 | if (RegionNotEmpty(pRegion)) { | |
62 | (*pBuf->update) (pScreen, pBuf); | |
63 | DamageEmpty(pBuf->pDamage); | |
64 | } | |
65 | } | |
66 | ||
67 | static void | |
68 | shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) | |
69 | { | |
70 | ScreenPtr pScreen = (ScreenPtr) data; | |
71 | ||
72 | shadowRedisplay(pScreen); | |
73 | } | |
74 | ||
75 | static void | |
76 | shadowWakeupHandler(pointer data, int i, pointer LastSelectMask) | |
77 | { | |
78 | } | |
79 | ||
80 | static void | |
81 | shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, | |
82 | unsigned int format, unsigned long planeMask, char *pdstLine) | |
83 | { | |
84 | ScreenPtr pScreen = pDrawable->pScreen; | |
85 | ||
86 | shadowBuf(pScreen); | |
87 | ||
88 | /* Many apps use GetImage to sync with the visable frame buffer */ | |
89 | if (pDrawable->type == DRAWABLE_WINDOW) | |
90 | shadowRedisplay(pScreen); | |
91 | unwrap(pBuf, pScreen, GetImage); | |
92 | pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); | |
93 | wrap(pBuf, pScreen, GetImage); | |
94 | } | |
95 | ||
96 | #define BACKWARDS_COMPATIBILITY | |
97 | ||
98 | static Bool | |
99 | shadowCloseScreen(ScreenPtr pScreen) | |
100 | { | |
101 | shadowBuf(pScreen); | |
102 | ||
103 | unwrap(pBuf, pScreen, GetImage); | |
104 | unwrap(pBuf, pScreen, CloseScreen); | |
105 | shadowRemove(pScreen, pBuf->pPixmap); | |
106 | DamageDestroy(pBuf->pDamage); | |
107 | #ifdef BACKWARDS_COMPATIBILITY | |
108 | RegionUninit(&pBuf->damage); /* bc */ | |
109 | #endif | |
110 | if (pBuf->pPixmap) | |
111 | pScreen->DestroyPixmap(pBuf->pPixmap); | |
112 | free(pBuf); | |
113 | return pScreen->CloseScreen(pScreen); | |
114 | } | |
115 | ||
116 | #ifdef BACKWARDS_COMPATIBILITY | |
117 | static void | |
118 | shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure) | |
119 | { | |
120 | ScreenPtr pScreen = closure; | |
121 | shadowBufPtr pBuf = (shadowBufPtr) | |
122 | dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey); | |
123 | ||
124 | /* Register the damaged region, use DamageReportNone below when we | |
125 | * want to break BC below... */ | |
126 | RegionUnion(&pDamage->damage, &pDamage->damage, pRegion); | |
127 | ||
128 | /* | |
129 | * BC hack. In 7.0 and earlier several drivers would inspect the | |
130 | * 'damage' member directly, so we have to keep it existing. | |
131 | */ | |
132 | RegionCopy(&pBuf->damage, pRegion); | |
133 | } | |
134 | #endif | |
135 | ||
136 | Bool | |
137 | shadowSetup(ScreenPtr pScreen) | |
138 | { | |
139 | shadowBufPtr pBuf; | |
140 | ||
141 | if (!dixRegisterPrivateKey(&shadowScrPrivateKeyRec, PRIVATE_SCREEN, 0)) | |
142 | return FALSE; | |
143 | ||
144 | if (!DamageSetup(pScreen)) | |
145 | return FALSE; | |
146 | ||
147 | pBuf = malloc(sizeof(shadowBufRec)); | |
148 | if (!pBuf) | |
149 | return FALSE; | |
150 | #ifdef BACKWARDS_COMPATIBILITY | |
151 | pBuf->pDamage = DamageCreate((DamageReportFunc) shadowReportFunc, | |
152 | (DamageDestroyFunc) NULL, | |
153 | DamageReportRawRegion, TRUE, pScreen, pScreen); | |
154 | #else | |
155 | pBuf->pDamage = DamageCreate((DamageReportFunc) NULL, | |
156 | (DamageDestroyFunc) NULL, | |
157 | DamageReportNone, TRUE, pScreen, pScreen); | |
158 | #endif | |
159 | if (!pBuf->pDamage) { | |
160 | free(pBuf); | |
161 | return FALSE; | |
162 | } | |
163 | ||
164 | wrap(pBuf, pScreen, CloseScreen); | |
165 | wrap(pBuf, pScreen, GetImage); | |
166 | pBuf->update = 0; | |
167 | pBuf->window = 0; | |
168 | pBuf->pPixmap = 0; | |
169 | pBuf->closure = 0; | |
170 | pBuf->randr = 0; | |
171 | #ifdef BACKWARDS_COMPATIBILITY | |
172 | RegionNull(&pBuf->damage); /* bc */ | |
173 | #endif | |
174 | ||
175 | dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf); | |
176 | return TRUE; | |
177 | } | |
178 | ||
179 | Bool | |
180 | shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update, | |
181 | ShadowWindowProc window, int randr, void *closure) | |
182 | { | |
183 | shadowBuf(pScreen); | |
184 | ||
185 | if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, | |
186 | (pointer) pScreen)) | |
187 | return FALSE; | |
188 | ||
189 | /* | |
190 | * Map simple rotation values to bitmasks; fortunately, | |
191 | * these are all unique | |
192 | */ | |
193 | switch (randr) { | |
194 | case 0: | |
195 | randr = SHADOW_ROTATE_0; | |
196 | break; | |
197 | case 90: | |
198 | randr = SHADOW_ROTATE_90; | |
199 | break; | |
200 | case 180: | |
201 | randr = SHADOW_ROTATE_180; | |
202 | break; | |
203 | case 270: | |
204 | randr = SHADOW_ROTATE_270; | |
205 | break; | |
206 | } | |
207 | pBuf->update = update; | |
208 | pBuf->window = window; | |
209 | pBuf->randr = randr; | |
210 | pBuf->closure = closure; | |
211 | pBuf->pPixmap = pPixmap; | |
212 | DamageRegister(&pPixmap->drawable, pBuf->pDamage); | |
213 | return TRUE; | |
214 | } | |
215 | ||
216 | void | |
217 | shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap) | |
218 | { | |
219 | shadowBuf(pScreen); | |
220 | ||
221 | if (pBuf->pPixmap) { | |
222 | DamageUnregister(pBuf->pDamage); | |
223 | pBuf->update = 0; | |
224 | pBuf->window = 0; | |
225 | pBuf->randr = 0; | |
226 | pBuf->closure = 0; | |
227 | pBuf->pPixmap = 0; | |
228 | } | |
229 | ||
230 | RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, | |
231 | (pointer) pScreen); | |
232 | } | |
233 | ||
234 | Bool | |
235 | shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window) | |
236 | { | |
237 | PixmapPtr pPixmap; | |
238 | ||
239 | pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height, | |
240 | pScreen->rootDepth, 0); | |
241 | if (!pPixmap) | |
242 | return FALSE; | |
243 | ||
244 | if (!shadowSetup(pScreen)) { | |
245 | pScreen->DestroyPixmap(pPixmap); | |
246 | return FALSE; | |
247 | } | |
248 | ||
249 | shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0); | |
250 | ||
251 | return TRUE; | |
252 | } |