xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

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 }