shadow.c revision 706f2543
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 39static DevPrivateKeyRec shadowScrPrivateKeyRec; 40#define shadowScrPrivateKey (&shadowScrPrivateKeyRec) 41 42#define wrap(priv, real, mem) {\ 43 priv->mem = real->mem; \ 44 real->mem = shadow##mem; \ 45} 46 47#define unwrap(priv, real, mem) {\ 48 real->mem = priv->mem; \ 49} 50 51static void 52shadowRedisplay(ScreenPtr pScreen) 53{ 54 shadowBuf(pScreen); 55 RegionPtr pRegion; 56 57 if (!pBuf || !pBuf->pDamage || !pBuf->update) 58 return; 59 pRegion = DamageRegion(pBuf->pDamage); 60 if (RegionNotEmpty(pRegion)) { 61 (*pBuf->update)(pScreen, pBuf); 62 DamageEmpty(pBuf->pDamage); 63 } 64} 65 66static void 67shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) 68{ 69 ScreenPtr pScreen = (ScreenPtr) data; 70 71 shadowRedisplay(pScreen); 72} 73 74static void 75shadowWakeupHandler(pointer data, int i, pointer LastSelectMask) 76{ 77} 78 79static void 80shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 81 unsigned int format, unsigned long planeMask, char *pdstLine) 82{ 83 ScreenPtr pScreen = pDrawable->pScreen; 84 shadowBuf(pScreen); 85 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); 92} 93 94#define BACKWARDS_COMPATIBILITY 95 96static Bool 97shadowCloseScreen(int i, ScreenPtr pScreen) 98{ 99 shadowBuf(pScreen); 100 101 unwrap(pBuf, pScreen, GetImage); 102 unwrap(pBuf, pScreen, CloseScreen); 103 shadowRemove(pScreen, pBuf->pPixmap); 104 DamageDestroy(pBuf->pDamage); 105#ifdef BACKWARDS_COMPATIBILITY 106 RegionUninit(&pBuf->damage); /* bc */ 107#endif 108 if (pBuf->pPixmap) 109 pScreen->DestroyPixmap(pBuf->pPixmap); 110 free(pBuf); 111 return pScreen->CloseScreen(i, pScreen); 112} 113 114#ifdef BACKWARDS_COMPATIBILITY 115static void 116shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure) 117{ 118 ScreenPtr pScreen = closure; 119 shadowBufPtr pBuf = (shadowBufPtr) 120 dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey); 121 122 /* Register the damaged region, use DamageReportNone below when we 123 * want to break BC below... */ 124 RegionUnion(&pDamage->damage, &pDamage->damage, pRegion); 125 126 /* 127 * BC hack. In 7.0 and earlier several drivers would inspect the 128 * 'damage' member directly, so we have to keep it existing. 129 */ 130 RegionCopy(&pBuf->damage, pRegion); 131} 132#endif 133 134Bool 135shadowSetup(ScreenPtr pScreen) 136{ 137 shadowBufPtr pBuf; 138 139 if (!dixRegisterPrivateKey(&shadowScrPrivateKeyRec, PRIVATE_SCREEN, 0)) 140 return FALSE; 141 142 if (!DamageSetup(pScreen)) 143 return FALSE; 144 145 pBuf = malloc(sizeof(shadowBufRec)); 146 if (!pBuf) 147 return FALSE; 148#ifdef BACKWARDS_COMPATIBILITY 149 pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc, 150 (DamageDestroyFunc)NULL, 151 DamageReportRawRegion, 152 TRUE, pScreen, pScreen); 153#else 154 pBuf->pDamage = DamageCreate((DamageReportFunc)NULL, 155 (DamageDestroyFunc)NULL, 156 DamageReportNone, 157 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 179Bool 180shadowAdd(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 216void 217shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap) 218{ 219 shadowBuf(pScreen); 220 221 if (pBuf->pPixmap) { 222 DamageUnregister(&pBuf->pPixmap->drawable, 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 234Bool 235shadowInit(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} 253