Edit

IABSD.fr/xenocara/xserver/fb/fboverlay.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2012-06-10 13:21:05
    Hash : e60da745
    Message : Update to xserver 1.12.2. tested by naddy@, krw@, mpi@.

  • xserver/fb/fboverlay.c
  • /*
     *
     * Copyright © 2000 SuSE, Inc.
     *
     * Permission to use, copy, modify, distribute, and sell this software and its
     * documentation for any purpose is hereby granted without fee, provided that
     * the above copyright notice appear in all copies and that both that
     * copyright notice and this permission notice appear in supporting
     * documentation, and that the name of SuSE not be used in advertising or
     * publicity pertaining to distribution of the software without specific,
     * written prior permission.  SuSE makes no representations about the
     * suitability of this software for any purpose.  It is provided "as is"
     * without express or implied warranty.
     *
     * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
     * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
     * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     *
     * Author:  Keith Packard, SuSE, Inc.
     */
    
    #ifdef HAVE_DIX_CONFIG_H
    #include <dix-config.h>
    #endif
    
    #include <stdlib.h>
    
    #include "fb.h"
    #include "fboverlay.h"
    #include "shmint.h"
    
    static DevPrivateKeyRec fbOverlayScreenPrivateKeyRec;
    
    #define fbOverlayScreenPrivateKey (&fbOverlayScreenPrivateKeyRec)
    
    DevPrivateKey
    fbOverlayGetScreenPrivateKey(void)
    {
        return fbOverlayScreenPrivateKey;
    }
    
    /*
     * Replace this if you want something supporting
     * multiple overlays with the same depth
     */
    Bool
    fbOverlayCreateWindow(WindowPtr pWin)
    {
        FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
        int i;
        PixmapPtr pPixmap;
    
        if (pWin->drawable.class != InputOutput)
            return TRUE;
    
        if (pWin->drawable.bitsPerPixel == 32)
            pWin->drawable.bitsPerPixel =
                fbGetScreenPrivate(pWin->drawable.pScreen)->win32bpp;
    
        for (i = 0; i < pScrPriv->nlayers; i++) {
            pPixmap = pScrPriv->layer[i].u.run.pixmap;
            if (pWin->drawable.depth == pPixmap->drawable.depth) {
                dixSetPrivate(&pWin->devPrivates, fbGetWinPrivateKey(), pPixmap);
                /*
                 * Make sure layer keys are written correctly by
                 * having non-root layers set to full while the
                 * root layer is set to empty.  This will cause
                 * all of the layers to get painted when the root
                 * is mapped
                 */
                if (!pWin->parent) {
                    RegionEmpty(&pScrPriv->layer[i].u.run.region);
                }
                return TRUE;
            }
        }
        return FALSE;
    }
    
    Bool
    fbOverlayCloseScreen(int iScreen, ScreenPtr pScreen)
    {
        FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
        int i;
    
        for (i = 0; i < pScrPriv->nlayers; i++) {
            (*pScreen->DestroyPixmap) (pScrPriv->layer[i].u.run.pixmap);
            RegionUninit(&pScrPriv->layer[i].u.run.region);
        }
        return TRUE;
    }
    
    /*
     * Return layer containing this window
     */
    int
    fbOverlayWindowLayer(WindowPtr pWin)
    {
        FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pWin->drawable.pScreen);
        int i;
    
        for (i = 0; i < pScrPriv->nlayers; i++)
            if (dixLookupPrivate(&pWin->devPrivates, fbGetWinPrivateKey()) ==
                (pointer) pScrPriv->layer[i].u.run.pixmap)
                return i;
        return 0;
    }
    
    Bool
    fbOverlayCreateScreenResources(ScreenPtr pScreen)
    {
        int i;
        FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
        PixmapPtr pPixmap;
        pointer pbits;
        int width;
        int depth;
        BoxRec box;
    
        if (!miCreateScreenResources(pScreen))
            return FALSE;
    
        box.x1 = 0;
        box.y1 = 0;
        box.x2 = pScreen->width;
        box.y2 = pScreen->height;
        for (i = 0; i < pScrPriv->nlayers; i++) {
            pbits = pScrPriv->layer[i].u.init.pbits;
            width = pScrPriv->layer[i].u.init.width;
            depth = pScrPriv->layer[i].u.init.depth;
            pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0);
            if (!pPixmap)
                return FALSE;
            if (!(*pScreen->ModifyPixmapHeader) (pPixmap, pScreen->width,
                                                 pScreen->height, depth,
                                                 BitsPerPixel(depth),
                                                 PixmapBytePad(width, depth),
                                                 pbits))
                return FALSE;
            pScrPriv->layer[i].u.run.pixmap = pPixmap;
            RegionInit(&pScrPriv->layer[i].u.run.region, &box, 0);
        }
        pScreen->devPrivate = pScrPriv->layer[0].u.run.pixmap;
        return TRUE;
    }
    
    void
    fbOverlayPaintKey(DrawablePtr pDrawable,
                      RegionPtr pRegion, CARD32 pixel, int layer)
    {
        fbFillRegionSolid(pDrawable, pRegion, 0,
                          fbReplicatePixel(pixel, pDrawable->bitsPerPixel));
    }
    
    /*
     * Track visible region for each layer
     */
    void
    fbOverlayUpdateLayerRegion(ScreenPtr pScreen, int layer, RegionPtr prgn)
    {
        FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
        int i;
        RegionRec rgnNew;
    
        if (!prgn || !RegionNotEmpty(prgn))
            return;
        for (i = 0; i < pScrPriv->nlayers; i++) {
            if (i == layer) {
                /* add new piece to this fb */
                RegionUnion(&pScrPriv->layer[i].u.run.region,
                            &pScrPriv->layer[i].u.run.region, prgn);
            }
            else if (RegionNotEmpty(&pScrPriv->layer[i].u.run.region)) {
                /* paint new piece with chroma key */
                RegionNull(&rgnNew);
                RegionIntersect(&rgnNew, prgn, &pScrPriv->layer[i].u.run.region);
                (*pScrPriv->PaintKey) (&pScrPriv->layer[i].u.run.pixmap->drawable,
                                       &rgnNew, pScrPriv->layer[i].key, i);
                RegionUninit(&rgnNew);
                /* remove piece from other fbs */
                RegionSubtract(&pScrPriv->layer[i].u.run.region,
                               &pScrPriv->layer[i].u.run.region, prgn);
            }
        }
    }
    
    /*
     * Copy only areas in each layer containing real bits
     */
    void
    fbOverlayCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
    {
        ScreenPtr pScreen = pWin->drawable.pScreen;
        FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
        RegionRec rgnDst;
        int dx, dy;
        int i;
        RegionRec layerRgn[FB_OVERLAY_MAX];
        PixmapPtr pPixmap;
    
        dx = ptOldOrg.x - pWin->drawable.x;
        dy = ptOldOrg.y - pWin->drawable.y;
    
        /*
         * Clip to existing bits
         */
        RegionTranslate(prgnSrc, -dx, -dy);
        RegionNull(&rgnDst);
        RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
        RegionTranslate(&rgnDst, dx, dy);
        /*
         * Compute the portion of each fb affected by this copy
         */
        for (i = 0; i < pScrPriv->nlayers; i++) {
            RegionNull(&layerRgn[i]);
            RegionIntersect(&layerRgn[i], &rgnDst,
                            &pScrPriv->layer[i].u.run.region);
            if (RegionNotEmpty(&layerRgn[i])) {
                RegionTranslate(&layerRgn[i], -dx, -dy);
                pPixmap = pScrPriv->layer[i].u.run.pixmap;
                miCopyRegion(&pPixmap->drawable, &pPixmap->drawable,
                             0,
                             &layerRgn[i], dx, dy, pScrPriv->CopyWindow, 0,
                             (void *) (long) i);
            }
        }
        /*
         * Update regions
         */
        for (i = 0; i < pScrPriv->nlayers; i++) {
            if (RegionNotEmpty(&layerRgn[i]))
                fbOverlayUpdateLayerRegion(pScreen, i, &layerRgn[i]);
    
            RegionUninit(&layerRgn[i]);
        }
        RegionUninit(&rgnDst);
    }
    
    void
    fbOverlayWindowExposures(WindowPtr pWin,
                             RegionPtr prgn, RegionPtr other_exposed)
    {
        fbOverlayUpdateLayerRegion(pWin->drawable.pScreen,
                                   fbOverlayWindowLayer(pWin), prgn);
        miWindowExposures(pWin, prgn, other_exposed);
    }
    
    Bool
    fbOverlaySetupScreen(ScreenPtr pScreen,
                         pointer pbits1,
                         pointer pbits2,
                         int xsize,
                         int ysize,
                         int dpix,
                         int dpiy, int width1, int width2, int bpp1, int bpp2)
    {
        return fbSetupScreen(pScreen,
                             pbits1, xsize, ysize, dpix, dpiy, width1, bpp1);
    }
    
    static Bool
    fb24_32OverlayCreateScreenResources(ScreenPtr pScreen)
    {
        FbOverlayScrPrivPtr pScrPriv = fbOverlayGetScrPriv(pScreen);
        int pitch;
        Bool retval;
        int i;
    
        if ((retval = fbOverlayCreateScreenResources(pScreen))) {
            for (i = 0; i < pScrPriv->nlayers; i++) {
                /* fix the screen pixmap */
                PixmapPtr pPix = (PixmapPtr) pScrPriv->layer[i].u.run.pixmap;
    
                if (pPix->drawable.bitsPerPixel == 32) {
                    pPix->drawable.bitsPerPixel = 24;
                    pitch = BitmapBytePad(pPix->drawable.width * 24);
                    pPix->devKind = pitch;
                }
            }
        }
    
        return retval;
    }
    
    Bool
    fbOverlayFinishScreenInit(ScreenPtr pScreen,
                              pointer pbits1,
                              pointer pbits2,
                              int xsize,
                              int ysize,
                              int dpix,
                              int dpiy,
                              int width1,
                              int width2,
                              int bpp1, int bpp2, int depth1, int depth2)
    {
        VisualPtr visuals;
        DepthPtr depths;
        int nvisuals;
        int ndepths;
        int bpp = 0, imagebpp = 32;
        VisualID defaultVisual;
        FbOverlayScrPrivPtr pScrPriv;
    
        if (!dixRegisterPrivateKey
            (&fbOverlayScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
            return FALSE;
    
        pScrPriv = malloc(sizeof(FbOverlayScrPrivRec));
        if (!pScrPriv)
            return FALSE;
    
        if (bpp1 == 32 || bpp2 == 32)
            bpp = 32;
        else if (bpp1 == 24 || bpp2 == 24)
            bpp = 24;
    
        if (bpp == 24) {
            int f;
    
            imagebpp = 32;
            /*
             * Check to see if we're advertising a 24bpp image format,
             * in which case windows will use it in preference to a 32 bit
             * format.
             */
            for (f = 0; f < screenInfo.numPixmapFormats; f++) {
                if (screenInfo.formats[f].bitsPerPixel == 24) {
                    imagebpp = 24;
                    break;
                }
            }
        }
        if (imagebpp == 32) {
            fbGetScreenPrivate(pScreen)->win32bpp = bpp;
            fbGetScreenPrivate(pScreen)->pix32bpp = bpp;
        }
        else {
            fbGetScreenPrivate(pScreen)->win32bpp = 32;
            fbGetScreenPrivate(pScreen)->pix32bpp = 32;
        }
    
        if (!fbInitVisuals(&visuals, &depths, &nvisuals, &ndepths, &depth1,
                           &defaultVisual, ((unsigned long) 1 << (bpp1 - 1)) |
                           ((unsigned long) 1 << (bpp2 - 1)), 8)) {
            free(pScrPriv);
            return FALSE;
        }
        if (!miScreenInit(pScreen, 0, xsize, ysize, dpix, dpiy, 0,
                          depth1, ndepths, depths,
                          defaultVisual, nvisuals, visuals)) {
            free(pScrPriv);
            return FALSE;
        }
        /* MI thinks there's no frame buffer */
    #ifdef MITSHM
        ShmRegisterFbFuncs(pScreen);
    #endif
        pScreen->minInstalledCmaps = 1;
        pScreen->maxInstalledCmaps = 2;
    
        pScrPriv->nlayers = 2;
        pScrPriv->PaintKey = fbOverlayPaintKey;
        pScrPriv->CopyWindow = fbCopyWindowProc;
        pScrPriv->layer[0].u.init.pbits = pbits1;
        pScrPriv->layer[0].u.init.width = width1;
        pScrPriv->layer[0].u.init.depth = depth1;
    
        pScrPriv->layer[1].u.init.pbits = pbits2;
        pScrPriv->layer[1].u.init.width = width2;
        pScrPriv->layer[1].u.init.depth = depth2;
        dixSetPrivate(&pScreen->devPrivates, fbOverlayScreenPrivateKey, pScrPriv);
    
        /* overwrite miCloseScreen with our own */
        pScreen->CloseScreen = fbOverlayCloseScreen;
        pScreen->CreateScreenResources = fbOverlayCreateScreenResources;
        pScreen->CreateWindow = fbOverlayCreateWindow;
        pScreen->WindowExposures = fbOverlayWindowExposures;
        pScreen->CopyWindow = fbOverlayCopyWindow;
        if (bpp == 24 && imagebpp == 32) {
            pScreen->ModifyPixmapHeader = fb24_32ModifyPixmapHeader;
            pScreen->CreateScreenResources = fb24_32OverlayCreateScreenResources;
        }
    
        return TRUE;
    }