shadow.c revision 4642e01f
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 int shadowScrPrivateKeyIndex; 40DevPrivateKey shadowScrPrivateKey = &shadowScrPrivateKeyIndex; 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 (REGION_NOTEMPTY(pScreen, 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 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); 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 REGION_UNION(pScreen, &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 REGION_COPY(pScreen, &pBuf->damage, pRegion); 131} 132#endif 133 134Bool 135shadowSetup(ScreenPtr pScreen) 136{ 137 shadowBufPtr pBuf; 138 139 if (!DamageSetup(pScreen)) 140 return FALSE; 141 142 pBuf = (shadowBufPtr) xalloc(sizeof(shadowBufRec)); 143 if (!pBuf) 144 return FALSE; 145#ifdef BACKWARDS_COMPATIBILITY 146 pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc, 147 (DamageDestroyFunc)NULL, 148 DamageReportRawRegion, 149 TRUE, pScreen, pScreen); 150#else 151 pBuf->pDamage = DamageCreate((DamageReportFunc)NULL, 152 (DamageDestroyFunc)NULL, 153 DamageReportNone, 154 TRUE, pScreen, pScreen); 155#endif 156 if (!pBuf->pDamage) { 157 xfree(pBuf); 158 return FALSE; 159 } 160 161 wrap(pBuf, pScreen, CloseScreen); 162 wrap(pBuf, pScreen, GetImage); 163 pBuf->update = 0; 164 pBuf->window = 0; 165 pBuf->pPixmap = 0; 166 pBuf->closure = 0; 167 pBuf->randr = 0; 168#ifdef BACKWARDS_COMPATIBILITY 169 REGION_NULL(pScreen, &pBuf->damage); /* bc */ 170#endif 171 172 dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf); 173 return TRUE; 174} 175 176Bool 177shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update, 178 ShadowWindowProc window, int randr, void *closure) 179{ 180 shadowBuf(pScreen); 181 182 if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, 183 (pointer)pScreen)) 184 return FALSE; 185 186 /* 187 * Map simple rotation values to bitmasks; fortunately, 188 * these are all unique 189 */ 190 switch (randr) { 191 case 0: 192 randr = SHADOW_ROTATE_0; 193 break; 194 case 90: 195 randr = SHADOW_ROTATE_90; 196 break; 197 case 180: 198 randr = SHADOW_ROTATE_180; 199 break; 200 case 270: 201 randr = SHADOW_ROTATE_270; 202 break; 203 } 204 pBuf->update = update; 205 pBuf->window = window; 206 pBuf->randr = randr; 207 pBuf->closure = 0; 208 pBuf->pPixmap = pPixmap; 209 DamageRegister(&pPixmap->drawable, pBuf->pDamage); 210 return TRUE; 211} 212 213void 214shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap) 215{ 216 shadowBuf(pScreen); 217 218 if (pBuf->pPixmap) { 219 DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage); 220 pBuf->update = 0; 221 pBuf->window = 0; 222 pBuf->randr = 0; 223 pBuf->closure = 0; 224 pBuf->pPixmap = 0; 225 } 226 227 RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, 228 (pointer) pScreen); 229} 230 231Bool 232shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window) 233{ 234 PixmapPtr pPixmap; 235 236 pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height, 237 pScreen->rootDepth, 0); 238 if (!pPixmap) 239 return FALSE; 240 241 if (!shadowSetup(pScreen)) { 242 pScreen->DestroyPixmap(pPixmap); 243 return FALSE; 244 } 245 246 shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0); 247 248 return TRUE; 249} 250