xserver

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

fboverlay.c (10364B)


      1 /*
      2  *
      3  * Copyright © 2000 SuSE, Inc.
      4  *
      5  * Permission to use, copy, modify, distribute, and sell this software and its
      6  * documentation for any purpose is hereby granted without fee, provided that
      7  * the above copyright notice appear in all copies and that both that
      8  * copyright notice and this permission notice appear in supporting
      9  * documentation, and that the name of SuSE not be used in advertising or
     10  * publicity pertaining to distribution of the software without specific,
     11  * written prior permission.  SuSE makes no representations about the
     12  * suitability of this software for any purpose.  It is provided "as is"
     13  * without express or implied warranty.
     14  *
     15  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
     17  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     19  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     21  *
     22  * Author:  Keith Packard, SuSE, Inc.
     23  */
     24 
     25 #ifdef HAVE_DIX_CONFIG_H
     26 #include <dix-config.h>
     27 #endif
     28 
     29 #include <stdlib.h>
     30 
     31 #include "fb.h"
     32 #include "fboverlay.h"
     33 #include "shmint.h"
     34 
     35 static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec;
     36 
     37 #define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec)
     38 
     39 DevPrivateKey
     40 fbOverlayGetScreenPrivateKey(void)
     41 {
     42     return fbOverlayScreenPrivateKey;
     43 }
     44 
     45 /*
     46  * Replace this if you want something supporting
     47  * multiple overlays with the same depth
     48  */
     49 Bool
     50 fbOverlayCreateWindow(WindowPtr pWin)
     51 {
     52     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
     53     int i;
     54     PixmapPtr pPixmap;
     55 
     56     if (pWin->drawable.class != InputOutput)
     57         return TRUE;
     58 
     59     for (i = 0; i < pScrPriv->nlayers; i++) {
     60         pPixmap = pScrPriv->layer[i].u.run.pixmap;
     61         if (pWin->drawable.depth == pPixmap->drawable.depth) {
     62             dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin), pPixmap);
     63             /*
     64              * Make sure layer keys are written correctly by
     65              * having non-root layers set to full while the
     66              * root layer is set to empty.  This will cause
     67              * all of the layers to get painted when the root
     68              * is mapped
     69              */
     70             if (!pWin->parent) {
     71                 RegionEmpty(&pScrPriv->layer[i].u.run.region);
     72             }
     73             return TRUE;
     74         }
     75     }
     76     return FALSE;
     77 }
     78 
     79 Bool
     80 fbOverlayCloseScreen(ScreenPtr pScreen)
     81 {
     82     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
     83     int i;
     84 
     85     for (i = 0; i < pScrPriv->nlayers; i++) {
     86         (*pScreen->DestroyPixmap) (pScrPriv->layer[i].u.run.pixmap);
     87         RegionUninit(&pScrPriv->layer[i].u.run.region);
     88     }
     89     return TRUE;
     90 }
     91 
     92 /*
     93  * Return layer containing this window
     94  */
     95 int
     96 fbOverlayWindowLayer(WindowPtr pWin)
     97 {
     98     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
     99     int i;
    100 
    101     for (i = 0; i < pScrPriv->nlayers; i++)
    102         if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey(pWin)) ==
    103             (void *) pScrPriv->layer[i].u.run.pixmap)
    104             return i;
    105     return 0;
    106 }
    107 
    108 Bool
    109 fbOverlayCreateScreenResources(ScreenPtr pScreen)
    110 {
    111     int i;
    112     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
    113     PixmapPtr pPixmap;
    114     void *pbits;
    115     int width;
    116     int depth;
    117     BoxRec box;
    118 
    119     if (!miCreateScreenResources(pScreen))
    120         return FALSE;
    121 
    122     box.x1 = 0;
    123     box.y1 = 0;
    124     box.x2 = pScreen->width;
    125     box.y2 = pScreen->height;
    126     for (i = 0; i < pScrPriv->nlayers; i++) {
    127         pbits = pScrPriv->layer[i].u.init.pbits;
    128         width = pScrPriv->layer[i].u.init.width;
    129         depth = pScrPriv->layer[i].u.init.depth;
    130         pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0);
    131         if (!pPixmap)
    132             return FALSE;
    133         if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width,
    134                                              pScreen->height, depth,
    135                                              BitsPerPixel(depth),
    136                                              PixmapBytePad(width, depth),
    137                                              pbits))
    138             return FALSE;
    139         pScrPriv->layer[i].u.run.pixmap = pPixmap;
    140         RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0);
    141     }
    142     pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap;
    143     return TRUE;
    144 }
    145 
    146 void
    147 fbOverlayPaintKey(DrawablePtr pDrawable,
    148                   RegionPtr pRegion, CARD32 pixel, int layer)
    149 {
    150     fbFillRegionSolid(pDrawable, pRegion, 0,
    151                       fbReplicatePixel(pixel, pDrawable->bitsPerPixel));
    152 }
    153 
    154 /*
    155  * Track visible region for each layer
    156  */
    157 void
    158 fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn)
    159 {
    160     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
    161     int i;
    162     RegionRec rgnNew;
    163 
    164     if (!prgn || !RegionNotEmpty(prgn))
    165         return;
    166     for (i = 0; i < pScrPriv->nlayers; i++) {
    167         if (i == layer) {
    168             /* add new piece to this fb */
    169             RegionUnion(&pScrPriv->layer[i].u.run.region,
    170                         &pScrPriv->layer[i].u.run.region, prgn);
    171         }
    172         else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region)) {
    173             /* paint new piece with chroma key */
    174             RegionNull(&rgnNew);
    175             RegionIntersect(&rgnNew, prgn, &pScrPriv->layer[i].u.run.region);
    176             (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable,
    177                                    &rgnNew, pScrPriv->layer[i].key, i);
    178             RegionUninit(&rgnNew);
    179             /* remove piece from other fbs */
    180             RegionSubtract(&pScrPriv->layer[i].u.run.region,
    181                            &pScrPriv->layer[i].u.run.region, prgn);
    182         }
    183     }
    184 }
    185 
    186 /*
    187  * Copy only areas in each layer containing real bits
    188  */
    189 void
    190 fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
    191 {
    192     ScreenPtr pScreen = pWin->drawable.pScreen;
    193     FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
    194     RegionRec rgnDst;
    195     int dx, dy;
    196     int i;
    197     RegionRec layerRgn[FB_OVERLAY_MAX];
    198     PixmapPtr pPixmap;
    199 
    200     dx = ptOldOrg.x - pWin->drawable.x;
    201     dy = ptOldOrg.y - pWin->drawable.y;
    202 
    203     /*
    204      * Clip to existing bits
    205      */
    206     RegionTranslate(prgnSrc, -dx, -dy);
    207     RegionNull(&rgnDst);
    208     RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
    209     RegionTranslate(&rgnDst, dx, dy);
    210     /*
    211      * Compute the portion of each fb affected by this copy
    212      */
    213     for (i = 0; i < pScrPriv->nlayers; i++) {
    214         RegionNull(&layerRgn[i]);
    215         RegionIntersect(&layerRgn[i], &rgnDst,
    216                         &pScrPriv->layer[i].u.run.region);
    217         if (RegionNotEmpty(&layerRgn[i])) {
    218             RegionTranslate(&layerRgn[i], -dx, -dy);
    219             pPixmap = pScrPriv->layer[i].u.run.pixmap;
    220             miCopyRegion(&pPixmap->drawable, &pPixmap->drawable,
    221                          0,
    222                          &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0,
    223                          (void *) (long) i);
    224         }
    225     }
    226     /*
    227      * Update regions
    228      */
    229     for (i = 0; i < pScrPriv->nlayers; i++) {
    230         if (RegionNotEmpty(&layerRgn[i]))
    231             fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]);
    232 
    233         RegionUninit(&layerRgn[i]);
    234     }
    235     RegionUninit(&rgnDst);
    236 }
    237 
    238 void
    239 fbOverlayWindowExposures(WindowPtr pWin, RegionPtr prgn)
    240 {
    241     fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
    242                                fbOverlayWindowLayer(pWin), prgn);
    243     miWindowExposures(pWin, prgn);
    244 }
    245 
    246 Bool
    247 fbOverlaySetupScreen(ScreenPtr pScreen,
    248                      void *pbits1,
    249                      void *pbits2,
    250                      int xsize,
    251                      int ysize,
    252                      int dpix,
    253                      int dpiy, int width1, int width2, int bpp1, int bpp2)
    254 {
    255     return fbSetupScreen(pScreen,
    256                          pbits1, xsize, ysize, dpix, dpiy, width1, bpp1);
    257 }
    258 
    259 Bool
    260 fbOverlayFinishScreenInit(ScreenPtr pScreen,
    261                           void *pbits1,
    262                           void *pbits2,
    263                           int xsize,
    264                           int ysize,
    265                           int dpix,
    266                           int dpiy,
    267                           int width1,
    268                           int width2,
    269                           int bpp1, int bpp2, int depth1, int depth2)
    270 {
    271     VisualPtr visuals;
    272     DepthPtr depths;
    273     int nvisuals;
    274     int ndepths;
    275     VisualID defaultVisual;
    276     FbOverlayScrPrivPtr pScrPriv;
    277 
    278     if (!dixRegisterPrivateKey
    279         (&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
    280         return FALSE;
    281 
    282     if (bpp1 == 24 || bpp2 == 24)
    283         return FALSE;
    284 
    285     pScrPriv = malloc(sizeof(FbOverlayScrPrivRec));
    286     if (!pScrPriv)
    287         return FALSE;
    288 
    289     if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1,
    290                        &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) |
    291                        ((unsigned long) 1 << (bpp2 - 1)), 8)) {
    292         free(pScrPriv);
    293         return FALSE;
    294     }
    295     if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0,
    296                       depth1, ndepths, depths,
    297                       defaultVisual, nvisuals, visuals)) {
    298         free(pScrPriv);
    299         return FALSE;
    300     }
    301     /* MI thinks there's no frame buffer */
    302 #ifdef MITSHM
    303     ShmRegisterFbFuncs(pScreen);
    304 #endif
    305     pScreen->minInstalledCmaps = 1;
    306     pScreen->maxInstalledCmaps = 2;
    307 
    308     pScrPriv->nlayers = 2;
    309     pScrPriv->PaintKey = fbOverlayPaintKey;
    310     pScrPriv->CopyWindow = fbCopyWindowProc;
    311     pScrPriv->layer[0].u.init.pbits = pbits1;
    312     pScrPriv->layer[0].u.init.width = width1;
    313     pScrPriv->layer[0].u.init.depth = depth1;
    314 
    315     pScrPriv->layer[1].u.init.pbits = pbits2;
    316     pScrPriv->layer[1].u.init.width = width2;
    317     pScrPriv->layer[1].u.init.depth = depth2;
    318     dixSetPrivate(&pScreen->devPrivates, fbOverlayScreenPrivateKey, pScrPriv);
    319 
    320     /* overwrite miCloseScreen with our own */
    321     pScreen->CloseScreen = fbOverlayCloseScreen;
    322     pScreen->CreateScreenResources = fbOverlayCreateScreenResources;
    323     pScreen->CreateWindow = fbOverlayCreateWindow;
    324     pScreen->WindowExposures = fbOverlayWindowExposures;
    325     pScreen->CopyWindow = fbOverlayCopyWindow;
    326 
    327     return TRUE;
    328 }