249 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			249 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Copyright © 2000 Keith Packard
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that
 | |
|  * copyright notice and this permission notice appear in supporting
 | |
|  * documentation, and that the name of Keith Packard not be used in
 | |
|  * advertising or publicity pertaining to distribution of the software without
 | |
|  * specific, written prior permission.  Keith Packard makes no
 | |
|  * representations about the suitability of this software for any purpose.  It
 | |
|  * is provided "as is" without express or implied warranty.
 | |
|  *
 | |
|  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 | |
|  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 | |
|  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 | |
|  * PERFORMANCE OF THIS SOFTWARE.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include    <X11/X.h>
 | |
| #include    "scrnintstr.h"
 | |
| #include    "windowstr.h"
 | |
| #include    "dixfontstr.h"
 | |
| #include    "mi.h"
 | |
| #include    "regionstr.h"
 | |
| #include    "globals.h"
 | |
| #include    "gcstruct.h"
 | |
| #include    "shadow.h"
 | |
| 
 | |
| DevPrivateKey shadowScrPrivateKey = &shadowScrPrivateKey;
 | |
| 
 | |
| #define wrap(priv, real, mem) {\
 | |
|     priv->mem = real->mem; \
 | |
|     real->mem = shadow##mem; \
 | |
| }
 | |
| 
 | |
| #define unwrap(priv, real, mem) {\
 | |
|     real->mem = priv->mem; \
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowRedisplay(ScreenPtr pScreen)
 | |
| {
 | |
|     shadowBuf(pScreen);
 | |
|     RegionPtr pRegion;
 | |
| 
 | |
|     if (!pBuf || !pBuf->pDamage || !pBuf->update)
 | |
| 	return;
 | |
|     pRegion = DamageRegion(pBuf->pDamage);
 | |
|     if (REGION_NOTEMPTY(pScreen, pRegion)) {
 | |
| 	(*pBuf->update)(pScreen, pBuf);
 | |
| 	DamageEmpty(pBuf->pDamage);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
 | |
| {
 | |
|     ScreenPtr pScreen = (ScreenPtr) data;
 | |
| 
 | |
|     shadowRedisplay(pScreen);
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowWakeupHandler(pointer data, int i, pointer LastSelectMask)
 | |
| {
 | |
| }
 | |
| 
 | |
| static void
 | |
| shadowGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
 | |
| 	       unsigned int format, unsigned long planeMask, char *pdstLine)
 | |
| {
 | |
|     ScreenPtr pScreen = pDrawable->pScreen;
 | |
|     shadowBuf(pScreen);
 | |
| 
 | |
|     /* Many apps use GetImage to sync with the visable frame buffer */
 | |
|     if (pDrawable->type == DRAWABLE_WINDOW)
 | |
| 	shadowRedisplay(pScreen);
 | |
|     unwrap(pBuf, pScreen, GetImage);
 | |
|     pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
 | |
|     wrap(pBuf, pScreen, GetImage);
 | |
| }
 | |
| 
 | |
| #define BACKWARDS_COMPATIBILITY
 | |
| 
 | |
| static Bool
 | |
| shadowCloseScreen(int i, ScreenPtr pScreen)
 | |
| {
 | |
|     shadowBuf(pScreen);
 | |
| 
 | |
|     unwrap(pBuf, pScreen, GetImage);
 | |
|     unwrap(pBuf, pScreen, CloseScreen);
 | |
|     shadowRemove(pScreen, pBuf->pPixmap);
 | |
|     DamageDestroy(pBuf->pDamage);
 | |
| #ifdef BACKWARDS_COMPATIBILITY
 | |
|     REGION_UNINIT(pScreen, &pBuf->damage); /* bc */
 | |
| #endif
 | |
|     if (pBuf->pPixmap)
 | |
| 	pScreen->DestroyPixmap(pBuf->pPixmap);
 | |
|     xfree(pBuf);
 | |
|     return pScreen->CloseScreen(i, pScreen);
 | |
| }
 | |
| 
 | |
| #ifdef BACKWARDS_COMPATIBILITY
 | |
| static void
 | |
| shadowReportFunc(DamagePtr pDamage, RegionPtr pRegion, void *closure)
 | |
| {
 | |
|     ScreenPtr pScreen = closure;
 | |
|     shadowBufPtr pBuf = (shadowBufPtr)
 | |
| 	dixLookupPrivate(&pScreen->devPrivates, shadowScrPrivateKey);
 | |
| 
 | |
|     /* Register the damaged region, use DamageReportNone below when we
 | |
|      * want to break BC below... */
 | |
|     REGION_UNION(pScreen, &pDamage->damage, &pDamage->damage, pRegion);
 | |
| 
 | |
|     /*
 | |
|      * BC hack.  In 7.0 and earlier several drivers would inspect the
 | |
|      * 'damage' member directly, so we have to keep it existing.
 | |
|      */
 | |
|     REGION_COPY(pScreen, &pBuf->damage, pRegion);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| Bool
 | |
| shadowSetup(ScreenPtr pScreen)
 | |
| {
 | |
|     shadowBufPtr pBuf;
 | |
| 
 | |
|     if (!DamageSetup(pScreen))
 | |
| 	return FALSE;
 | |
| 
 | |
|     pBuf = (shadowBufPtr) xalloc(sizeof(shadowBufRec));
 | |
|     if (!pBuf)
 | |
| 	return FALSE;
 | |
| #ifdef BACKWARDS_COMPATIBILITY
 | |
|     pBuf->pDamage = DamageCreate((DamageReportFunc)shadowReportFunc, 
 | |
| 		    		 (DamageDestroyFunc)NULL,
 | |
| 				 DamageReportRawRegion,
 | |
| 				 TRUE, pScreen, pScreen);
 | |
| #else
 | |
|     pBuf->pDamage = DamageCreate((DamageReportFunc)NULL, 
 | |
| 		    		 (DamageDestroyFunc)NULL,
 | |
| 				 DamageReportNone,
 | |
| 				 TRUE, pScreen, pScreen);
 | |
| #endif
 | |
|     if (!pBuf->pDamage) {
 | |
| 	xfree(pBuf);
 | |
| 	return FALSE;
 | |
|     }
 | |
| 
 | |
|     wrap(pBuf, pScreen, CloseScreen);
 | |
|     wrap(pBuf, pScreen, GetImage);
 | |
|     pBuf->update = 0;
 | |
|     pBuf->window = 0;
 | |
|     pBuf->pPixmap = 0;
 | |
|     pBuf->closure = 0;
 | |
|     pBuf->randr = 0;
 | |
| #ifdef BACKWARDS_COMPATIBILITY
 | |
|     REGION_NULL(pScreen, &pBuf->damage); /* bc */
 | |
| #endif
 | |
| 
 | |
|     dixSetPrivate(&pScreen->devPrivates, shadowScrPrivateKey, pBuf);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| Bool
 | |
| shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update,
 | |
| 	  ShadowWindowProc window, int randr, void *closure)
 | |
| {
 | |
|     shadowBuf(pScreen);
 | |
| 
 | |
|     if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
 | |
| 					(pointer)pScreen))
 | |
| 	return FALSE;
 | |
| 
 | |
|     /*
 | |
|      * Map simple rotation values to bitmasks; fortunately,
 | |
|      * these are all unique
 | |
|      */
 | |
|     switch (randr) {
 | |
|     case 0:
 | |
| 	randr = SHADOW_ROTATE_0;
 | |
| 	break;
 | |
|     case 90:
 | |
| 	randr = SHADOW_ROTATE_90;
 | |
| 	break;
 | |
|     case 180:
 | |
| 	randr = SHADOW_ROTATE_180;
 | |
| 	break;
 | |
|     case 270:
 | |
| 	randr = SHADOW_ROTATE_270;
 | |
| 	break;
 | |
|     }
 | |
|     pBuf->update = update;
 | |
|     pBuf->window = window;
 | |
|     pBuf->randr = randr;
 | |
|     pBuf->closure = 0;
 | |
|     pBuf->pPixmap = pPixmap;
 | |
|     DamageRegister(&pPixmap->drawable, pBuf->pDamage);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| void
 | |
| shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap)
 | |
| {
 | |
|     shadowBuf(pScreen);
 | |
| 
 | |
|     if (pBuf->pPixmap) {
 | |
| 	DamageUnregister(&pBuf->pPixmap->drawable, pBuf->pDamage);
 | |
| 	pBuf->update = 0;
 | |
| 	pBuf->window = 0;
 | |
| 	pBuf->randr = 0;
 | |
| 	pBuf->closure = 0;
 | |
| 	pBuf->pPixmap = 0;
 | |
|     }
 | |
| 
 | |
|     RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
 | |
| 				 (pointer) pScreen);
 | |
| }
 | |
| 
 | |
| Bool
 | |
| shadowInit(ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window)
 | |
| {
 | |
|     PixmapPtr pPixmap;
 | |
|     
 | |
|     pPixmap = pScreen->CreatePixmap(pScreen, pScreen->width, pScreen->height,
 | |
| 				    pScreen->rootDepth, 0);
 | |
|     if (!pPixmap)
 | |
| 	return FALSE;
 | |
|     
 | |
|     if (!shadowSetup(pScreen)) {
 | |
| 	pScreen->DestroyPixmap(pPixmap);
 | |
| 	return FALSE;
 | |
|     }
 | |
| 
 | |
|     shadowAdd(pScreen, pPixmap, update, window, SHADOW_ROTATE_0, 0);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 |