172 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
   Copyright (C) 1999.  The XFree86 Project Inc.
 | 
						|
   Copyright 2014 Red Hat, Inc.
 | 
						|
 | 
						|
   Written by Mark Vojkovich (mvojkovi@ucsd.edu)
 | 
						|
   Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com)
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef HAVE_XORG_CONFIG_H
 | 
						|
#include <xorg-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include "misc.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "input.h"
 | 
						|
#include <X11/fonts/font.h>
 | 
						|
#include "mi.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "dixfontstr.h"
 | 
						|
#include <X11/fonts/fontstruct.h>
 | 
						|
#include "xf86.h"
 | 
						|
#include "xf86str.h"
 | 
						|
#include "shadowfb.h"
 | 
						|
 | 
						|
#include "picturestr.h"
 | 
						|
 | 
						|
static Bool ShadowCloseScreen(ScreenPtr pScreen);
 | 
						|
static Bool ShadowCreateRootWindow(WindowPtr pWin);
 | 
						|
 | 
						|
typedef struct {
 | 
						|
    ScrnInfoPtr pScrn;
 | 
						|
    RefreshAreaFuncPtr preRefresh;
 | 
						|
    RefreshAreaFuncPtr postRefresh;
 | 
						|
    CloseScreenProcPtr CloseScreen;
 | 
						|
    CreateWindowProcPtr CreateWindow;
 | 
						|
} ShadowScreenRec, *ShadowScreenPtr;
 | 
						|
 | 
						|
static DevPrivateKeyRec ShadowScreenKeyRec;
 | 
						|
 | 
						|
static ShadowScreenPtr
 | 
						|
shadowfbGetScreenPrivate(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    return dixLookupPrivate(&(pScreen)->devPrivates, &ShadowScreenKeyRec);
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ShadowFBInit2(ScreenPtr pScreen,
 | 
						|
              RefreshAreaFuncPtr preRefreshArea,
 | 
						|
              RefreshAreaFuncPtr postRefreshArea)
 | 
						|
{
 | 
						|
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
 | 
						|
    ShadowScreenPtr pPriv;
 | 
						|
 | 
						|
    if (!preRefreshArea && !postRefreshArea)
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (!dixRegisterPrivateKey(&ShadowScreenKeyRec, PRIVATE_SCREEN, 0))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    if (!(pPriv = (ShadowScreenPtr) malloc(sizeof(ShadowScreenRec))))
 | 
						|
        return FALSE;
 | 
						|
 | 
						|
    dixSetPrivate(&pScreen->devPrivates, &ShadowScreenKeyRec, pPriv);
 | 
						|
 | 
						|
    pPriv->pScrn = pScrn;
 | 
						|
    pPriv->preRefresh = preRefreshArea;
 | 
						|
    pPriv->postRefresh = postRefreshArea;
 | 
						|
 | 
						|
    pPriv->CloseScreen = pScreen->CloseScreen;
 | 
						|
    pPriv->CreateWindow = pScreen->CreateWindow;
 | 
						|
 | 
						|
    pScreen->CloseScreen = ShadowCloseScreen;
 | 
						|
    pScreen->CreateWindow = ShadowCreateRootWindow;
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
Bool
 | 
						|
ShadowFBInit(ScreenPtr pScreen, RefreshAreaFuncPtr refreshArea)
 | 
						|
{
 | 
						|
    return ShadowFBInit2(pScreen, NULL, refreshArea);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Note that we don't do DamageEmpty, or indeed look at the region inside the
 | 
						|
 * DamagePtr at all.  This is an optimization, believe it or not.  The
 | 
						|
 * incoming RegionPtr is the new damage, and if we were to empty the region
 | 
						|
 * miext/damage would just have to waste time reallocating and re-unioning
 | 
						|
 * it every time, whereas if we leave it around the union gets fast-pathed
 | 
						|
 * away.
 | 
						|
 */
 | 
						|
 | 
						|
static void
 | 
						|
shadowfbReportPre(DamagePtr damage, RegionPtr reg, void *closure)
 | 
						|
{
 | 
						|
    ShadowScreenPtr pPriv = closure;
 | 
						|
 | 
						|
    if (!pPriv->pScrn->vtSema)
 | 
						|
        return;
 | 
						|
 | 
						|
    pPriv->preRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
shadowfbReportPost(DamagePtr damage, RegionPtr reg, void *closure)
 | 
						|
{
 | 
						|
    ShadowScreenPtr pPriv = closure;
 | 
						|
 | 
						|
    if (!pPriv->pScrn->vtSema)
 | 
						|
        return;
 | 
						|
 | 
						|
    pPriv->postRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
ShadowCreateRootWindow(WindowPtr pWin)
 | 
						|
{
 | 
						|
    Bool ret;
 | 
						|
    ScreenPtr pScreen = pWin->drawable.pScreen;
 | 
						|
    ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
 | 
						|
 | 
						|
    /* paranoia */
 | 
						|
    if (pWin != pScreen->root)
 | 
						|
        ErrorF("ShadowCreateRootWindow called unexpectedly\n");
 | 
						|
 | 
						|
    /* call down, but don't hook ourselves back in; we know the first time
 | 
						|
     * we're called it's for the root window.
 | 
						|
     */
 | 
						|
    pScreen->CreateWindow = pPriv->CreateWindow;
 | 
						|
    ret = pScreen->CreateWindow(pWin);
 | 
						|
 | 
						|
    /* this might look like it leaks, but the damage code reaps listeners
 | 
						|
     * when their drawable disappears.
 | 
						|
     */
 | 
						|
    if (ret) {
 | 
						|
        DamagePtr damage;
 | 
						|
 | 
						|
        if (pPriv->preRefresh) {
 | 
						|
            damage = DamageCreate(shadowfbReportPre, NULL,
 | 
						|
                                  DamageReportRawRegion,
 | 
						|
                                  TRUE, pScreen, pPriv);
 | 
						|
            DamageRegister(&pWin->drawable, damage);
 | 
						|
        }
 | 
						|
 | 
						|
        if (pPriv->postRefresh) {
 | 
						|
            damage = DamageCreate(shadowfbReportPost, NULL,
 | 
						|
                                  DamageReportRawRegion,
 | 
						|
                                  TRUE, pScreen, pPriv);
 | 
						|
            DamageSetReportAfterOp(damage, TRUE);
 | 
						|
            DamageRegister(&pWin->drawable, damage);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static Bool
 | 
						|
ShadowCloseScreen(ScreenPtr pScreen)
 | 
						|
{
 | 
						|
    ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
 | 
						|
 | 
						|
    pScreen->CloseScreen = pPriv->CloseScreen;
 | 
						|
 | 
						|
    free(pPriv);
 | 
						|
 | 
						|
    return (*pScreen->CloseScreen) (pScreen);
 | 
						|
}
 |