First import
[xorg_rtime.git] / xorg-server-1.4 / miext / shadow / shadow.c
blobf624216db6a2536a99e296174db383b0f29bb737
1 /*
2 * Copyright © 2000 Keith Packard
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.
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.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
27 #include <stdlib.h>
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"
39 int shadowScrPrivateIndex;
40 int shadowGeneration;
42 #define wrap(priv, real, mem) {\
43 priv->mem = real->mem; \
44 real->mem = shadow##mem; \
47 #define unwrap(priv, real, mem) {\
48 real->mem = priv->mem; \
51 static void
52 shadowRedisplay(ScreenPtr pScreen)
54 shadowBuf(pScreen);
55 RegionPtr pRegion;
57 if (!pBuf || !pBuf->pDamage || !pBuf->update)
58 return;
59 pRegion = DamageRegion(pBuf->pDamage);
60 if (REGION_NOTEMPTY(pScreen, pRegion)) {
61 (*pBuf->update)(pScreen, pBuf);
62 DamageEmpty(pBuf->pDamage);
66 static void
67 shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
69 ScreenPtr pScreen = (ScreenPtr) data;
71 shadowRedisplay(pScreen);
74 static void
75 shadowWakeupHandler(pointer data, int i, pointer LastSelectMask)
79 static void
80 shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
81 unsigned int format, unsigned long planeMask, char *pdstLine)
83 ScreenPtr pScreen = pDrawable->pScreen;
84 shadowBuf(pScreen);
86 /* Many apps use GetImage to sync with the visable frame buffer */
87 if (pDrawable->type == DRAWABLE_WINDOW)
88 shadowRedisplay(pScreen);
89 unwrap(pBuf, pScreen, GetImage);
90 pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
91 wrap(pBuf, pScreen, GetImage);
94 #define BACKWARDS_COMPATIBILITY
96 static Bool
97 shadowCloseScreen(int i, ScreenPtr pScreen)
99 shadowBuf(pScreen);
101 unwrap(pBuf, pScreen, GetImage);
102 unwrap(pBuf, pScreen, CloseScreen);
103 shadowRemove(pScreen, pBuf->pPixmap);
104 DamageDestroy(pBuf->pDamage);
105 #ifdef BACKWARDS_COMPATIBILITY
106 REGION_UNINIT(pScreen, &pBuf->damage); /* bc */
107 #endif
108 if (pBuf->pPixmap)
109 pScreen->DestroyPixmap(pBuf->pPixmap);
110 xfree(pBuf);
111 return pScreen->CloseScreen(i, pScreen);
114 #ifdef BACKWARDS_COMPATIBILITY
115 static void
116 shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure)
118 ScreenPtr pScreen = closure;
119 shadowBufPtr pBuf = pScreen->devPrivates[shadowScrPrivateIndex].ptr;
121 /* Register the damaged region, use DamageReportNone below when we
122 * want to break BC below... */
123 REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pRegion);
126 * BC hack. In 7.0 and earlier several drivers would inspect the
127 * 'damage' member directly, so we have to keep it existing.
129 REGION_COPY(pScreen, &pBuf->damage, pRegion);
131 #endif
133 Bool
134 shadowSetup(ScreenPtr pScreen)
136 shadowBufPtr pBuf;
138 if (!DamageSetup(pScreen))
139 return FALSE;
141 if (shadowGeneration != serverGeneration) {
142 shadowScrPrivateIndex = AllocateScreenPrivateIndex();
143 if (shadowScrPrivateIndex == -1)
144 return FALSE;
145 shadowGeneration = serverGeneration;
148 pBuf = (shadowBufPtr) xalloc(sizeof(shadowBufRec));
149 if (!pBuf)
150 return FALSE;
151 #ifdef BACKWARDS_COMPATIBILITY
152 pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc,
153 (DamageDestroyFunc)NULL,
154 DamageReportRawRegion,
155 TRUE, pScreen, pScreen);
156 #else
157 pBuf->pDamage = DamageCreate((DamageReportFunc)NULL,
158 (DamageDestroyFunc)NULL,
159 DamageReportNone,
160 TRUE, pScreen, pScreen);
161 #endif
162 if (!pBuf->pDamage) {
163 xfree(pBuf);
164 return FALSE;
167 wrap(pBuf, pScreen, CloseScreen);
168 wrap(pBuf, pScreen, GetImage);
169 pBuf->update = 0;
170 pBuf->window = 0;
171 pBuf->pPixmap = 0;
172 pBuf->closure = 0;
173 pBuf->randr = 0;
174 #ifdef BACKWARDS_COMPATIBILITY
175 REGION_NULL(pScreen, &pBuf->damage); /* bc */
176 #endif
178 pScreen->devPrivates[shadowScrPrivateIndex].ptr = (pointer) pBuf;
179 return TRUE;
182 Bool
183 shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update,
184 ShadowWindowProc window, int randr, void *closure)
186 shadowBuf(pScreen);
188 if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
189 (pointer)pScreen))
190 return FALSE;
193 * Map simple rotation values to bitmasks; fortunately,
194 * these are all unique
196 switch (randr) {
197 case 0:
198 randr = SHADOW_ROTATE_0;
199 break;
200 case 90:
201 randr = SHADOW_ROTATE_90;
202 break;
203 case 180:
204 randr = SHADOW_ROTATE_180;
205 break;
206 case 270:
207 randr = SHADOW_ROTATE_270;
208 break;
210 pBuf->update = update;
211 pBuf->window = window;
212 pBuf->randr = randr;
213 pBuf->closure = 0;
214 pBuf->pPixmap = pPixmap;
215 DamageRegister(&pPixmap->drawable, pBuf->pDamage);
216 return TRUE;
219 void
220 shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap)
222 shadowBuf(pScreen);
224 if (pBuf->pPixmap) {
225 DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage);
226 pBuf->update = 0;
227 pBuf->window = 0;
228 pBuf->randr = 0;
229 pBuf->closure = 0;
230 pBuf->pPixmap = 0;
233 RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
234 (pointer) pScreen);
237 Bool
238 shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window)
240 PixmapPtr pPixmap;
242 pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height,
243 pScreen->rootDepth);
244 if (!pPixmap)
245 return FALSE;
247 if (!shadowSetup(pScreen)) {
248 pScreen->DestroyPixmap(pPixmap);
249 return FALSE;
252 shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0);
254 return TRUE;