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