xref: /OK3568_Linux_fs/external/xserver/hw/xfree86/shadowfb/shadowfb.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun    Copyright (C) 1999.  The XFree86 Project Inc.
3*4882a593Smuzhiyun    Copyright 2014 Red Hat, Inc.
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun    Written by Mark Vojkovich (mvojkovi@ucsd.edu)
6*4882a593Smuzhiyun    Pre-fb-write callbacks and RENDER support - Nolan Leake (nolan@vmware.com)
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
10*4882a593Smuzhiyun #include <xorg-config.h>
11*4882a593Smuzhiyun #endif
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <X11/X.h>
14*4882a593Smuzhiyun #include <X11/Xproto.h>
15*4882a593Smuzhiyun #include "misc.h"
16*4882a593Smuzhiyun #include "pixmapstr.h"
17*4882a593Smuzhiyun #include "input.h"
18*4882a593Smuzhiyun #include <X11/fonts/font.h>
19*4882a593Smuzhiyun #include "mi.h"
20*4882a593Smuzhiyun #include "scrnintstr.h"
21*4882a593Smuzhiyun #include "windowstr.h"
22*4882a593Smuzhiyun #include "gcstruct.h"
23*4882a593Smuzhiyun #include "dixfontstr.h"
24*4882a593Smuzhiyun #include <X11/fonts/fontstruct.h>
25*4882a593Smuzhiyun #include "xf86.h"
26*4882a593Smuzhiyun #include "xf86str.h"
27*4882a593Smuzhiyun #include "shadowfb.h"
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #include "picturestr.h"
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static Bool ShadowCloseScreen(ScreenPtr pScreen);
32*4882a593Smuzhiyun static Bool ShadowCreateRootWindow(WindowPtr pWin);
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun typedef struct {
35*4882a593Smuzhiyun     ScrnInfoPtr pScrn;
36*4882a593Smuzhiyun     RefreshAreaFuncPtr preRefresh;
37*4882a593Smuzhiyun     RefreshAreaFuncPtr postRefresh;
38*4882a593Smuzhiyun     CloseScreenProcPtr CloseScreen;
39*4882a593Smuzhiyun     CreateWindowProcPtr CreateWindow;
40*4882a593Smuzhiyun } ShadowScreenRec, *ShadowScreenPtr;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun static DevPrivateKeyRec ShadowScreenKeyRec;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static ShadowScreenPtr
shadowfbGetScreenPrivate(ScreenPtr pScreen)45*4882a593Smuzhiyun shadowfbGetScreenPrivate(ScreenPtr pScreen)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun     return dixLookupPrivate(&(pScreen)->devPrivates, &ShadowScreenKeyRec);
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun Bool
ShadowFBInit2(ScreenPtr pScreen,RefreshAreaFuncPtr preRefreshArea,RefreshAreaFuncPtr postRefreshArea)51*4882a593Smuzhiyun ShadowFBInit2(ScreenPtr pScreen,
52*4882a593Smuzhiyun               RefreshAreaFuncPtr preRefreshArea,
53*4882a593Smuzhiyun               RefreshAreaFuncPtr postRefreshArea)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
56*4882a593Smuzhiyun     ShadowScreenPtr pPriv;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun     if (!preRefreshArea && !postRefreshArea)
59*4882a593Smuzhiyun         return FALSE;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun     if (!dixRegisterPrivateKey(&ShadowScreenKeyRec, PRIVATE_SCREEN, 0))
62*4882a593Smuzhiyun         return FALSE;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun     if (!(pPriv = (ShadowScreenPtr) malloc(sizeof(ShadowScreenRec))))
65*4882a593Smuzhiyun         return FALSE;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun     dixSetPrivate(&pScreen->devPrivates, &ShadowScreenKeyRec, pPriv);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun     pPriv->pScrn = pScrn;
70*4882a593Smuzhiyun     pPriv->preRefresh = preRefreshArea;
71*4882a593Smuzhiyun     pPriv->postRefresh = postRefreshArea;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun     pPriv->CloseScreen = pScreen->CloseScreen;
74*4882a593Smuzhiyun     pPriv->CreateWindow = pScreen->CreateWindow;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun     pScreen->CloseScreen = ShadowCloseScreen;
77*4882a593Smuzhiyun     pScreen->CreateWindow = ShadowCreateRootWindow;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun     return TRUE;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun Bool
ShadowFBInit(ScreenPtr pScreen,RefreshAreaFuncPtr refreshArea)83*4882a593Smuzhiyun ShadowFBInit(ScreenPtr pScreen, RefreshAreaFuncPtr refreshArea)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun     return ShadowFBInit2(pScreen, NULL, refreshArea);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /*
89*4882a593Smuzhiyun  * Note that we don't do DamageEmpty, or indeed look at the region inside the
90*4882a593Smuzhiyun  * DamagePtr at all.  This is an optimization, believe it or not.  The
91*4882a593Smuzhiyun  * incoming RegionPtr is the new damage, and if we were to empty the region
92*4882a593Smuzhiyun  * miext/damage would just have to waste time reallocating and re-unioning
93*4882a593Smuzhiyun  * it every time, whereas if we leave it around the union gets fast-pathed
94*4882a593Smuzhiyun  * away.
95*4882a593Smuzhiyun  */
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun static void
shadowfbReportPre(DamagePtr damage,RegionPtr reg,void * closure)98*4882a593Smuzhiyun shadowfbReportPre(DamagePtr damage, RegionPtr reg, void *closure)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun     ShadowScreenPtr pPriv = closure;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun     if (!pPriv->pScrn->vtSema)
103*4882a593Smuzhiyun         return;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     pPriv->preRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static void
shadowfbReportPost(DamagePtr damage,RegionPtr reg,void * closure)109*4882a593Smuzhiyun shadowfbReportPost(DamagePtr damage, RegionPtr reg, void *closure)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun     ShadowScreenPtr pPriv = closure;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun     if (!pPriv->pScrn->vtSema)
114*4882a593Smuzhiyun         return;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun     pPriv->postRefresh(pPriv->pScrn, RegionNumRects(reg), RegionRects(reg));
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun static Bool
ShadowCreateRootWindow(WindowPtr pWin)120*4882a593Smuzhiyun ShadowCreateRootWindow(WindowPtr pWin)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun     Bool ret;
123*4882a593Smuzhiyun     ScreenPtr pScreen = pWin->drawable.pScreen;
124*4882a593Smuzhiyun     ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun     /* paranoia */
127*4882a593Smuzhiyun     if (pWin != pScreen->root)
128*4882a593Smuzhiyun         ErrorF("ShadowCreateRootWindow called unexpectedly\n");
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun     /* call down, but don't hook ourselves back in; we know the first time
131*4882a593Smuzhiyun      * we're called it's for the root window.
132*4882a593Smuzhiyun      */
133*4882a593Smuzhiyun     pScreen->CreateWindow = pPriv->CreateWindow;
134*4882a593Smuzhiyun     ret = pScreen->CreateWindow(pWin);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun     /* this might look like it leaks, but the damage code reaps listeners
137*4882a593Smuzhiyun      * when their drawable disappears.
138*4882a593Smuzhiyun      */
139*4882a593Smuzhiyun     if (ret) {
140*4882a593Smuzhiyun         DamagePtr damage;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun         if (pPriv->preRefresh) {
143*4882a593Smuzhiyun             damage = DamageCreate(shadowfbReportPre, NULL,
144*4882a593Smuzhiyun                                   DamageReportRawRegion,
145*4882a593Smuzhiyun                                   TRUE, pScreen, pPriv);
146*4882a593Smuzhiyun             DamageRegister(&pWin->drawable, damage);
147*4882a593Smuzhiyun         }
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun         if (pPriv->postRefresh) {
150*4882a593Smuzhiyun             damage = DamageCreate(shadowfbReportPost, NULL,
151*4882a593Smuzhiyun                                   DamageReportRawRegion,
152*4882a593Smuzhiyun                                   TRUE, pScreen, pPriv);
153*4882a593Smuzhiyun             DamageSetReportAfterOp(damage, TRUE);
154*4882a593Smuzhiyun             DamageRegister(&pWin->drawable, damage);
155*4882a593Smuzhiyun         }
156*4882a593Smuzhiyun     }
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun     return ret;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun static Bool
ShadowCloseScreen(ScreenPtr pScreen)162*4882a593Smuzhiyun ShadowCloseScreen(ScreenPtr pScreen)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun     ShadowScreenPtr pPriv = shadowfbGetScreenPrivate(pScreen);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     pScreen->CloseScreen = pPriv->CloseScreen;
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun     free(pPriv);
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun     return (*pScreen->CloseScreen) (pScreen);
171*4882a593Smuzhiyun }
172