Edit

IABSD.fr/xenocara/driver/xf86-video-nv/src/g80_exa.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2012-08-16 16:35:27
    Hash : 59c344e6
    Message : Update to xf86-video-nv 2.1.20

  • driver/xf86-video-nv/src/g80_exa.c
  • /*
     * Copyright (c) 2007 NVIDIA, Corporation
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     */
    
    
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    
    #include "g80_type.h"
    #include "g80_dma.h"
    #include "g80_xaa.h"
    
    static void
    waitMarker(ScreenPtr pScreen, int marker)
    {
        G80Sync(xf86ScreenToScrn(pScreen));
    }
    
    static Bool
    setSrc(G80Ptr pNv, PixmapPtr pSrc)
    {
        CARD32 depth;
    
        switch(pSrc->drawable.depth) {
            case  8: depth = 0x000000f3; break;
            case 15: depth = 0x000000f8; break;
            case 16: depth = 0x000000e8; break;
            case 24: depth = 0x000000e6; break;
            case 32: depth = 0x000000cf; break;
            default: return FALSE;
        }
    
        G80DmaStart(pNv, 0x230, 2);
        G80DmaNext (pNv, depth);
        G80DmaNext (pNv, 0x00000001);
        G80DmaStart(pNv, 0x244, 5);
        G80DmaNext (pNv, exaGetPixmapPitch(pSrc));
        G80DmaNext (pNv, pSrc->drawable.width);
        G80DmaNext (pNv, pSrc->drawable.height);
        G80DmaNext (pNv, 0x00000000);
        G80DmaNext (pNv, exaGetPixmapOffset(pSrc));
    
        return TRUE;
    }
    
    static Bool
    setDst(G80Ptr pNv, PixmapPtr pDst)
    {
        CARD32 depth, depth2;
    
        switch(pDst->drawable.depth) {
            case  8: depth = 0x000000f3; depth2 = 3; break;
            case 15: depth = 0x000000f8; depth2 = 1; break;
            case 16: depth = 0x000000e8; depth2 = 0; break;
            case 24: depth = 0x000000e6; depth2 = 2; break;
            case 32: depth = 0x000000cf; depth2 = 2; break;
            default: return FALSE;
        }
    
        G80DmaStart(pNv, 0x200, 2);
        G80DmaNext (pNv, depth);
        G80DmaNext (pNv, 0x00000001);
        G80DmaStart(pNv, 0x214, 5);
        G80DmaNext (pNv, exaGetPixmapPitch(pDst));
        G80DmaNext (pNv, pDst->drawable.width);
        G80DmaNext (pNv, pDst->drawable.height);
        G80DmaNext (pNv, 0x00000000);
        G80DmaNext (pNv, exaGetPixmapOffset(pDst));
        G80DmaStart(pNv, 0x2e8, 1);
        G80DmaNext (pNv, depth2);
        G80DmaStart(pNv, 0x584, 1);
        G80DmaNext (pNv, depth);
        G80SetClip(pNv, 0, 0, pDst->drawable.width, pDst->drawable.height);
    
        return TRUE;
    }
    
    /* solid fills */
    
    static Bool
    prepareSolid(PixmapPtr      pPixmap,
                 int            alu,
                 Pixel          planemask,
                 Pixel          fg)
    {
        ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
        G80Ptr pNv = G80PTR(pScrn);
    
        if(pPixmap->drawable.depth > 24) return FALSE;
        if(!setDst(pNv, pPixmap)) return FALSE;
        G80DmaStart(pNv, 0x2ac, 1);
        G80DmaNext (pNv, 4);
        G80SetRopSolid(pNv, alu, planemask);
        G80DmaStart(pNv, 0x580, 1);
        G80DmaNext (pNv, 4);
        G80DmaStart(pNv, 0x588, 1);
        G80DmaNext (pNv, fg);
    
        pNv->DMAKickoffCallback = G80DMAKickoffCallback;
        return TRUE;
    }
    
    static void
    solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
    {
        ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
        G80Ptr pNv = G80PTR(pScrn);
    
        G80DmaStart(pNv, 0x600, 4);
        G80DmaNext (pNv, x1);
        G80DmaNext (pNv, y1);
        G80DmaNext (pNv, x2);
        G80DmaNext (pNv, y2);
    
        if((x2 - x1) * (y2 - y1) >= 512)
            G80DmaKickoff(pNv);
    }
    
    static void
    doneSolid(PixmapPtr pPixmap)
    {
    }
    
    /* screen to screen copies */
    
    static Bool
    prepareCopy(PixmapPtr       pSrcPixmap,
                PixmapPtr       pDstPixmap,
                int             dx,
                int             dy,
                int             alu,
                Pixel           planemask)
    {
        ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
        G80Ptr pNv = G80PTR(pScrn);
    
        if(!setSrc(pNv, pSrcPixmap)) return FALSE;
        if(!setDst(pNv, pDstPixmap)) return FALSE;
        G80DmaStart(pNv, 0x2ac, 1);
        if(alu == GXcopy && planemask == ~0) {
            G80DmaNext (pNv, 3);
        } else {
            G80DmaNext (pNv, 4);
            G80SetRopSolid(pNv, alu, planemask);
        }
        pNv->DMAKickoffCallback = G80DMAKickoffCallback;
        return TRUE;
    }
    
    static void
    copy(PixmapPtr pDstPixmap,
         int       srcX,
         int       srcY,
         int       dstX,
         int       dstY,
         int       width,
         int       height)
    {
        ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
        G80Ptr pNv = G80PTR(pScrn);
    
        G80DmaStart(pNv, 0x110, 1);
        G80DmaNext (pNv, 0);
        G80DmaStart(pNv, 0x8b0, 12);
        G80DmaNext (pNv, dstX);
        G80DmaNext (pNv, dstY);
        G80DmaNext (pNv, width);
        G80DmaNext (pNv, height);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, 1);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, 1);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, srcX);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, srcY);
    
        if(width * height >= 512)
            G80DmaKickoff(pNv);
    }
    
    static void
    doneCopy(PixmapPtr pDstPixmap)
    {
    }
    
    /* composite */
    
    static Bool
    checkComposite(int          op,
                   PicturePtr   pSrc,
                   PicturePtr   pMask,
                   PicturePtr   pDst)
    {
        return FALSE;
    }
    
    /* upload to screen */
    
    static Bool
    upload(PixmapPtr pDst,
           int       x,
           int       y,
           int       w,
           int       h,
           char      *src,
           int       src_pitch)
    {
        ScrnInfoPtr pScrn = xf86ScreenToScrn(pDst->drawable.pScreen);
        G80Ptr pNv = G80PTR(pScrn);
        const int Bpp = pDst->drawable.bitsPerPixel >> 3;
        int line_dwords = (w * Bpp + 3) / 4;
        const Bool kickoff = w * h >= 512;
        CARD32 depth;
    
        if(!setDst(pNv, pDst)) return FALSE;
        switch(pDst->drawable.depth) {
            case  8: depth = 0x000000f3; break;
            case 15: depth = 0x000000f8; break;
            case 16: depth = 0x000000e8; break;
            case 24: depth = 0x000000e6; break;
            case 32: depth = 0x000000cf; break;
            default: return FALSE;
        }
    
        G80SetClip(pNv, x, y, w, h);
        G80DmaStart(pNv, 0x2ac, 1);
        G80DmaNext (pNv, 3);
        G80DmaStart(pNv, 0x800, 2);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, depth);
        G80DmaStart(pNv, 0x838, 10);
        G80DmaNext (pNv, (line_dwords * 4) / Bpp);
        G80DmaNext (pNv, h);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, 1);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, 1);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, x);
        G80DmaNext (pNv, 0);
        G80DmaNext (pNv, y);
    
        while(h-- > 0) {
            int count = line_dwords;
            char *p = src;
    
            while(count) {
                int size = count > 1792 ? 1792 : count;
    
                G80DmaStart(pNv, 0x40000860, size);
                memcpy(&pNv->dmaBase[pNv->dmaCurrent], p, size * 4);
    
                p += size * Bpp;
                pNv->dmaCurrent += size;
    
                count -= size;
            }
    
            src += src_pitch;
        }
    
        if(kickoff)
            G80DmaKickoff(pNv);
        else
            pNv->DMAKickoffCallback = G80DMAKickoffCallback;
    
        return TRUE;
    }
    
    /******************************************************************************/
    
    Bool G80ExaInit(ScreenPtr pScreen, ScrnInfoPtr pScrn)
    {
        G80Ptr pNv = G80PTR(pScrn);
        ExaDriverPtr exa;
        const int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
    
        exa = pNv->exa = exaDriverAlloc();
        if(!exa) return FALSE;
    
        exa->exa_major         = EXA_VERSION_MAJOR;
        exa->exa_minor         = EXA_VERSION_MINOR;
        exa->memoryBase        = pNv->mem;
        exa->offScreenBase     = 0;
        exa->memorySize        = pitch * pNv->offscreenHeight;
        exa->pixmapOffsetAlign = 256;
        exa->pixmapPitchAlign  = 256;
        exa->flags             = EXA_OFFSCREEN_PIXMAPS;
        exa->maxX              = 8192;
        exa->maxY              = 8192;
    
        /**** Rendering ops ****/
        exa->PrepareSolid     = prepareSolid;
        exa->Solid            = solid;
        exa->DoneSolid        = doneSolid;
        exa->PrepareCopy      = prepareCopy;
        exa->Copy             = copy;
        exa->DoneCopy         = doneCopy;
        exa->CheckComposite   = checkComposite;
        //exa->PrepareComposite = prepareComposite;
        //exa->Composite        = composite;
        //exa->DoneComposite    = doneComposite;
        exa->UploadToScreen   = upload;
    
        exa->WaitMarker       = waitMarker;
    
        return exaDriverInit(pScreen, exa);
    }