shadow.c revision 05b261ec
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 39int shadowScrPrivateIndex; 40int shadowGeneration; 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 = pScreen->devPrivates[shadowScrPrivateIndex].ptr; 120 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); 124 125 /* 126 * BC hack. In 7.0 and earlier several drivers would inspect the 127 * 'damage' member directly, so we have to keep it existing. 128 */ 129 REGION_COPY(pScreen, &pBuf->damage, pRegion); 130} 131#endif 132 133Bool 134shadowSetup(ScreenPtr pScreen) 135{ 136 shadowBufPtr pBuf; 137 138 if (!DamageSetup(pScreen)) 139 return FALSE; 140 141 if (shadowGeneration != serverGeneration) { 142 shadowScrPrivateIndex = AllocateScreenPrivateIndex(); 143 if (shadowScrPrivateIndex == -1) 144 return FALSE; 145 shadowGeneration = serverGeneration; 146 } 147 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; 165 } 166 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 177 178 pScreen->devPrivates[shadowScrPrivateIndex].ptr = (pointer) pBuf; 179 return TRUE; 180} 181 182Bool 183shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update, 184 ShadowWindowProc window, int randr, void *closure) 185{ 186 shadowBuf(pScreen); 187 188 if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, 189 (pointer)pScreen)) 190 return FALSE; 191 192 /* 193 * Map simple rotation values to bitmasks; fortunately, 194 * these are all unique 195 */ 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; 209 } 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; 217} 218 219void 220shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap) 221{ 222 shadowBuf(pScreen); 223 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; 231 } 232 233 RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, 234 (pointer) pScreen); 235} 236 237Bool 238shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window) 239{ 240 PixmapPtr pPixmap; 241 242 pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height, 243 pScreen->rootDepth); 244 if (!pPixmap) 245 return FALSE; 246 247 if (!shadowSetup(pScreen)) { 248 pScreen->DestroyPixmap(pPixmap); 249 return FALSE; 250 } 251 252 shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0); 253 254 return TRUE; 255} 256