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 #define shadowScrPrivateKey (&shadowScrPrivateKeyRec)
41
42 #define shadowGetBuf(pScr) ((shadowBufPtr) \
43 dixLookupPrivate(&(pScr)->devPrivates, shadowScrPrivateKey))
44 #define shadowBuf(pScr) shadowBufPtr pBuf = shadowGetBuf(pScr)
45
46 #define wrap(priv, real, mem) {\
47 priv->mem = real->mem; \
48 real->mem = shadow##mem; \
49 }
50
51 #define unwrap(priv, real, mem) {\
52 real->mem = priv->mem; \
53 }
54
55 static void
shadowRedisplay(ScreenPtr pScreen)56 shadowRedisplay(ScreenPtr pScreen)
57 {
58 shadowBuf(pScreen);
59 RegionPtr pRegion;
60
61 if (!pBuf || !pBuf->pDamage || !pBuf->update)
62 return;
63 pRegion = DamageRegion(pBuf->pDamage);
64 if (RegionNotEmpty(pRegion)) {
65 (*pBuf->update) (pScreen, pBuf);
66 DamageEmpty(pBuf->pDamage);
67 }
68 }
69
70 static void
shadowBlockHandler(ScreenPtr pScreen,void * timeout)71 shadowBlockHandler(ScreenPtr pScreen, void *timeout)
72 {
73 shadowBuf(pScreen);
74
75 shadowRedisplay(pScreen);
76
77 unwrap(pBuf, pScreen, BlockHandler);
78 pScreen->BlockHandler(pScreen, timeout);
79 wrap(pBuf, pScreen, BlockHandler);
80 }
81
82 static void
shadowGetImage(DrawablePtr pDrawable,int sx,int sy,int w,int h,unsigned int format,unsigned long planeMask,char * pdstLine)83 shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
84 unsigned int format, unsigned long planeMask, char *pdstLine)
85 {
86 ScreenPtr pScreen = pDrawable->pScreen;
87
88 shadowBuf(pScreen);
89
90 /* Many apps use GetImage to sync with the visable frame buffer */
91 if (pDrawable->type == DRAWABLE_WINDOW)
92 shadowRedisplay(pScreen);
93 unwrap(pBuf, pScreen, GetImage);
94 pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
95 wrap(pBuf, pScreen, GetImage);
96 }
97
98 static Bool
shadowCloseScreen(ScreenPtr pScreen)99 shadowCloseScreen(ScreenPtr pScreen)
100 {
101 shadowBuf(pScreen);
102
103 unwrap(pBuf, pScreen, GetImage);
104 unwrap(pBuf, pScreen, CloseScreen);
105 unwrap(pBuf, pScreen, BlockHandler);
106 shadowRemove(pScreen, pBuf->pPixmap);
107 DamageDestroy(pBuf->pDamage);
108 if (pBuf->pPixmap)
109 pScreen->DestroyPixmap(pBuf->pPixmap);
110 free(pBuf);
111 return pScreen->CloseScreen(pScreen);
112 }
113
114 Bool
shadowSetup(ScreenPtr pScreen)115 shadowSetup(ScreenPtr pScreen)
116 {
117 shadowBufPtr pBuf;
118
119 if (!dixRegisterPrivateKey(&shadowScrPrivateKeyRec, PRIVATE_SCREEN, 0))
120 return FALSE;
121
122 if (!DamageSetup(pScreen))
123 return FALSE;
124
125 pBuf = malloc(sizeof(shadowBufRec));
126 if (!pBuf)
127 return FALSE;
128 pBuf->pDamage = DamageCreate((DamageReportFunc) NULL,
129 (DamageDestroyFunc) NULL,
130 DamageReportNone, TRUE, pScreen, pScreen);
131 if (!pBuf->pDamage) {
132 free(pBuf);
133 return FALSE;
134 }
135
136 wrap(pBuf, pScreen, CloseScreen);
137 wrap(pBuf, pScreen, GetImage);
138 wrap(pBuf, pScreen, BlockHandler);
139 pBuf->update = 0;
140 pBuf->window = 0;
141 pBuf->pPixmap = 0;
142 pBuf->closure = 0;
143 pBuf->randr = 0;
144
145 dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf);
146 return TRUE;
147 }
148
149 Bool
shadowAdd(ScreenPtr pScreen,PixmapPtr pPixmap,ShadowUpdateProc update,ShadowWindowProc window,int randr,void * closure)150 shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update,
151 ShadowWindowProc window, int randr, void *closure)
152 {
153 shadowBuf(pScreen);
154
155 /*
156 * Map simple rotation values to bitmasks; fortunately,
157 * these are all unique
158 */
159 switch (randr) {
160 case 0:
161 randr = SHADOW_ROTATE_0;
162 break;
163 case 90:
164 randr = SHADOW_ROTATE_90;
165 break;
166 case 180:
167 randr = SHADOW_ROTATE_180;
168 break;
169 case 270:
170 randr = SHADOW_ROTATE_270;
171 break;
172 }
173 pBuf->update = update;
174 pBuf->window = window;
175 pBuf->randr = randr;
176 pBuf->closure = closure;
177 pBuf->pPixmap = pPixmap;
178 DamageRegister(&pPixmap->drawable, pBuf->pDamage);
179 return TRUE;
180 }
181
182 void
shadowRemove(ScreenPtr pScreen,PixmapPtr pPixmap)183 shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap)
184 {
185 shadowBuf(pScreen);
186
187 if (pBuf->pPixmap) {
188 DamageUnregister(pBuf->pDamage);
189 pBuf->update = 0;
190 pBuf->window = 0;
191 pBuf->randr = 0;
192 pBuf->closure = 0;
193 pBuf->pPixmap = 0;
194 }
195 }
196