shadowfb.c revision 1b5d61b8
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 31static Bool ShadowCloseScreen(ScreenPtr pScreen); 32static Bool ShadowCreateRootWindow(WindowPtr pWin); 33 34typedef struct { 35 ScrnInfoPtr pScrn; 36 RefreshAreaFuncPtr preRefresh; 37 RefreshAreaFuncPtr postRefresh; 38 CloseScreenProcPtr CloseScreen; 39 CreateWindowProcPtr CreateWindow; 40} ShadowScreenRec, *ShadowScreenPtr; 41 42static DevPrivateKeyRec ShadowScreenKeyRec; 43 44static ShadowScreenPtr 45shadowfbGetScreenPrivate(ScreenPtr pScreen) 46{ 47 return dixLookupPrivate(&(pScreen)->devPrivates, &ShadowScreenKeyRec); 48} 49 50Bool 51ShadowFBInit2(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 82Bool 83ShadowFBInit(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 97static void 98shadowfbReportPre(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 108static void 109shadowfbReportPost(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 119static Bool 120ShadowCreateRootWindow(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 161static Bool 162ShadowCloseScreen(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} 172