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 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 55static void 56shadowRedisplay(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 70static void 71shadowBlockHandler(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 82static void 83shadowGetImage(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 visible 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 98static Bool 99shadowCloseScreen(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 114Bool 115shadowSetup(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 149Bool 150shadowAdd(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 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