shadow.c revision 35c4bbdf
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 41#define shadowScrPrivateKey (&shadowScrPrivateKeyRec) 42 43#define wrap(priv, real, mem) {\ 44 priv->mem = real->mem; \ 45 real->mem = shadow##mem; \ 46} 47 48#define unwrap(priv, real, mem) {\ 49 real->mem = priv->mem; \ 50} 51 52static void 53shadowRedisplay(ScreenPtr pScreen) 54{ 55 shadowBuf(pScreen); 56 RegionPtr pRegion; 57 58 if (!pBuf || !pBuf->pDamage || !pBuf->update) 59 return; 60 pRegion = DamageRegion(pBuf->pDamage); 61 if (RegionNotEmpty(pRegion)) { 62 (*pBuf->update) (pScreen, pBuf); 63 DamageEmpty(pBuf->pDamage); 64 } 65} 66 67static void 68shadowBlockHandler(void *data, OSTimePtr pTimeout, void *pRead) 69{ 70 ScreenPtr pScreen = (ScreenPtr) data; 71 72 shadowRedisplay(pScreen); 73} 74 75static void 76shadowWakeupHandler(void *data, int i, void *LastSelectMask) 77{ 78} 79 80static void 81shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, 82 unsigned int format, unsigned long planeMask, char *pdstLine) 83{ 84 ScreenPtr pScreen = pDrawable->pScreen; 85 86 shadowBuf(pScreen); 87 88 /* Many apps use GetImage to sync with the visable frame buffer */ 89 if (pDrawable->type == DRAWABLE_WINDOW) 90 shadowRedisplay(pScreen); 91 unwrap(pBuf, pScreen, GetImage); 92 pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); 93 wrap(pBuf, pScreen, GetImage); 94} 95 96static Bool 97shadowCloseScreen(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 if (pBuf->pPixmap) 106 pScreen->DestroyPixmap(pBuf->pPixmap); 107 free(pBuf); 108 return pScreen->CloseScreen(pScreen); 109} 110 111Bool 112shadowSetup(ScreenPtr pScreen) 113{ 114 shadowBufPtr pBuf; 115 116 if (!dixRegisterPrivateKey(&shadowScrPrivateKeyRec, PRIVATE_SCREEN, 0)) 117 return FALSE; 118 119 if (!DamageSetup(pScreen)) 120 return FALSE; 121 122 pBuf = malloc(sizeof(shadowBufRec)); 123 if (!pBuf) 124 return FALSE; 125 pBuf->pDamage = DamageCreate((DamageReportFunc) NULL, 126 (DamageDestroyFunc) NULL, 127 DamageReportNone, TRUE, pScreen, pScreen); 128 if (!pBuf->pDamage) { 129 free(pBuf); 130 return FALSE; 131 } 132 133 wrap(pBuf, pScreen, CloseScreen); 134 wrap(pBuf, pScreen, GetImage); 135 pBuf->update = 0; 136 pBuf->window = 0; 137 pBuf->pPixmap = 0; 138 pBuf->closure = 0; 139 pBuf->randr = 0; 140 141 dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf); 142 return TRUE; 143} 144 145Bool 146shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update, 147 ShadowWindowProc window, int randr, void *closure) 148{ 149 shadowBuf(pScreen); 150 151 if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, 152 (void *) pScreen)) 153 return FALSE; 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 182void 183shadowRemove(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 RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler, 197 (void *) pScreen); 198} 199