/*
 * Copyright 1997-2003 by Alan Hourihane, North Wales, UK.
 *
 * 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 Alan
 * Hourihane not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission.  Alan Hourihane makes no representations about the
 * suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL ALAN HOURIHANE 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.
 *
 * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
 *
 * Trident 3DImage' accelerated options.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "xf86.h"
#include "xf86_OSproc.h"

#include "xf86Pci.h"

#include "miline.h"

#include "trident.h"
#include "trident_regs.h"

#ifdef HAVE_XAA_H
#include "xaarop.h"
#include "xaalocal.h"


static void ImageSync(ScrnInfoPtr pScrn);
static void ImageSyncClip(ScrnInfoPtr pScrn);
#if 0
static void ImageSetupForSolidLine(ScrnInfoPtr pScrn,
                                    int color,
                                    int rop,
                                    unsigned int planemask);
static void ImageSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
                                                int x, int y,
                                                int dmaj, int dmin,
                                                int e, int len,
                                                int octant);
#endif
static void ImageSetupForFillRectSolid(ScrnInfoPtr pScrn,
                                            int color,
                                            int rop,
                                            unsigned int planemask);
static void ImageSubsequentFillRectSolid(ScrnInfoPtr pScrn,
                                            int x, int y,
                                            int w, int h);
static void ImageSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
                                                int x1, int y1,
                                                int x2, int y2,
                                                int w, int h);
static void ImageSetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
                                            int xdir, int ydir,
                                            int rop,
                                            unsigned int planemask,
                                            int transparency_color);
static void ImageSetClippingRectangle(ScrnInfoPtr pScrn,
                                        int x1, int y1,
                                        int x2, int y2);
static void ImageDisableClipping(ScrnInfoPtr pScrn);
static void ImageSetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
                                            int patternx,
                                            int patterny,
                                            int fg, int bg,
                                            int rop,
                                            unsigned int planemask);
static void ImageSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
                                                    int patternx,
                                                    int patterny,
                                                    int x, int y,
                                                    int w, int h);
#if 0
static void ImageSetupForColor8x8PatternFill(ScrnInfoPtr pScrn,
                                                int patternx,
                                                int patterny,
                                                int rop,
                                                unsigned int planemask,
                                                int trans_col);
static void ImageSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn,
                                                    int patternx,
                                                    int patterny,
                                                    int x, int y,
                                                    int w, int h);
#endif
static void ImageSetupForScanlineImageWrite(ScrnInfoPtr pScrn,
                                            int rop,
                                            unsigned int planemask,
                                            int transparency_color,
                                            int bpp,
                                            int depth);
static void ImageSubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
                                                    int x, int y,
                                                    int w, int h,
                                                    int skipleft);
static void ImageSubsequentImageWriteScanline(ScrnInfoPtr pScrn,
                                                int bufno);
static void ImageSetupForScanlineCPUToScreenColorExpandFill(
                                            ScrnInfoPtr pScrn,
                                            int fg, int bg,
                                            int rop,
                                            unsigned int planemask);
static void ImageSubsequentScanlineCPUToScreenColorExpandFill(
                                                    ScrnInfoPtr pScrn,
                                                    int x, int y,
                                                    int w, int h,
                                                    int skipleft);
static void ImageSubsequentColorExpandScanline(ScrnInfoPtr pScrn,
                                                int bufno);


static void
ImageInitializeAccelerator(ScrnInfoPtr pScrn)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    switch (pScrn->depth) {
    case 8:
        pTrident->EngineOperation = 0;
        break;
    case 15:
        pTrident->EngineOperation = 5;
        break;
    case 16:
        pTrident->EngineOperation = 1;
        break;
    case 24:
        pTrident->EngineOperation = 2;
        break;
    }
    IMAGE_OUT(0x2120, 0xF0000000);
    IMAGE_OUT(0x2120, 0x40000000 | pTrident->EngineOperation);
    IMAGE_OUT(0x2120, 0x80000000);
    IMAGE_OUT(0x2144, 0x00000000);
    IMAGE_OUT(0x2148, 0x00000000);
    IMAGE_OUT(0x2150, 0x00000000);
    IMAGE_OUT(0x2154, 0x00000000);
    IMAGE_OUT(0x2120, 0x60000000 |
                        (pScrn->displayWidth << 16) |
                        pScrn->displayWidth);
    IMAGE_OUT(0x216C, 0x00000000);
    IMAGE_OUT(0x2170, 0x00000000);
    IMAGE_OUT(0x217C, 0x00000000);
    IMAGE_OUT(0x2120, 0x10000000);
    IMAGE_OUT(0x2130, (2047 << 16) | 2047);
    pTrident->Clipping = FALSE;
    pTrident->DstEnable = FALSE;
}
#endif

Bool
ImageAccelInit(ScreenPtr pScreen)
{
#ifdef HAVE_XAA_H
    XAAInfoRecPtr infoPtr;
    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    if (pTrident->NoAccel)
        return FALSE;

    pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec();
    if (!infoPtr) return FALSE;

    pTrident->InitializeAccelerator = ImageInitializeAccelerator;
    ImageInitializeAccelerator(pScrn);

    infoPtr->Flags = PIXMAP_CACHE |
            LINEAR_FRAMEBUFFER |
            OFFSCREEN_PIXMAPS;

    infoPtr->Sync = ImageSync;

#if 0
    infoPtr->SetClippingRectangle = ImageSetClippingRectangle;
    infoPtr->DisableClipping = ImageDisableClipping;
    infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_FILL |
                                HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
                                HARDWARE_CLIP_MONO_8x8_FILL;
#endif

#if 0
    infoPtr->SolidLineFlags = NO_PLANEMASK;
    infoPtr->SetupForSolidLine = ImageSetupForSolidLine;
    infoPtr->SolidBresenhamLineErrorTermBits = 13;
    infoPtr->SubsequentSolidBresenhamLine =
                                    ImageSubsequentSolidBresenhamLine;
    infoPtr->ClippingFlags |= HARDWARE_CLIP_SOLID_LINE;
#endif

    infoPtr->SolidFillFlags = NO_PLANEMASK;
    infoPtr->SetupForSolidFill = ImageSetupForFillRectSolid;
    infoPtr->SubsequentSolidFillRect = ImageSubsequentFillRectSolid;

    infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK |
                                        NO_TRANSPARENCY |
                                        ONLY_TWO_BITBLT_DIRECTIONS;

    infoPtr->SetupForScreenToScreenCopy =
                                    ImageSetupForScreenToScreenCopy;
    infoPtr->SubsequentScreenToScreenCopy =
                                    ImageSubsequentScreenToScreenCopy;

    infoPtr->Mono8x8PatternFillFlags =  NO_PLANEMASK |
                                    BIT_ORDER_IN_BYTE_MSBFIRST |
                                    HARDWARE_PATTERN_SCREEN_ORIGIN |
                                    HARDWARE_PATTERN_PROGRAMMED_BITS;

    infoPtr->SetupForMono8x8PatternFill =
                                    ImageSetupForMono8x8PatternFill;
    infoPtr->SubsequentMono8x8PatternFillRect =
                                ImageSubsequentMono8x8PatternFillRect;

#if 0
    infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK |
                                    NO_TRANSPARENCY |
                                    HARDWARE_PATTERN_SCREEN_ORIGIN |
                                    BIT_ORDER_IN_BYTE_MSBFIRST;

    infoPtr->SetupForColor8x8PatternFill =
                                    ImageSetupForColor8x8PatternFill;
    infoPtr->SubsequentColor8x8PatternFillRect =
                            ImageSubsequentColor8x8PatternFillRect;
    infoPtr->ClippingFlags |= HARDWARE_CLIP_COLOR_8x8_FILL;
#endif

    if (pTrident->Chipset != CYBER9397DVD) {
        /*
         * It seems as though the 9397DVD doesn't like the transfer
         * window.  But then, I've also tried at the two port
         * addresses too, with no luck.  Disable for this chipset for
         * now. I'd guess there's some extra setup needed for this
         * chipset.
         */
        infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
                                            NO_PLANEMASK |
                                            LEFT_EDGE_CLIPPING |
                                            BIT_ORDER_IN_BYTE_MSBFIRST;

        pTrident->XAAScanlineColorExpandBuffers[0] =
                            xnfalloc(((pScrn->virtualX + 63)) * 4 *
                                        (pScrn->bitsPerPixel / 8));

        infoPtr->NumScanlineColorExpandBuffers = 1;
        infoPtr->ScanlineColorExpandBuffers =
                            pTrident->XAAScanlineColorExpandBuffers;

        infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
                    ImageSetupForScanlineCPUToScreenColorExpandFill;
        infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
                    ImageSubsequentScanlineCPUToScreenColorExpandFill;
        infoPtr->SubsequentColorExpandScanline =
                                ImageSubsequentColorExpandScanline;

        infoPtr->ScanlineImageWriteFlags = NO_PLANEMASK |
                                                LEFT_EDGE_CLIPPING;

        infoPtr->SetupForScanlineImageWrite =
                                    ImageSetupForScanlineImageWrite;
        infoPtr->SubsequentScanlineImageWriteRect =
                ImageSubsequentScanlineImageWriteRect;
        infoPtr->SubsequentImageWriteScanline =
                                    ImageSubsequentImageWriteScanline;

        infoPtr->NumScanlineImageWriteBuffers = 1;
        infoPtr->ScanlineImageWriteBuffers =
                                    pTrident->XAAImageScanlineBuffer;

        pTrident->XAAImageScanlineBuffer[0] =
                xnfalloc(pScrn->virtualX * pScrn->bitsPerPixel / 8);

        infoPtr->ImageWriteBase = pTrident->IOBase + 0x10000;
    }

    return(XAAInit(pScreen, infoPtr));
#else
    return FALSE;
#endif
}

#ifdef HAVE_XAA_H
static void
ImageSync(ScrnInfoPtr pScrn)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    int busy;
    int cnt = 5000000;

    if (pTrident->Clipping) ImageDisableClipping(pScrn);
    if (pTrident->DstEnable) {
        IMAGE_OUT(0x2120, 0x70000000);
        pTrident->DstEnable = FALSE;
    }

    IMAGEBUSY(busy);
    while (busy != 0) {
        if (--cnt < 0) {
            ErrorF("GE timeout\n");
            IMAGE_OUT(0x2164, 0x80000000);
        }

        IMAGEBUSY(busy);
    }
}

static void
ImageSyncClip(ScrnInfoPtr pScrn)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    int busy;
    int cnt = 5000000;

    IMAGEBUSY(busy);
    while (busy != 0) {
        if (--cnt < 0) {
            ErrorF("GE timeout\n");
            IMAGE_OUT(0x2164, 0x80000000);
        }

        IMAGEBUSY(busy);
    }
}

static void
ImageSetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
                                int xdir, int ydir,
                                int rop,
                                unsigned int planemask,
                                int transparency_color)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    pTrident->BltScanDirection = 0;
    if ((xdir < 0) || (ydir < 0))
        pTrident->BltScanDirection |= (1 << 2);

    IMAGE_OUT(0x2120, 0x80000000);
    IMAGE_OUT(0x2120, 0x90000000 | XAAGetCopyROP(rop));

    if (transparency_color != -1) {
        IMAGE_OUT(0x2120, 0x70000000 |
                            (1 << 26) |
                            (transparency_color & 0xffffff));
        pTrident->DstEnable = TRUE;
    }
}

static void
ImageSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
                                    int x1, int y1,
                                    int x2, int y2,
                                    int w, int h)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    if (pTrident->BltScanDirection) {
        IMAGE_OUT(0x2100, ((y1 + h - 1) << 16) | (x1 + w - 1));
        IMAGE_OUT(0x2104, (y1 << 16) | x1);
        IMAGE_OUT(0x2108, ((y2 + h - 1) << 16) | (x2 + w - 1));
        IMAGE_OUT(0x210C, y2<<16 | x2);
    } else {
        IMAGE_OUT(0x2100, (y1 << 16) | x1);
        IMAGE_OUT(0x2104, ((y1 + h - 1) << 16) | (x1 + w - 1));
        IMAGE_OUT(0x2108, (y2 << 16) | x2);
        IMAGE_OUT(0x210C, ((y2 + h - 1) << 16) | (x2 + w - 1));
    }

    IMAGE_OUT(0x2124, 0x80000000 |
                        (1 << 7) | (1 << 22) | (1 << 10) |
                        pTrident->BltScanDirection |
                        (pTrident->Clipping ? 1 : 0));

    if (!pTrident->UsePCIRetry)
        ImageSyncClip(pScrn);
}

static void
ImageSetClippingRectangle(ScrnInfoPtr pScrn,
                            int x1, int y1,
                            int x2, int y2)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    IMAGE_OUT(0x2120, 0x10000000 |
                        ((y1 & 0xfff) << 16) | (x1 & 0xfff));
    IMAGE_OUT(0x2130, ((y2 & 0xfff) << 16) | (x2 & 0xfff));
    pTrident->Clipping = TRUE;
}

static void
ImageDisableClipping(ScrnInfoPtr pScrn)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    pTrident->Clipping = FALSE;
}

#if 0
static void
ImageSetupForSolidLine(ScrnInfoPtr pScrn,
                        int color,
                        int rop,
                        unsigned int planemask)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    REPLICATE(color);
    IMAGE_OUT(0x2120, 0x84000000);
    IMAGE_OUT(0x2120, 0x90000000 | XAAGetCopyROP(rop));
    IMAGE_OUT(0x2144, color);
}

static void
ImageSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
                                    int x, int y,
                                    int dmaj, int dmin,
                                    int e, int len, int octant)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    int tmp;
    int D = 0, E = 0, ymajor = 0;

    IMAGE_OUT(0x2124, 0x20000000 |
                        (3 << 22) | (1 << 10) | (1 << 9) |
                        (pTrident->Clipping ? 1 : 0));
    if (!(octant & YMAJOR)) {
        if ((!(octant & XDECREASING)) && (!(octant & YDECREASING))) {
            E = 1;
            D = 0;
        }

        if ((!(octant & XDECREASING)) && ( (octant & YDECREASING))) {
            E = 1;
            D = 1;
        }

        if (( (octant & XDECREASING)) && (!(octant & YDECREASING))) {
            E = 1;
            D = 2;
        }
        if (( (octant & XDECREASING)) && ( (octant & YDECREASING))) {
            E = 1;
            D = 3;
        }

        ymajor = 0;
    } else {
        if ((!(octant & XDECREASING)) && (!(octant & YDECREASING))) {
            E = 0;
            D = 0;
        }

        if ((!(octant & XDECREASING)) && ( (octant & YDECREASING))) {
            E = 0;
            D = 2;
        }

        if (( (octant & XDECREASING)) && (!(octant & YDECREASING))) {
            E = 0;
            D = 1;
        }

        if (( (octant & XDECREASING)) && ( (octant & YDECREASING))) {
            E = 0;
            D = 3;
        }

        ymajor = (1 << 18);
    }

    if (E) {
        tmp = x;
        x = y;
        y = tmp;
    }
    if (D & 0x02) {
        IMAGE_OUT(0x21FC, 0x20000000 |
                            (1 << 27) | (1 << 19) | (1 << 17) |
                            ymajor | (x + len - 1));
    } else {
        IMAGE_OUT(0x21FC, 0x20000000 |
                            (1 << 27) | (1 << 19) | (1 << 17) |
                            ymajor | ( y + len - 1));
    }
    IMAGE_OUT(0x2100, (E << 30) | ((y & 0xfff) << 16) | (x & 0xfff));
    IMAGE_OUT(0x2104, (D << 30) |
                        (((dmaj - dmin) & 0xfff) << 16) |
                        (-dmin & 0xfff));
    IMAGE_OUT(0x2108, ((-e & 0xfff) << 16));

    if (!pTrident->UsePCIRetry)
        ImageSyncClip(pScrn);
}
#endif

static void
ImageSetupForFillRectSolid(ScrnInfoPtr pScrn,
                            int color,
                            int rop,
                            unsigned int planemask)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    REPLICATE(color);
    IMAGE_OUT(0x2120, 0x80000000);
    IMAGE_OUT(0x2120, 0x90000000 | XAAGetCopyROP(rop));
    IMAGE_OUT(0x2144, color);
}

static void
ImageSubsequentFillRectSolid(ScrnInfoPtr pScrn,
                                int x, int y,
                                int w, int h)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    if ((w <= 0) || (h <= 0))
        return;

    IMAGE_OUT(0x2108, ((y & 0xfff) << 16) | (x & 0xfff));
    IMAGE_OUT(0x210C, (((y + h - 1) & 0xfff) << 16) |
                        ((x + w - 1) & 0xfff));
    IMAGE_OUT(0x2124, 0x80000000 |
                        (3 << 22) | (1 << 10) | (1 << 9) |
                        (pTrident->Clipping ? 1 : 0));
    if (!pTrident->UsePCIRetry)
        ImageSyncClip(pScrn);
}

static void
MoveDWORDS(register CARD32* dest,
            register CARD32* src,
            register int dwords )
{
    Bool extra = FALSE;

    if (dwords & 0x01) extra = TRUE;

    while(dwords & ~0x03) {
        *dest = *src;
        *(dest + 1) = *(src + 1);
        *(dest + 2) = *(src + 2);
        *(dest + 3) = *(src + 3);
        src += 4;
        dest += 4;
        dwords -= 4;
    }

    if(!dwords) {
        if (extra) *dest = 0x00000000;
        return;
    }

    *dest = *src;
    if(dwords == 1) {
        if (extra) *(dest + 1) = 0x00000000;
        return;
    }

    *(dest + 1) = *(src + 1);
    if(dwords == 2) {
        if (extra) *(dest + 2) = 0x00000000;
        return;
    }

    *(dest + 2) = *(src + 2);
    if (extra) *(dest + 3) = 0x00000000;
}

static void
ImageSetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
                                int patternx, int patterny,
                                int fg, int bg,
                                int rop,
                                unsigned int planemask)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    IMAGE_OUT(0x2120, 0x90000000 | XAAGetPatternROP(rop));
    if (bg == -1) {
        REPLICATE(fg);
        IMAGE_OUT(0x2120, 0x80000000 | (1 << 27));
        IMAGE_OUT(0x2130, patternx);
        IMAGE_OUT(0x2134, patterny);
        IMAGE_OUT(0x2150, fg);
        IMAGE_OUT(0x2154, ~fg);
    } else {
        REPLICATE(bg);
        REPLICATE(fg);
        IMAGE_OUT(0x2120, 0x80000000 | (1 << 27) | (1 << 26));
        IMAGE_OUT(0x2130, patternx);
        IMAGE_OUT(0x2134, patterny);
        IMAGE_OUT(0x2150, fg);
        IMAGE_OUT(0x2154, bg);
    }
}

static void
ImageSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
                                        int patternx, int patterny,
                                        int x, int y,
                                        int w, int h)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    IMAGE_OUT(0x2108, ((y & 0xfff) << 16) | (x & 0xfff));
    IMAGE_OUT(0x210C, (((y + h - 1) & 0xfff) << 16) |
                        ((x + w - 1) & 0xfff));
    IMAGE_OUT(0x2124, 0x80000000 |
                        (7 << 18) | (1 << 22) | (1 << 10) | (1 << 9) |
                        (pTrident->Clipping ? 1 : 0));
    if (!pTrident->UsePCIRetry)
        ImageSyncClip(pScrn);
}

#if 0
static void
ImageSetupForColor8x8PatternFill(ScrnInfoPtr pScrn,
                                    int patternx, int patterny,
                                    int rop,
                                    unsigned int planemask,
                                    int transparency_color)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    IMAGE_OUT(0x2120, 0x90000000 | XAAGetPatternROP(rop));
    IMAGE_OUT(0x2120, 0x80000000 | (1 << 26));
    if (transparency_color != -1) {
        IMAGE_OUT(0x2120, 0x70000000 |
                            (1 << 26) |
                            (transparency_color & 0xffffff));
        pTrident->DstEnable = TRUE;
    }
}

static void
ImageSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn,
                                        int patternx, int patterny,
                                        int x, int y,
                                        int w, int h)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    IMAGE_OUT(0x2100, ((patterny & 0xfff) << 16) |
                        (patternx & 0xfff));
    IMAGE_OUT(0x2104, (((patterny + h - 1) & 0xfff) << 16) |
                        ((patternx + w - 1) & 0xfff));
    IMAGE_OUT(0x2108, ((y & 0xfff) << 16) | (x & 0xfff));
    IMAGE_OUT(0x210C, (((y + h - 1) & 0xfff) << 16) |
                        ((x + w - 1) & 0xfff));
    IMAGE_OUT(0x2124, 0x80000000 |
                        (1 << 22) | (1 << 10) | (1 << 7) |
                        (pTrident->Clipping ? 1 : 0));
    if (!pTrident->UsePCIRetry)
        ImageSyncClip(pScrn);
}
#endif

static void
ImageSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
                                                int fg, int bg,
                                                int rop,
                                                unsigned int planemask
){
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);

    IMAGE_OUT(0x2120, 0x80000000);
    IMAGE_OUT(0x2120, 0x90000000 | XAAGetCopyROP(rop));
    if (bg == -1) {
        pTrident->ROP = (2 << 22);
        REPLICATE(fg);
        IMAGE_OUT(0x2144, fg);
        IMAGE_OUT(0x2148, ~fg);
    } else {
        pTrident->ROP = (3 << 22);
        REPLICATE(fg);
        IMAGE_OUT(0x2144, fg);
        REPLICATE(bg);
        IMAGE_OUT(0x2148, bg);
    }
}

static void
ImageSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
                                                    int x, int y,
                                                    int w, int h,
                                                    int skipleft
){
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    ImageSetClippingRectangle(pScrn,(x + skipleft), y,
                                (x + w - 1), (y + h - 1));
    IMAGE_OUT(0x2108, ((y & 0xfff) << 16) | (x & 0xfff));
    IMAGE_OUT(0x210C, (((y + h - 1) & 0xfff) << 16) |
                        ((x + w - 1) & 0xfff));
    IMAGE_OUT(0x2124, 0x80000000 | (pTrident->ROP) | (1 << 10) | 1);
    pTrident->dwords = (w + 31) >> 5;
    pTrident->h = h;
}

static void
ImageSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    XAAInfoRecPtr infoRec;
    infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);

    MoveDWORDS((CARD32*)infoRec->ImageWriteBase,
            (CARD32*)pTrident->XAAScanlineColorExpandBuffers[bufno],
            pTrident->dwords);

    pTrident->h--;
    if (!pTrident->h)
        ImageSync(pScrn);
}

static void
ImageSetupForScanlineImageWrite(ScrnInfoPtr pScrn,
                                int rop,
                                unsigned int planemask,
                                int transparency_color,
                                int bpp, int depth)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    IMAGE_OUT(0x2120, 0x90000000 | XAAGetCopyROP(rop));
    if (transparency_color != -1) {
        IMAGE_OUT(0x2120, 0x70000000 |
                            (1 << 26) |
                            (transparency_color & 0xffffff));
        pTrident->DstEnable = TRUE;
    }

    IMAGE_OUT(0x2120, 0x80000000);
}

static void
ImageSubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
                                        int x, int y,
                                        int w, int h,
                                        int skipleft)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    ImageSetClippingRectangle(pScrn,
                                (x + skipleft), y,
                                (x + w - 1), (y + h - 1));
    IMAGE_OUT(0x2108, ((y & 0xfff) << 16) | (x & 0xfff));
    IMAGE_OUT(0x210C, (((y + h - 1) & 0xfff) << 16) |
                        ((x + w - 1) & 0xfff));
    IMAGE_OUT(0x2124, 0x80000000 |
                        (1 << 22) | (1 << 10) | 1);
    pTrident->dwords = ((w * (pScrn->bitsPerPixel / 8)) + 3) >> 2;
    pTrident->h = h;
}


static void
ImageSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
{
    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
    XAAInfoRecPtr infoRec;
    infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);

    MoveDWORDS((CARD32*)infoRec->ImageWriteBase,
                (CARD32*)pTrident->XAAImageScanlineBuffer[bufno],
                pTrident->dwords);

    pTrident->h--;
    if (!pTrident->h)
        ImageSync(pScrn);
}
#endif