tga_accel.c revision 7706df26
17706df26Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tga/tga_accel.c,v 1.15 2001/11/21 22:32:59 alanh Exp $ */
27706df26Smrg
37706df26Smrg/*
47706df26Smrg * Copyright 1996,1997 by Alan Hourihane, Wigan, England.
57706df26Smrg *
67706df26Smrg * Permission to use, copy, modify, distribute, and sell this software and its
77706df26Smrg * documentation for any purpose is hereby granted without fee, provided that
87706df26Smrg * the above copyright notice appear in all copies and that both that
97706df26Smrg * copyright notice and this permission notice appear in supporting
107706df26Smrg * documentation, and that the name of Alan Hourihane not be used in
117706df26Smrg * advertising or publicity pertaining to distribution of the software without
127706df26Smrg * specific, written prior permission.  Alan Hourihane makes no representations
137706df26Smrg * about the suitability of this software for any purpose.  It is provided
147706df26Smrg * "as is" without express or implied warranty.
157706df26Smrg *
167706df26Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
177706df26Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
187706df26Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
197706df26Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
207706df26Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
217706df26Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
227706df26Smrg * PERFORMANCE OF THIS SOFTWARE.
237706df26Smrg *
247706df26Smrg * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
257706df26Smrg *
267706df26Smrg * DEC TGA accelerated options.
277706df26Smrg */
287706df26Smrg
297706df26Smrg#ifdef HAVE_CONFIG_H
307706df26Smrg#include "config.h"
317706df26Smrg#endif
327706df26Smrg
337706df26Smrg#include "fb.h"
347706df26Smrg#include "micmap.h"
357706df26Smrg#include "xf86.h"
367706df26Smrg#include "xf86_OSproc.h"
377706df26Smrg#include "xf86PciInfo.h"
387706df26Smrg#include "xf86Pci.h"
397706df26Smrg#include "xf86cmap.h"
407706df26Smrg#include "mipointer.h"
417706df26Smrg
427706df26Smrg#include "mibstore.h"
437706df26Smrg#include "miline.h"
447706df26Smrg
457706df26Smrg#include "tga_regs.h"
467706df26Smrg#include "BT.h"
477706df26Smrg#include "tga.h"
487706df26Smrg
497706df26Smrg/* defines */
507706df26Smrg
517706df26Smrg#define BLIT_FORWARDS 0
527706df26Smrg#define BLIT_BACKWARDS 1
537706df26Smrg#define USE_BLOCK_FILL 2
547706df26Smrg#define USE_OPAQUE_FILL 3
557706df26Smrg#define MIX_SRC 0x03
567706df26Smrg
577706df26Smrg#define CE_BUFSIZE 256
587706df26Smrg
597706df26Smrg#define FB_OFFSET(x, y) (((long)(y) * pScrn->displayWidth * (pTga->Bpp)) + (long)(x) * pTga->Bpp)
607706df26Smrg
617706df26Smrg/* prototypes */
627706df26Smrg
637706df26Smrgstatic void TGACopyLineForwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
647706df26Smrg			 int y2, int w);
657706df26Smrgstatic void TGACopyLineBackwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
667706df26Smrg			  int y2, int w);
677706df26Smrgextern void TGASync(ScrnInfoPtr pScrn);
687706df26Smrgstatic void TGASetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
697706df26Smrg			  unsigned int planemask);
707706df26Smrgstatic void TGASubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h);
717706df26Smrgstatic void TGASetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
727706df26Smrg				   int rop, unsigned int planemask,
737706df26Smrg				   int transparency_color);
747706df26Smrgstatic void TGASubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
757706df26Smrg				     int x2, int y2, int w, int h);
767706df26Smrgstatic void TGASetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
777706df26Smrg				   int fg, int bg, int rop,
787706df26Smrg				   unsigned int planemask);
797706df26Smrgstatic void TGASubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx,
807706df26Smrg					 int paty, int x, int y, int w,
817706df26Smrg					 int h);
827706df26Smrgstatic void TGASetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
837706df26Smrg							  int fg, int bg,
847706df26Smrg							  int rop,
857706df26Smrg							  unsigned int planemask);
867706df26Smrg
877706df26Smrgstatic void
887706df26SmrgTGASubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
897706df26Smrg						int x, int y, int w,
907706df26Smrg						int h, int skipleft);
917706df26Smrgstatic void
927706df26SmrgTGASubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
937706df26Smrg
947706df26Smrg
957706df26Smrg/*
967706df26Smrg * The following function sets up the supported acceleration. Call it
977706df26Smrg * from the FbInit() function in the SVGA driver.
987706df26Smrg */
997706df26SmrgBool
1007706df26SmrgDEC21030AccelInit(ScreenPtr pScreen)
1017706df26Smrg{
1027706df26Smrg  XAAInfoRecPtr TGA_AccelInfoRec;
1037706df26Smrg  BoxRec AvailFBArea;
1047706df26Smrg  ScrnInfoPtr pScrn;
1057706df26Smrg  TGAPtr pTga;
1067706df26Smrg
1077706df26Smrg  pScrn = xf86Screens[pScreen->myNum];
1087706df26Smrg  pTga = TGAPTR(pScrn);
1097706df26Smrg
1107706df26Smrg  /*  ErrorF("DEC21030AccelInit called!"); */
1117706df26Smrg
1127706df26Smrg  /* first, create the XAAInfoRec */
1137706df26Smrg  TGA_AccelInfoRec = XAACreateInfoRec();
1147706df26Smrg
1157706df26Smrg  /*  ErrorF("XAACreateInfoRec called"); */
1167706df26Smrg
1177706df26Smrg  if(pScrn->depth == 8) {
1187706df26Smrg    pTga->depthflag = BPP8PACKED;
1197706df26Smrg    pTga->Bpp = 1;
1207706df26Smrg  } else {
1217706df26Smrg    pTga->depthflag = BPP24;
1227706df26Smrg    pTga->Bpp = 4;
1237706df26Smrg  }
1247706df26Smrg
1257706df26Smrg  TGA_AccelInfoRec->Flags =  PIXMAP_CACHE | LINEAR_FRAMEBUFFER |
1267706df26Smrg    OFFSCREEN_PIXMAPS;
1277706df26Smrg
1287706df26Smrg  TGA_AccelInfoRec->Sync = TGASync;
1297706df26Smrg
1307706df26Smrg  /* solid fill */
1317706df26Smrg
1327706df26Smrg  TGA_AccelInfoRec->SolidFillFlags = 0;
1337706df26Smrg  TGA_AccelInfoRec->SetupForSolidFill = TGASetupForSolidFill;
1347706df26Smrg  TGA_AccelInfoRec->SubsequentSolidFillRect = TGASubsequentSolidFillRect;
1357706df26Smrg
1367706df26Smrg  /* screen to screen copy */
1377706df26Smrg  TGA_AccelInfoRec->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
1387706df26Smrg  TGA_AccelInfoRec->SetupForScreenToScreenCopy =
1397706df26Smrg    TGASetupForScreenToScreenCopy;
1407706df26Smrg  TGA_AccelInfoRec->SubsequentScreenToScreenCopy =
1417706df26Smrg    TGASubsequentScreenToScreenCopy;
1427706df26Smrg
1437706df26Smrg  /* mono 8x8 pattern fill */
1447706df26Smrg
1457706df26Smrg  TGA_AccelInfoRec->Mono8x8PatternFillFlags =
1467706df26Smrg    HARDWARE_PATTERN_PROGRAMMED_BITS | BIT_ORDER_IN_BYTE_LSBFIRST;
1477706df26Smrg  TGA_AccelInfoRec->SetupForMono8x8PatternFill =
1487706df26Smrg    TGASetupForMono8x8PatternFill;
1497706df26Smrg  TGA_AccelInfoRec->SubsequentMono8x8PatternFillRect =
1507706df26Smrg    TGASubsequentMono8x8PatternFillRect;
1517706df26Smrg
1527706df26Smrg  /* color expand */
1537706df26Smrg  /* does not work for 32bpp (yet) */
1547706df26Smrg  TGA_AccelInfoRec->ScanlineCPUToScreenColorExpandFillFlags =
1557706df26Smrg    BIT_ORDER_IN_BYTE_LSBFIRST;
1567706df26Smrg
1577706df26Smrg  TGA_AccelInfoRec->NumScanlineColorExpandBuffers = 1;
1587706df26Smrg  pTga->buffers[0] = (CARD32 *)xnfalloc(CE_BUFSIZE);
1597706df26Smrg  TGA_AccelInfoRec->ScanlineColorExpandBuffers =
1607706df26Smrg    (unsigned char **)pTga->buffers;
1617706df26Smrg  TGA_AccelInfoRec->SetupForScanlineCPUToScreenColorExpandFill =
1627706df26Smrg    TGASetupForScanlineCPUToScreenColorExpandFill;
1637706df26Smrg  TGA_AccelInfoRec->SubsequentScanlineCPUToScreenColorExpandFill =
1647706df26Smrg    TGASubsequentScanlineCPUToScreenColorExpandFill;
1657706df26Smrg  TGA_AccelInfoRec->SubsequentColorExpandScanline =
1667706df26Smrg    TGASubsequentColorExpandScanline;
1677706df26Smrg
1687706df26Smrg  /* lines */
1697706df26Smrg
1707706df26Smrg  TGA_AccelInfoRec->PolylinesThinSolid = TGAPolyLines;
1717706df26Smrg  if(pTga->NoXaaPolySegment == FALSE)
1727706df26Smrg    TGA_AccelInfoRec->PolySegmentThinSolid = TGAPolySegment;
1737706df26Smrg  TGA_AccelInfoRec->PolylinesThinSolidFlags = 0x0;
1747706df26Smrg  TGA_AccelInfoRec->PolySegmentThinSolidFlags = 0x0;
1757706df26Smrg
1767706df26Smrg  TGA_AccelInfoRec->PolylinesThinDashed = TGAPolyLinesDashed;
1777706df26Smrg  if(pTga->NoXaaPolySegment == FALSE)
1787706df26Smrg    TGA_AccelInfoRec->PolySegmentThinDashed = TGAPolySegmentDashed;
1797706df26Smrg  TGA_AccelInfoRec->PolylinesThinDashedFlags = 0x0;
1807706df26Smrg  TGA_AccelInfoRec->PolySegmentThinDashedFlags = 0x0;
1817706df26Smrg  TGA_AccelInfoRec->DashedLineFlags = LINE_PATTERN_LSBFIRST_LSBJUSTIFIED;
1827706df26Smrg  TGA_AccelInfoRec->DashPatternMaxLength = 16;
1837706df26Smrg
1847706df26Smrg  /* initialize the pixmap cache */
1857706df26Smrg
1867706df26Smrg  AvailFBArea.x1 = 0;
1877706df26Smrg  AvailFBArea.y1 = 0; /* these gotta be 0 */
1887706df26Smrg  AvailFBArea.x2 = pScrn->displayWidth;
1897706df26Smrg  AvailFBArea.y2 = (pScrn->videoRam * 1024) / (pScrn->displayWidth *
1907706df26Smrg					       pTga->Bpp);
1917706df26Smrg  xf86InitFBManager(pScreen, &AvailFBArea);
1927706df26Smrg
1937706df26Smrg  TGA_AccelInfoRec->PixmapCacheFlags = 0;
1947706df26Smrg
1957706df26Smrg  /* initialize XAA */
1967706df26Smrg  return(XAAInit(pScreen, TGA_AccelInfoRec));
1977706df26Smrg}
1987706df26Smrg
1997706df26Smrgstatic void
2007706df26SmrgTGASetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
2017706df26Smrg					      int fg, int bg, int rop,
2027706df26Smrg					      unsigned int planemask)
2037706df26Smrg{
2047706df26Smrg#ifdef PROFILE
2057706df26Smrg    unsigned int start, stop;
2067706df26Smrg#endif
2077706df26Smrg    TGAPtr pTga = NULL;
2087706df26Smrg    unsigned int fgcolor = 0, bgcolor = 0, pmask = 0;
2097706df26Smrg    TGA_DECL();
2107706df26Smrg
2117706df26Smrg    pTga = TGAPTR(pScrn);
2127706df26Smrg    TGA_GET_IOBASE();
2137706df26Smrg    TGA_GET_OFFSET();
2147706df26Smrg
2157706df26Smrg/*      ErrorF("TGASetupForScanlineCPUToScreenColorExpandFill called\n"); */
2167706df26Smrg    if(pTga->depthflag == BPP8PACKED) {
2177706df26Smrg      fgcolor = (fg | (fg << 8) | (fg << 16) | (fg << 24));
2187706df26Smrg      bgcolor = bg | (bg << 8) | (bg << 16) | (bg << 24);
2197706df26Smrg      pmask = planemask | (planemask << 8) | (planemask << 16)
2207706df26Smrg	| (planemask << 24);
2217706df26Smrg    }
2227706df26Smrg    else {
2237706df26Smrg      bgcolor = bg;
2247706df26Smrg      fgcolor = fg;
2257706df26Smrg      pmask = planemask;
2267706df26Smrg    }
2277706df26Smrg    pTga->current_rop = rop | pTga->depthflag;
2287706df26Smrg
2297706df26Smrg    if(bg == -1) {
2307706df26Smrg	pTga->transparent_pattern_p = 1;
2317706df26Smrg	if(rop == MIX_SRC) {
2327706df26Smrg	  pTga->block_or_opaque_p = USE_BLOCK_FILL;
2337706df26Smrg	  TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
2347706df26Smrg	  TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
2357706df26Smrg	  if(pTga->depthflag == BPP24) {
2367706df26Smrg	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
2377706df26Smrg	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
2387706df26Smrg	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
2397706df26Smrg	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
2407706df26Smrg	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
2417706df26Smrg	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
2427706df26Smrg	  }
2437706df26Smrg	}
2447706df26Smrg	else {
2457706df26Smrg	  pTga->block_or_opaque_p = USE_OPAQUE_FILL;
2467706df26Smrg	  TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
2477706df26Smrg	}
2487706df26Smrg    }
2497706df26Smrg    else {
2507706df26Smrg	pTga->transparent_pattern_p = 0;
2517706df26Smrg	TGA_FAST_WRITE_REG(bgcolor, TGA_BACKGROUND_REG);
2527706df26Smrg	TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
2537706df26Smrg    }
2547706df26Smrg    TGA_FAST_WRITE_REG(pmask, TGA_PLANEMASK_REG); /* we know when to
2557706df26Smrg						     reset this */
2567706df26Smrg    TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
2577706df26Smrg
2587706df26Smrg    TGA_SAVE_OFFSET();
2597706df26Smrg
2607706df26Smrg    return;
2617706df26Smrg}
2627706df26Smrg
2637706df26Smrgstatic void
2647706df26SmrgTGASubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
2657706df26Smrg						int x, int y, int w,
2667706df26Smrg						int h, int skipleft)
2677706df26Smrg{
2687706df26Smrg#ifdef PROFILE
2697706df26Smrg    unsigned int start, stop;
2707706df26Smrg#endif
2717706df26Smrg    TGAPtr pTga;
2727706df26Smrg    TGA_DECL();
2737706df26Smrg
2747706df26Smrg    pTga = TGAPTR(pScrn);
2757706df26Smrg    TGA_GET_IOBASE();
2767706df26Smrg    TGA_GET_OFFSET();
2777706df26Smrg
2787706df26Smrg/*      ErrorF("TGASubsequentScanlineCPUToScreenColorExpandFill called\n"); */
2797706df26Smrg/*      ErrorF("w = %d, h = %d\n", w, h); */
2807706df26Smrg
2817706df26Smrg    pTga->ce_height = h;
2827706df26Smrg    pTga->ce_width = w;
2837706df26Smrg    pTga->ce_x = x;
2847706df26Smrg    pTga->ce_y = y;
2857706df26Smrg    pTga->ce_skipleft = skipleft;
2867706df26Smrg/*      ErrorF("skipleft is %d\n", skipleft); */
2877706df26Smrg
2887706df26Smrg    if(pTga->transparent_pattern_p) {
2897706df26Smrg	if(pTga->block_or_opaque_p == USE_BLOCK_FILL)
2907706df26Smrg	    TGA_FAST_WRITE_REG(BLOCKSTIPPLE | X11 | pTga->depthflag,
2917706df26Smrg			       TGA_MODE_REG);
2927706df26Smrg	else
2937706df26Smrg	    TGA_FAST_WRITE_REG(TRANSPARENTSTIPPLE | X11 | pTga->depthflag,
2947706df26Smrg			       TGA_MODE_REG);
2957706df26Smrg/*  	ErrorF("transparent stipple with x = %d, y = %d, w = %d, h = %d\n", */
2967706df26Smrg/*  	       x, y, w, h); */
2977706df26Smrg    }
2987706df26Smrg    else
2997706df26Smrg	TGA_FAST_WRITE_REG(OPAQUESTIPPLE | X11 | pTga->depthflag,
3007706df26Smrg			   TGA_MODE_REG);
3017706df26Smrg
3027706df26Smrg    TGA_SAVE_OFFSET();
3037706df26Smrg    return;
3047706df26Smrg}
3057706df26Smrg
3067706df26Smrgstatic void
3077706df26SmrgTGASubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
3087706df26Smrg{
3097706df26Smrg#ifdef PROFILE
3107706df26Smrg    unsigned int start, stop;
3117706df26Smrg#endif
3127706df26Smrg    TGAPtr pTga;
3137706df26Smrg    unsigned char *p = NULL;
3147706df26Smrg    int width = 0;
3157706df26Smrg    unsigned int addr;
3167706df26Smrg    unsigned int pixelmask = 0;
3177706df26Smrg    unsigned int stipple;
3187706df26Smrg    unsigned int align_mask;
3197706df26Smrg    int align = 0;
3207706df26Smrg    int skipleft;
3217706df26Smrg
3227706df26Smrg    CARD32 c = 0, d = 0;
3237706df26Smrg    CARD32 *e = NULL;
3247706df26Smrg    int i = 0, num_dwords = 0;
3257706df26Smrg    TGA_DECL();
3267706df26Smrg
3277706df26Smrg    pTga = TGAPTR(pScrn);
3287706df26Smrg    TGA_GET_IOBASE();
3297706df26Smrg    TGA_GET_OFFSET();
3307706df26Smrg
3317706df26Smrg    align_mask = (pTga->depthflag == BPP24) ? 0x0f : 0x03;
3327706df26Smrg
3337706df26Smrg#if 0
3347706df26Smrg    ErrorF("TGASubsequentColorExpandScanline called\n");
3357706df26Smrg    if(pTga->transparent_pattern_p)
3367706df26Smrg      ErrorF("transparent color expand\n");
3377706df26Smrg#endif
3387706df26Smrg
3397706df26Smrg    p = (unsigned char *)pTga->buffers[0];
3407706df26Smrg    addr = FB_OFFSET(pTga->ce_x, pTga->ce_y);
3417706df26Smrg    width = pTga->ce_width;
3427706df26Smrg    skipleft = pTga->ce_skipleft;
3437706df26Smrg
3447706df26Smrg    while(width > 0) {
3457706df26Smrg	if(!pTga->transparent_pattern_p)
3467706df26Smrg	    pixelmask = 0xFFFFFFFF;
3477706df26Smrg
3487706df26Smrg	align = (addr & align_mask) / pTga->Bpp; /* no. pixels out of align */
3497706df26Smrg	if (align) {
3507706df26Smrg	    if (!pTga->transparent_pattern_p)
3517706df26Smrg		pixelmask <<= align;
3527706df26Smrg/*  	    ErrorF("alignment is %d\n", align); */
3537706df26Smrg	    addr -= align * pTga->Bpp;
3547706df26Smrg	    width += align;
3557706df26Smrg
3567706df26Smrg	    e = (CARD32 *)p;
3577706df26Smrg	    num_dwords = (width / 32) + 1;
3587706df26Smrg	    if(num_dwords > (CE_BUFSIZE / 4)) { /* shouldn't happen */
3597706df26Smrg		ErrorF("TGASubsequentColorExpandScanline passed scanline %d bytes long, truncating\n", num_dwords * 4);
3607706df26Smrg		num_dwords = CE_BUFSIZE / 4;
3617706df26Smrg	    }
3627706df26Smrg	    for(i = 0; i < num_dwords; i++) {
3637706df26Smrg		c = e[i];
3647706df26Smrg		if(i == 0)
3657706df26Smrg		    e[i] = c << align;
3667706df26Smrg		else
3677706df26Smrg		    e[i] = (d >> (32 - align)) | (c << align);
3687706df26Smrg		d = c;
3697706df26Smrg	    }
3707706df26Smrg	}
3717706df26Smrg
3727706df26Smrg	if (!pTga->transparent_pattern_p) {
3737706df26Smrg	    if (skipleft) {
3747706df26Smrg		pixelmask <<= skipleft;
3757706df26Smrg		skipleft = 0;
3767706df26Smrg	    }
3777706df26Smrg	    if (width < 32) {
3787706df26Smrg		pixelmask &= (0xFFFFFFFF >> (32 - width));
3797706df26Smrg	    }
3807706df26Smrg	    TGA_FAST_WRITE_REG(pixelmask, TGA_PIXELMASK_REG);
3817706df26Smrg	}
3827706df26Smrg	else {
3837706df26Smrg	    unsigned int *i = NULL;
3847706df26Smrg
3857706df26Smrg/*  	    ErrorF("transparent scanline with x = %d, y = %d, w = %d, h = %d\n",  pTga->ce_x, pTga->ce_y, pTga->ce_width, pTga->ce_height); */
3867706df26Smrg	    if (skipleft) {
3877706df26Smrg		i = (unsigned int *)p;
3887706df26Smrg		*i &= (0xFFFFFFFF << skipleft);
3897706df26Smrg		skipleft = 0;
3907706df26Smrg	    }
3917706df26Smrg	    if (width < 32) {
3927706df26Smrg		i = (unsigned int *)p;
3937706df26Smrg		*i &= (0xFFFFFFFF >> (32 - width));
3947706df26Smrg	    }
3957706df26Smrg	}
3967706df26Smrg
3977706df26Smrg	stipple = *((unsigned int *)p);
3987706df26Smrg	switch (pTga->Chipset) {
3997706df26Smrg	case PCI_CHIP_TGA2:
4007706df26Smrg	    *(unsigned int *)(pTga->FbBase + addr) = stipple; WMB;
4017706df26Smrg	    break;
4027706df26Smrg	case PCI_CHIP_DEC21030:
4037706df26Smrg	    TGA_FAST_WRITE_REG(addr, TGA_ADDRESS_REG);
4047706df26Smrg	    TGA_FAST_WRITE_REG(stipple, TGA_CONTINUE_REG);
4057706df26Smrg	}
4067706df26Smrg	addr += 32 * pTga->Bpp;
4077706df26Smrg	p += 4;
4087706df26Smrg	width -= 32;
4097706df26Smrg    }
4107706df26Smrg    pTga->ce_height--;
4117706df26Smrg    if(pTga->ce_height == 0) {
4127706df26Smrg	TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag,
4137706df26Smrg			   TGA_MODE_REG);
4147706df26Smrg	TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
4157706df26Smrg	TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
4167706df26Smrg    }
4177706df26Smrg    else
4187706df26Smrg	pTga->ce_y += 1;
4197706df26Smrg
4207706df26Smrg    TGA_SAVE_OFFSET();
4217706df26Smrg    return;
4227706df26Smrg}
4237706df26Smrg
4247706df26Smrg/* Block Fill mode is faster, but only works for certain rops.  So we will
4257706df26Smrg   have to implement Opaque Fill anyway, so we will do that first, then
4267706df26Smrg   do Block Fill for the special cases
4277706df26Smrg*/
4287706df26Smrgvoid
4297706df26SmrgTGASetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
4307706df26Smrg		     unsigned int planemask)
4317706df26Smrg{
4327706df26Smrg#ifdef PROFILE
4337706df26Smrg  unsigned int start, stop;
4347706df26Smrg#endif
4357706df26Smrg  TGAPtr pTga;
4367706df26Smrg  unsigned int fgcolor = 0, pmask = 0;
4377706df26Smrg  TGA_DECL();
4387706df26Smrg
4397706df26Smrg  pTga = TGAPTR(pScrn);
4407706df26Smrg  TGA_GET_IOBASE();
4417706df26Smrg  TGA_GET_OFFSET();
4427706df26Smrg  /*  ErrorF("TGASetupForSolidFill called"); */
4437706df26Smrg
4447706df26Smrg  if(pTga->depthflag == BPP8PACKED) {
4457706df26Smrg    fgcolor = color | (color << 8) | (color << 16) | (color << 24);
4467706df26Smrg    pmask = planemask | (planemask << 8) | (planemask << 16) |
4477706df26Smrg		     (planemask << 24);
4487706df26Smrg  }
4497706df26Smrg  else {
4507706df26Smrg    fgcolor = color;
4517706df26Smrg    pmask = planemask;
4527706df26Smrg  }
4537706df26Smrg
4547706df26Smrg
4557706df26Smrg  if(rop == MIX_SRC) { /* we can just do a block copy */
4567706df26Smrg    pTga->block_or_opaque_p = USE_BLOCK_FILL;
4577706df26Smrg    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
4587706df26Smrg    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
4597706df26Smrg    if(pTga->depthflag == BPP24) {
4607706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
4617706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
4627706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
4637706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
4647706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
4657706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
4667706df26Smrg    }
4677706df26Smrg  }
4687706df26Smrg  else {
4697706df26Smrg    pTga->block_or_opaque_p = USE_OPAQUE_FILL;
4707706df26Smrg    pTga->current_rop = rop | pTga->depthflag;
4717706df26Smrg    TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
4727706df26Smrg/*      ErrorF("opaque fill called\n"); */
4737706df26Smrg  }
4747706df26Smrg
4757706df26Smrg  pTga->current_planemask = pmask;
4767706df26Smrg  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_DATA_REG);
4777706df26Smrg  TGA_SAVE_OFFSET();
4787706df26Smrg  return;
4797706df26Smrg}
4807706df26Smrg
4817706df26Smrgvoid
4827706df26SmrgTGASubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
4837706df26Smrg{
4847706df26Smrg  unsigned int mode_reg = 0;
4857706df26Smrg  int i = 0;
4867706df26Smrg  unsigned int pixel_count = 0; /* the actual # of pixels to be written */
4877706df26Smrg  unsigned int write_data = 0; /* the actual data written */
4887706df26Smrg  int a1 = 0;
4897706df26Smrg#ifdef PROFILE
4907706df26Smrg  unsigned int stop, start;
4917706df26Smrg#endif
4927706df26Smrg  TGAPtr pTga;
4937706df26Smrg  TGA_DECL();
4947706df26Smrg
4957706df26Smrg  pTga = TGAPTR(pScrn);
4967706df26Smrg  TGA_GET_IOBASE();
4977706df26Smrg  TGA_GET_OFFSET();
4987706df26Smrg
4997706df26Smrg  /*  ErrorF("TGASubsequentFillRectSolid called\n"); */
5007706df26Smrg
5017706df26Smrg  if(pTga->block_or_opaque_p == USE_OPAQUE_FILL) {
5027706df26Smrg    mode_reg = OPAQUEFILL | X11 | pTga->depthflag;
5037706df26Smrg    TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
5047706df26Smrg    /* we have to set this to GXCOPY every time before we exit */
5057706df26Smrg  }
5067706df26Smrg  else
5077706df26Smrg    mode_reg = BLOCKFILL | X11 | pTga->depthflag;
5087706df26Smrg
5097706df26Smrg  TGA_FAST_WRITE_REG(mode_reg, TGA_MODE_REG);
5107706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
5117706df26Smrg
5127706df26Smrg  if(w > 2048) {
5137706df26Smrg    ErrorF("TGASubsequentSolidFillRect called with w = %d, truncating.\n", w);
5147706df26Smrg    w = 2048;
5157706df26Smrg  }
5167706df26Smrg  pixel_count = w - 1;
5177706df26Smrg
5187706df26Smrg  for(i = 0; i < h; i++) {
5197706df26Smrg    a1 = FB_OFFSET(x, y + i);
5207706df26Smrg    if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
5217706df26Smrg      TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
5227706df26Smrg    write_data = pixel_count;
5237706df26Smrg    TGA_FAST_WRITE_REG(a1, TGA_ADDRESS_REG);
5247706df26Smrg    TGA_FAST_WRITE_REG(write_data, TGA_CONTINUE_REG);
5257706df26Smrg  }
5267706df26Smrg
5277706df26Smrg  mode_reg = SIMPLE | X11 | pTga->depthflag;
5287706df26Smrg  TGA_FAST_WRITE_REG(mode_reg, TGA_MODE_REG);
5297706df26Smrg  if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
5307706df26Smrg    TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag,
5317706df26Smrg		       TGA_RASTEROP_REG); /* GXCOPY */
5327706df26Smrg  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
5337706df26Smrg
5347706df26Smrg  TGA_SAVE_OFFSET();
5357706df26Smrg  return;
5367706df26Smrg}
5377706df26Smrg
5387706df26Smrg/* we only need to calculate the direction of a move once per move,
5397706df26Smrg   so we do it in the setup function and leave it */
5407706df26Smrg
5417706df26Smrgvoid
5427706df26SmrgTGASetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
5437706df26Smrg			      int rop, unsigned int planemask,
5447706df26Smrg			      int transparency_color)
5457706df26Smrg    /* xdir 1 = left-to-right, -1 = right to left
5467706df26Smrg       ydir 1 = top-to-bottom, -1 = bottom to top
5477706df26Smrg    */
5487706df26Smrg{
5497706df26Smrg#ifdef PROFILE
5507706df26Smrg  unsigned int start, stop;
5517706df26Smrg#endif
5527706df26Smrg  TGAPtr pTga;
5537706df26Smrg  unsigned int pmask = 0;
5547706df26Smrg  TGA_DECL();
5557706df26Smrg
5567706df26Smrg  pTga = TGAPTR(pScrn);
5577706df26Smrg  TGA_GET_IOBASE();
5587706df26Smrg  TGA_GET_OFFSET();
5597706df26Smrg
5607706df26Smrg  /* see section 6.2.9 */
5617706df26Smrg
5627706df26Smrg  if (pTga->depthflag == BPP8PACKED) {
5637706df26Smrg    pmask = planemask | (planemask << 8) | (planemask << 16) |
5647706df26Smrg		 (planemask << 24);
5657706df26Smrg  }
5667706df26Smrg  else
5677706df26Smrg    pmask = planemask;
5687706df26Smrg
5697706df26Smrg  pTga->current_planemask = pmask;
5707706df26Smrg  TGA_FAST_WRITE_REG(pmask, TGA_PLANEMASK_REG);
5717706df26Smrg
5727706df26Smrg  pTga->current_rop = rop | pTga->depthflag;
5737706df26Smrg
5747706df26Smrg  /* do we copy a rectangle from top to bottom or bottom to top? */
5757706df26Smrg  if (ydir == -1) {
5767706df26Smrg    pTga->blitdir = BLIT_FORWARDS;
5777706df26Smrg  }
5787706df26Smrg  else {
5797706df26Smrg    pTga->blitdir = BLIT_BACKWARDS;
5807706df26Smrg  }
5817706df26Smrg  TGA_SAVE_OFFSET();
5827706df26Smrg  return;
5837706df26Smrg}
5847706df26Smrg
5857706df26Smrg/*
5867706df26Smrg * This is the implementation of the SubsequentForScreenToScreenCopy
5877706df26Smrg * that sends commands to the coprocessor to perform a screen-to-screen
5887706df26Smrg * copy of the specified areas, with the parameters from the SetUp call.
5897706df26Smrg */
5907706df26Smrgvoid
5917706df26SmrgTGASubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
5927706df26Smrg				int y2, int w, int h)
5937706df26Smrg{
5947706df26Smrg  /* x1, y1 = source coords
5957706df26Smrg     x2, y2 = destination coords
5967706df26Smrg     w = width
5977706df26Smrg     h = height
5987706df26Smrg  */
5997706df26Smrg
6007706df26Smrg  int i = 0;
6017706df26Smrg  void (*copy_func)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w);
6027706df26Smrg#ifdef PROFILE
6037706df26Smrg  unsigned int stop, start;
6047706df26Smrg#endif
6057706df26Smrg  TGAPtr pTga;
6067706df26Smrg  TGA_DECL();
6077706df26Smrg
6087706df26Smrg  pTga = TGAPTR(pScrn);
6097706df26Smrg  TGA_GET_IOBASE();
6107706df26Smrg  TGA_GET_OFFSET();
6117706df26Smrg#if 0
6127706df26Smrg  ErrorF("TGASubsequentScreenToScreenCopy(,%d,%d,%d,%d,%d,%d):"
6137706df26Smrg	 " COPY %s BLIT %s\n",
6147706df26Smrg	 x1, y1, x2, y2, w, h, (x2 > x1 && (x1 + w) > x2)?"BWD":"FWD",
6157706df26Smrg	 (pTga->blitdir == BLIT_FORWARDS)?"FWD":"BWD");
6167706df26Smrg#endif
6177706df26Smrg  TGASync(pScrn); /* ?? */
6187706df26Smrg
6197706df26Smrg  TGA_FAST_WRITE_REG(COPY | X11 | pTga->depthflag, TGA_MODE_REG);
6207706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
6217706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
6227706df26Smrg
6237706df26Smrg  if(x2 > x1 && (x1 + w) > x2)
6247706df26Smrg    copy_func = TGACopyLineBackwards;
6257706df26Smrg  else
6267706df26Smrg    copy_func = TGACopyLineForwards;
6277706df26Smrg
6287706df26Smrg  TGA_SAVE_OFFSET();
6297706df26Smrg  if(pTga->blitdir == BLIT_FORWARDS) {
6307706df26Smrg    for(i = h - 1; i >= 0; i--) { /* copy from bottom to top */
6317706df26Smrg      (*copy_func)(pScrn, x1, y1 + i, x2, y2 + i, w);
6327706df26Smrg    }
6337706df26Smrg  }
6347706df26Smrg  else {
6357706df26Smrg    for(i = 0; i < h; i++) {
6367706df26Smrg      (*copy_func)(pScrn, x1, y1 + i, x2, y2 + i, w);
6377706df26Smrg    }
6387706df26Smrg  }
6397706df26Smrg
6407706df26Smrg  TGASync(pScrn); /* ?? */
6417706df26Smrg
6427706df26Smrg  TGA_GET_OFFSET();
6437706df26Smrg  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
6447706df26Smrg  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
6457706df26Smrg  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
6467706df26Smrg  TGA_SAVE_OFFSET();
6477706df26Smrg
6487706df26Smrg  return;
6497706df26Smrg}
6507706df26Smrg
6517706df26Smrg
6527706df26Smrgvoid
6537706df26SmrgTGACopyLineForwards(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w)
6547706df26Smrg{
6557706df26Smrg  /* copy a line of width w from x1,y1 to x2,y2 using copy mode */
6567706df26Smrg  int read;
6577706df26Smrg  unsigned long source_address, destination_address;
6587706df26Smrg  unsigned int mask_source, mask_destination;
6597706df26Smrg  int cando;
6607706df26Smrg  unsigned int cando_mask;
6617706df26Smrg  int source_align, destination_align;
6627706df26Smrg  int pixel_shift;
6637706df26Smrg#ifdef PROFILE
6647706df26Smrg  unsigned int start, stop;
6657706df26Smrg#endif
6667706df26Smrg  TGAPtr pTga;
6677706df26Smrg  TGA_DECL();
6687706df26Smrg
6697706df26Smrg  pTga = TGAPTR(pScrn);
6707706df26Smrg  TGA_GET_IOBASE();
6717706df26Smrg  TGA_GET_OFFSET();
6727706df26Smrg
6737706df26Smrg  cando = 32;
6747706df26Smrg  cando_mask = 0xFFFFFFFFU;
6757706df26Smrg  if (pTga->Chipset == PCI_CHIP_DEC21030 && pTga->depthflag == BPP24) {
6767706df26Smrg    cando = 16;
6777706df26Smrg    cando_mask = 0x0000FFFFU;
6787706df26Smrg  }
6797706df26Smrg
6807706df26Smrg  source_address = FB_OFFSET(x1, y1);
6817706df26Smrg  destination_address = FB_OFFSET(x2, y2);
6827706df26Smrg#if 0
6837706df26Smrg  ErrorF("CPY-FWD(,%d,%d,%d,%d,%d): sadr = 0x%lx, dadr = 0x%lx\n",
6847706df26Smrg	 x1, y1, x2, y2, w, source_address, destination_address);
6857706df26Smrg#endif
6867706df26Smrg  read = 0;
6877706df26Smrg  while (read < w) {
6887706df26Smrg
6897706df26Smrg    mask_source = cando_mask;
6907706df26Smrg    if ((w - read) >= cando)
6917706df26Smrg      mask_destination = cando_mask;
6927706df26Smrg    else
6937706df26Smrg      mask_destination = cando_mask >> (cando - (w - read));
6947706df26Smrg
6957706df26Smrg    source_align = source_address & 0x07;
6967706df26Smrg    source_address -= source_align;
6977706df26Smrg    mask_source <<= source_align / pTga->Bpp;
6987706df26Smrg    /*    mask_source &= cando_mask; */
6997706df26Smrg
7007706df26Smrg    destination_align = destination_address & 0x07;
7017706df26Smrg    destination_address -= destination_align;
7027706df26Smrg    mask_destination <<= destination_align / pTga->Bpp;
7037706df26Smrg    /*    mask_destination &= cando_mask; */
7047706df26Smrg
7057706df26Smrg    if (destination_align >= source_align)
7067706df26Smrg      pixel_shift = destination_align - source_align;
7077706df26Smrg    else {
7087706df26Smrg      pixel_shift = 8 - (source_align - destination_align);
7097706df26Smrg      /* we need to prime the residue register in this case */
7107706df26Smrg      destination_address -= 8;
7117706df26Smrg      mask_destination <<= 8 / pTga->Bpp;
7127706df26Smrg      mask_destination &= cando_mask;/* ?? */
7137706df26Smrg    }
7147706df26Smrg
7157706df26Smrg    TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
7167706df26Smrg    switch (pTga->Chipset) {
7177706df26Smrg    case PCI_CHIP_TGA2:
7187706df26Smrg        *(unsigned int *)(pTga->FbBase + source_address) = mask_source; WMB;
7197706df26Smrg	*(unsigned int *)(pTga->FbBase + destination_address) = mask_destination; WMB;
7207706df26Smrg	break;
7217706df26Smrg    case PCI_CHIP_DEC21030:
7227706df26Smrg        /* use GADR and GCTR */
7237706df26Smrg        TGA_FAST_WRITE_REG(source_address, TGA_ADDRESS_REG);
7247706df26Smrg	TGA_FAST_WRITE_REG(mask_source, TGA_CONTINUE_REG);
7257706df26Smrg	TGA_FAST_WRITE_REG(destination_address, TGA_ADDRESS_REG);
7267706df26Smrg	TGA_FAST_WRITE_REG(mask_destination, TGA_CONTINUE_REG);
7277706df26Smrg	break;
7287706df26Smrg    }
7297706df26Smrg
7307706df26Smrg    source_address += (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
7317706df26Smrg    destination_address += cando * pTga->Bpp;
7327706df26Smrg
7337706df26Smrg    read += cando;
7347706df26Smrg    read -= destination_align / pTga->Bpp; /* "read" is perhaps better
7357706df26Smrg				    called "written"... */
7367706df26Smrg    if (destination_align < source_align) {
7377706df26Smrg      read -= 8 / pTga->Bpp;
7387706df26Smrg    }
7397706df26Smrg  }
7407706df26Smrg
7417706df26Smrg  TGA_SAVE_OFFSET();
7427706df26Smrg  return;
7437706df26Smrg}
7447706df26Smrg
7457706df26Smrg
7467706df26Smrgvoid
7477706df26SmrgTGACopyLineBackwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
7487706df26Smrg			  int y2, int w)
7497706df26Smrg     /* x1, y1 = source
7507706df26Smrg	x2, y2 = destination
7517706df26Smrg	w = width
7527706df26Smrg     */
7537706df26Smrg{
7547706df26Smrg  unsigned long a1, a2;
7557706df26Smrg  unsigned long source_address, destination_address;
7567706df26Smrg  unsigned int mask_source, mask_destination;
7577706df26Smrg  int cando;
7587706df26Smrg  unsigned int cando_mask;
7597706df26Smrg  int source_align, destination_align;
7607706df26Smrg  int pixel_shift;
7617706df26Smrg  int read;
7627706df26Smrg#ifdef PROFILE
7637706df26Smrg  unsigned int start, stop;
7647706df26Smrg#endif
7657706df26Smrg  TGAPtr pTga;
7667706df26Smrg  TGA_DECL();
7677706df26Smrg
7687706df26Smrg  pTga = TGAPTR(pScrn);
7697706df26Smrg  TGA_GET_IOBASE();
7707706df26Smrg  TGA_GET_OFFSET();
7717706df26Smrg
7727706df26Smrg  cando = 32;
7737706df26Smrg  cando_mask = 0xFFFFFFFFU;
7747706df26Smrg  if (pTga->Chipset == PCI_CHIP_DEC21030 && pTga->depthflag == BPP24) {
7757706df26Smrg    cando = 16;
7767706df26Smrg    cando_mask = 0x0000FFFFU;
7777706df26Smrg  }
7787706df26Smrg
7797706df26Smrg  a1 = FB_OFFSET(x1, y1);
7807706df26Smrg  a2 = FB_OFFSET(x2, y2);
7817706df26Smrg
7827706df26Smrg  source_address = FB_OFFSET((x1 + w) - cando, y1);
7837706df26Smrg  destination_address = FB_OFFSET((x2 + w) - cando, y2);
7847706df26Smrg
7857706df26Smrg#if 0
7867706df26Smrg  ErrorF("CPY-BWD(,%d,%d,%d,%d,%d): sadr = 0x%lx, dadr = 0x%lx"
7877706df26Smrg	 " a1 0x%lx a2 0x%lx\n",
7887706df26Smrg	 x1, y1, x2, y2, w, source_address, destination_address, a1, a2);
7897706df26Smrg#endif
7907706df26Smrg
7917706df26Smrg  read = 0;
7927706df26Smrg  while (read < w) {
7937706df26Smrg    mask_source = cando_mask;
7947706df26Smrg    if ((w - read) >= cando)
7957706df26Smrg      mask_destination = cando_mask;
7967706df26Smrg    else {
7977706df26Smrg      mask_destination = ((unsigned int)cando_mask) << (cando - (w - read));
7987706df26Smrg      mask_destination &= cando_mask; /* esp. for cando==16 */
7997706df26Smrg    }
8007706df26Smrg
8017706df26Smrg    source_align = source_address & 0x07;
8027706df26Smrg    destination_align = destination_address & 0x07;
8037706df26Smrg
8047706df26Smrg    if (read == 0 && destination_align &&
8057706df26Smrg       (source_align > destination_align)) {
8067706df26Smrg      /* we want to take out all the destination_align pixels in one
8077706df26Smrg	 little copy first, then move on to the main stuff */
8087706df26Smrg      unsigned long tmp_src, tmp_dest;
8097706df26Smrg      unsigned int tmp_src_mask, tmp_dest_mask;
8107706df26Smrg
8117706df26Smrg      tmp_src = a1 + (w - (source_align / pTga->Bpp)) * pTga->Bpp;
8127706df26Smrg      tmp_dest = a2 + (w - (destination_align / pTga->Bpp) - (8 / pTga->Bpp)) * pTga->Bpp;
8137706df26Smrg      tmp_src_mask = cando_mask;
8147706df26Smrg      tmp_dest_mask = ((unsigned int)0x000000FF) >> (8 - destination_align) / pTga->Bpp;
8157706df26Smrg      tmp_dest_mask <<= 8 / pTga->Bpp;
8167706df26Smrg      pixel_shift = (8 - source_align) + destination_align;
8177706df26Smrg#if 0
8187706df26Smrg      ErrorF("CPY-BWD - preliminary copy: sa = %d, da = %d, ps =%d\n",
8197706df26Smrg	     source_align, destination_align, pixel_shift);
8207706df26Smrg#endif
8217706df26Smrg      TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
8227706df26Smrg      switch (pTga->Chipset)
8237706df26Smrg      {
8247706df26Smrg      case PCI_CHIP_TGA2:
8257706df26Smrg	  *(unsigned int *)(pTga->FbBase + tmp_src) = tmp_src_mask; WMB;
8267706df26Smrg	  *(unsigned int *)(pTga->FbBase + tmp_dest) = tmp_dest_mask; WMB;
8277706df26Smrg	  break;
8287706df26Smrg      case PCI_CHIP_DEC21030:
8297706df26Smrg	  /* use GADR and GCTR */
8307706df26Smrg	  TGA_FAST_WRITE_REG(tmp_src, TGA_ADDRESS_REG);
8317706df26Smrg	  TGA_FAST_WRITE_REG(tmp_src_mask, TGA_CONTINUE_REG);
8327706df26Smrg	  TGA_FAST_WRITE_REG(tmp_dest, TGA_ADDRESS_REG);
8337706df26Smrg	  TGA_FAST_WRITE_REG(tmp_dest_mask, TGA_CONTINUE_REG);
8347706df26Smrg	  break;
8357706df26Smrg      }
8367706df26Smrg
8377706df26Smrg      source_address += (8 - source_align);
8387706df26Smrg      mask_source >>= (8 - source_align) / pTga->Bpp;
8397706df26Smrg      mask_source >>= destination_align / pTga->Bpp;
8407706df26Smrg      mask_destination >>= destination_align / pTga->Bpp;
8417706df26Smrg    }
8427706df26Smrg    else if (read == 0 && (source_align != destination_align)) {
8437706df26Smrg      source_address += (8 - source_align);
8447706df26Smrg      /*    	mask_source >>= (8 - source_align); */
8457706df26Smrg      /* if we uncomment this, it breaks...TGA tries to
8467706df26Smrg	 optimize away a read of our last pixels... */
8477706df26Smrg    }
8487706df26Smrg    else if (source_align) {
8497706df26Smrg      source_address += (8 - source_align);
8507706df26Smrg      mask_source >>= (8 - source_align) / pTga->Bpp;
8517706df26Smrg    }
8527706df26Smrg
8537706df26Smrg    if (destination_align) {
8547706df26Smrg      destination_address += (8 - destination_align);
8557706df26Smrg      mask_destination >>= (8 - destination_align) / pTga->Bpp;
8567706df26Smrg    }
8577706df26Smrg
8587706df26Smrg    if (destination_align >= source_align)
8597706df26Smrg      pixel_shift = destination_align - source_align;
8607706df26Smrg    else {
8617706df26Smrg      pixel_shift = (8 - source_align) + destination_align;
8627706df26Smrg      if (destination_align) {
8637706df26Smrg	source_address += 8;
8647706df26Smrg	mask_source >>= 8 / pTga->Bpp;
8657706df26Smrg      }
8667706df26Smrg    }
8677706df26Smrg
8687706df26Smrg#if 0
8697706df26Smrg    ErrorF("CPY-BWD - normal: sadr 0x%lx sm 0x%x dadr 0x%lx dm 0x%x"
8707706df26Smrg	   " sa %d da %d ps %d read %d\n",
8717706df26Smrg	   source_address, mask_source,
8727706df26Smrg	   destination_address, mask_destination,
8737706df26Smrg	   source_align, destination_align, pixel_shift, read);
8747706df26Smrg#endif
8757706df26Smrg    TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
8767706df26Smrg    switch (pTga->Chipset) {
8777706df26Smrg    case PCI_CHIP_TGA2:
8787706df26Smrg        *(unsigned int *)(pTga->FbBase + source_address) = mask_source; WMB;
8797706df26Smrg	*(unsigned int *)(pTga->FbBase + destination_address) = mask_destination; WMB;
8807706df26Smrg	break;
8817706df26Smrg    case PCI_CHIP_DEC21030:
8827706df26Smrg        /* use GADR and GCTR */
8837706df26Smrg        TGA_FAST_WRITE_REG(source_address, TGA_ADDRESS_REG);
8847706df26Smrg	TGA_FAST_WRITE_REG(mask_source, TGA_CONTINUE_REG);
8857706df26Smrg	TGA_FAST_WRITE_REG(destination_address, TGA_ADDRESS_REG);
8867706df26Smrg	TGA_FAST_WRITE_REG(mask_destination, TGA_CONTINUE_REG);
8877706df26Smrg	break;
8887706df26Smrg    }
8897706df26Smrg
8907706df26Smrg/*      if(read == 0) */
8917706df26Smrg/*        ErrorF("sa = %d, da = %d, ps = %d\n", source_align, destination_align, */
8927706df26Smrg/*      	     pixel_shift); */
8937706df26Smrg
8947706df26Smrg    if (destination_align > source_align) {
8957706df26Smrg      source_address -= cando * pTga->Bpp - 8;
8967706df26Smrg      destination_address -= (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
8977706df26Smrg      if (read == 0)
8987706df26Smrg	read += (cando - 8 / pTga->Bpp) + source_align / pTga->Bpp;
8997706df26Smrg      else
9007706df26Smrg	read += cando - 8 / pTga->Bpp;
9017706df26Smrg    }
9027706df26Smrg    else if (destination_align == source_align) {
9037706df26Smrg      source_address -= cando * pTga->Bpp;
9047706df26Smrg      destination_address -= cando * pTga->Bpp;
9057706df26Smrg      if (read == 0 && destination_align)
9067706df26Smrg	read += (cando - (8 - destination_align) / pTga->Bpp);
9077706df26Smrg      else
9087706df26Smrg	read += cando;
9097706df26Smrg    }
9107706df26Smrg    else if (source_align > destination_align) {
9117706df26Smrg      source_address -= cando * pTga->Bpp - 8;
9127706df26Smrg      destination_address -= (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
9137706df26Smrg      /* only happens when read == 0 */
9147706df26Smrg      if (destination_align)
9157706df26Smrg	read += (cando - 16 / pTga->Bpp) + source_align / pTga->Bpp;
9167706df26Smrg      else
9177706df26Smrg	read += cando - pixel_shift / pTga->Bpp;
9187706df26Smrg    }
9197706df26Smrg  }
9207706df26Smrg
9217706df26Smrg  TGA_SAVE_OFFSET();
9227706df26Smrg  return;
9237706df26Smrg}
9247706df26Smrg
9257706df26Smrgvoid
9267706df26SmrgTGASetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
9277706df26Smrg			      int fg, int bg, int rop, unsigned int planemask)
9287706df26Smrg{
9297706df26Smrg#ifdef PROFILE
9307706df26Smrg  unsigned int start, stop;
9317706df26Smrg#endif
9327706df26Smrg  TGAPtr pTga;
9337706df26Smrg  unsigned int fgcolor = 0, bgcolor = 0, pmask = 0;
9347706df26Smrg  TGA_DECL();
9357706df26Smrg
9367706df26Smrg  pTga = TGAPTR(pScrn);
9377706df26Smrg  TGA_GET_IOBASE();
9387706df26Smrg  TGA_GET_OFFSET();
9397706df26Smrg
9407706df26Smrg/*    ErrorF("TGASetupForMono8x8PatternFill called with patx = %d, paty = %d, fg = %d, bg = %d, rop = %d, planemask = %d\n", */
9417706df26Smrg/*  	 patx, paty, fg, bg, rop, planemask);  */
9427706df26Smrg
9437706df26Smrg  if(bg == -1)  /* we are transparent */
9447706df26Smrg    pTga->transparent_pattern_p = 1;
9457706df26Smrg  else
9467706df26Smrg    pTga->transparent_pattern_p = 0;
9477706df26Smrg
9487706df26Smrg  if(rop == MIX_SRC)
9497706df26Smrg    pTga->block_or_opaque_p = USE_BLOCK_FILL;
9507706df26Smrg  else
9517706df26Smrg    pTga->block_or_opaque_p = USE_OPAQUE_FILL;
9527706df26Smrg
9537706df26Smrg  if(pTga->depthflag == BPP8PACKED) {
9547706df26Smrg    fgcolor = fg | (fg << 8) | (fg << 16) | (fg << 24);
9557706df26Smrg    bgcolor = bg | (bg << 8) | (bg << 16) | (bg << 24);
9567706df26Smrg    pmask = planemask | (planemask << 8) | (planemask << 16) |
9577706df26Smrg      (planemask << 24);
9587706df26Smrg  }
9597706df26Smrg  else {
9607706df26Smrg    fgcolor = fg;
9617706df26Smrg    bgcolor = bg;
9627706df26Smrg    pmask = planemask;
9637706df26Smrg  }
9647706df26Smrg
9657706df26Smrg
9667706df26Smrg  if(pTga->transparent_pattern_p &&
9677706df26Smrg     pTga->block_or_opaque_p == USE_BLOCK_FILL) {
9687706df26Smrg    /* we can use block fill mode to draw a transparent stipple */
9697706df26Smrg    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
9707706df26Smrg    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
9717706df26Smrg    if(pTga->depthflag == BPP24) {
9727706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
9737706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
9747706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
9757706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
9767706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
9777706df26Smrg      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
9787706df26Smrg    }
9797706df26Smrg  }
9807706df26Smrg  else if(pTga->transparent_pattern_p) {
9817706df26Smrg    TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
9827706df26Smrg  }
9837706df26Smrg  else {
9847706df26Smrg    TGA_FAST_WRITE_REG(bgcolor, TGA_BACKGROUND_REG);
9857706df26Smrg    TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
9867706df26Smrg    TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
9877706df26Smrg  }
9887706df26Smrg  pTga->current_rop = rop;
9897706df26Smrg  pTga->current_planemask = pmask;
9907706df26Smrg  TGA_SAVE_OFFSET();
9917706df26Smrg  return;
9927706df26Smrg}
9937706df26Smrg
9947706df26Smrgvoid
9957706df26SmrgTGASubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
9967706df26Smrg				    int x, int y, int w, int h)
9977706df26Smrg/* patx and paty = first & second dwords of pattern to be rendered, packed */
9987706df26Smrg{
9997706df26Smrg  TGAPtr pTga;
10007706df26Smrg  int i, j;
10017706df26Smrg  unsigned int stipple_mask[8], align, tmp;
10027706df26Smrg#ifdef PROFILE
10037706df26Smrg  register unsigned int stop, start;
10047706df26Smrg#endif
10057706df26Smrg  TGA_DECL();
10067706df26Smrg
10077706df26Smrg
10087706df26Smrg/*    ErrorF("TGASubsequentMono8x8PatternFillRect called with x = %d, y = %d, w = %d, h = %d\n", x, y, w, h); */
10097706df26Smrg
10107706df26Smrg  pTga = TGAPTR(pScrn);
10117706df26Smrg  TGA_GET_IOBASE();
10127706df26Smrg  TGA_GET_OFFSET();
10137706df26Smrg
10147706df26Smrg  if(w > 2048)
10157706df26Smrg    ErrorF("TGASubsequentMono8x8PatternFillRect called with w > 2048, truncating\n");
10167706df26Smrg  if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
10177706df26Smrg    TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
10187706df26Smrg
10197706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
10207706df26Smrg  if(pTga->depthflag == BPP8PACKED)
10217706df26Smrg    align = FB_OFFSET(x, y) % 4;
10227706df26Smrg  else
10237706df26Smrg    align = x % 4;
10247706df26Smrg
10257706df26Smrg  for(i = 0; i < 4; i++) {
10267706df26Smrg    tmp = (patx >> (i * 8)) & 0xFF;
10277706df26Smrg    stipple_mask[i] = (tmp | (tmp << 8) | (tmp << 16) | (tmp << 24));
10287706df26Smrg  }
10297706df26Smrg  for(i = 4; i < 8; i++) {
10307706df26Smrg    tmp = (paty >> ((i - 4) * 8)) & 0xFF;
10317706df26Smrg    stipple_mask[i] = (tmp | (tmp << 8) | (tmp << 16) | (tmp << 24));
10327706df26Smrg  }
10337706df26Smrg  if(align) { /* stipples must be aligned to four bytes */
10347706df26Smrg    for(i = 0; i < 8; i++) {
10357706df26Smrg      stipple_mask[i] = (stipple_mask[i] << align) |
10367706df26Smrg	((stipple_mask[i] & 0xFF000000) >> (32 - align));
10377706df26Smrg    }
10387706df26Smrg  }
10397706df26Smrg
10407706df26Smrg  if((pTga->block_or_opaque_p == USE_BLOCK_FILL) && pTga->transparent_pattern_p) {
10417706df26Smrg    /* use block fill */
10427706df26Smrg    TGA_FAST_WRITE_REG(BLOCKFILL | X11 | pTga->depthflag, TGA_MODE_REG);
10437706df26Smrg
10447706df26Smrg    for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
10457706df26Smrg      TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
10467706df26Smrg      TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
10477706df26Smrg      TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
10487706df26Smrg    }
10497706df26Smrg  }
10507706df26Smrg  else if(pTga->transparent_pattern_p) {
10517706df26Smrg    /* if we can't use block fill, we'll use transparent fill */
10527706df26Smrg    TGA_FAST_WRITE_REG(TRANSPARENTFILL | X11 | pTga->depthflag, TGA_MODE_REG);
10537706df26Smrg    for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
10547706df26Smrg      TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
10557706df26Smrg      TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
10567706df26Smrg      TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
10577706df26Smrg    }
10587706df26Smrg  }
10597706df26Smrg  else { /* use opaque fill mode */
10607706df26Smrg/*      ErrorF("Using opaque fill mode\n"); */
10617706df26Smrg    TGA_FAST_WRITE_REG(OPAQUEFILL | X11 | pTga->depthflag, TGA_MODE_REG);
10627706df26Smrg    for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
10637706df26Smrg      TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
10647706df26Smrg      TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
10657706df26Smrg      TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
10667706df26Smrg    }
10677706df26Smrg  }
10687706df26Smrg
10697706df26Smrg  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
10707706df26Smrg  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
10717706df26Smrg  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
10727706df26Smrg
10737706df26Smrg  TGA_SAVE_OFFSET();
10747706df26Smrg
10757706df26Smrg  return;
10767706df26Smrg}
10777706df26Smrg
10787706df26Smrgvoid
10797706df26SmrgTGASetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
10807706df26Smrg		     unsigned int planemask)
10817706df26Smrg{
10827706df26Smrg#ifdef PROFILE
10837706df26Smrg  unsigned int start, stop;
10847706df26Smrg#endif
10857706df26Smrg  TGAPtr pTga = NULL;
10867706df26Smrg  unsigned int fgcolor = 0, pmask = 0;
10877706df26Smrg  TGA_DECL();
10887706df26Smrg
10897706df26Smrg  pTga = TGAPTR(pScrn);
10907706df26Smrg  TGA_GET_IOBASE();
10917706df26Smrg  TGA_GET_OFFSET();
10927706df26Smrg/*    ErrorF("TGASetupForSolidLine called\n"); */
10937706df26Smrg
10947706df26Smrg  if(pTga->depthflag == BPP8PACKED) {
10957706df26Smrg    fgcolor = color | (color << 8) | (color << 16) | (color << 24);
10967706df26Smrg    pmask = planemask | (planemask << 8) | (planemask << 16) |
10977706df26Smrg      (planemask << 24);
10987706df26Smrg  }
10997706df26Smrg  else {
11007706df26Smrg    fgcolor = color;
11017706df26Smrg    pmask = planemask;
11027706df26Smrg  }
11037706df26Smrg
11047706df26Smrg
11057706df26Smrg  pTga->current_rop = rop | pTga->depthflag;
11067706df26Smrg  TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
11077706df26Smrg  pTga->current_planemask = pmask;
11087706df26Smrg  TGA_FAST_WRITE_REG(0xFFFF, TGA_DATA_REG);
11097706df26Smrg  TGA_FAST_WRITE_REG(pScrn->displayWidth, TGA_WIDTH_REG);
11107706df26Smrg  TGA_SAVE_OFFSET();
11117706df26Smrg
11127706df26Smrg  return;
11137706df26Smrg}
11147706df26Smrg
11157706df26Smrgvoid
11167706df26SmrgTGASubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
11177706df26Smrg			      int dir)
11187706df26Smrg{
11197706df26Smrg  if(dir == DEGREES_0)  /* line is to the right */
11207706df26Smrg      TGASubsequentSolidLine(pScrn, x, y, x + len, y, 0x0, OMIT_LAST);
11217706df26Smrg  else if(dir == DEGREES_270) /* line is down */
11227706df26Smrg      TGASubsequentSolidLine(pScrn, x, y, x, y + len, YMAJOR, OMIT_LAST);
11237706df26Smrg  else
11247706df26Smrg      ErrorF("TGASubsequentSolidHorVertLine passed dir %d!\n", dir);
11257706df26Smrg
11267706df26Smrg  return;
11277706df26Smrg}
11287706df26Smrg
11297706df26Smrgvoid
11307706df26SmrgTGASubsequentSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
11317706df26Smrg		       int octant, int flags)
11327706df26Smrg{
11337706df26Smrg#ifdef PROFILE
11347706df26Smrg  unsigned int start, stop;
11357706df26Smrg#endif
11367706df26Smrg  TGAPtr pTga = NULL;
11377706df26Smrg  CARD32 abs_dx = 0, abs_dy = 0, address = 0, octant_reg = 0;
11387706df26Smrg  int length = 0;
11397706df26Smrg  TGA_DECL();
11407706df26Smrg
11417706df26Smrg  pTga = TGAPTR(pScrn);
11427706df26Smrg  TGA_GET_IOBASE();
11437706df26Smrg  TGA_GET_OFFSET();
11447706df26Smrg/*    ErrorF("TGASubsequentSolidLine called\n"); */
11457706df26Smrg
11467706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
11477706df26Smrg  TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag |
11487706df26Smrg		     ((flags & OMIT_LAST) ? 0x0 : CAP_ENDS), TGA_MODE_REG);
11497706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
11507706df26Smrg
11517706df26Smrg  address = FB_OFFSET(x1, y1);
11527706df26Smrg  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
11537706df26Smrg  abs_dx = abs(x2 - x1);
11547706df26Smrg  abs_dy = abs(y2 - y1);
11557706df26Smrg  if(octant & YMAJOR)
11567706df26Smrg    length = abs_dy;
11577706df26Smrg  else
11587706df26Smrg    length = abs_dx;
11597706df26Smrg
11607706df26Smrg  if(octant & YMAJOR) {
11617706df26Smrg      if(octant & YDECREASING) {
11627706df26Smrg	  if(octant & XDECREASING)
11637706df26Smrg	      octant_reg = TGA_SLOPE0_REG;
11647706df26Smrg	  else
11657706df26Smrg	      octant_reg = TGA_SLOPE2_REG;
11667706df26Smrg      }
11677706df26Smrg      else {
11687706df26Smrg	  if(octant & XDECREASING)
11697706df26Smrg	      octant_reg = TGA_SLOPE1_REG;
11707706df26Smrg	  else
11717706df26Smrg	      octant_reg = TGA_SLOPE3_REG;
11727706df26Smrg      }
11737706df26Smrg  }
11747706df26Smrg  else {
11757706df26Smrg      if(octant & YDECREASING) {
11767706df26Smrg	  if(octant & XDECREASING)
11777706df26Smrg	      octant_reg = TGA_SLOPE4_REG;
11787706df26Smrg	  else
11797706df26Smrg	      octant_reg = TGA_SLOPE6_REG;
11807706df26Smrg      }
11817706df26Smrg      else {
11827706df26Smrg	  if(octant & XDECREASING)
11837706df26Smrg	      octant_reg = TGA_SLOPE5_REG;
11847706df26Smrg	  else
11857706df26Smrg	      octant_reg = TGA_SLOPE7_REG;
11867706df26Smrg      }
11877706df26Smrg  }
11887706df26Smrg
11897706df26Smrg  TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
11907706df26Smrg  if(length > 16 && length % 16)
11917706df26Smrg    length -= length % 16;
11927706df26Smrg  else
11937706df26Smrg    length -= 16;
11947706df26Smrg
11957706df26Smrg  while(length > 0) {
11967706df26Smrg    TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_CONTINUE_REG);
11977706df26Smrg    length -= 16;
11987706df26Smrg  }
11997706df26Smrg
12007706df26Smrg  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
12017706df26Smrg  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
12027706df26Smrg  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
12037706df26Smrg
12047706df26Smrg  TGA_SAVE_OFFSET();
12057706df26Smrg
12067706df26Smrg  return;
12077706df26Smrg}
12087706df26Smrg
12097706df26Smrgvoid
12107706df26SmrgTGASetupForClippedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
12117706df26Smrg		       int octant)
12127706df26Smrg{
12137706df26Smrg#ifdef PROFILE
12147706df26Smrg  unsigned int start, stop;
12157706df26Smrg#endif
12167706df26Smrg  TGAPtr pTga = NULL;
12177706df26Smrg  CARD32 abs_dx = 0, abs_dy = 0, octant_reg = 0;
12187706df26Smrg  TGA_DECL();
12197706df26Smrg
12207706df26Smrg  pTga = TGAPTR(pScrn);
12217706df26Smrg  TGA_GET_IOBASE();
12227706df26Smrg  TGA_GET_OFFSET();
12237706df26Smrg/*    ErrorF("TGASetupForClippedLine called\n"); */
12247706df26Smrg
12257706df26Smrg/*    TGA_FAST_WRITE_REG(pTga->current_rop | BPP8PACKED, TGA_RASTEROP_REG); */
12267706df26Smrg/*    TGA_FAST_WRITE_REG(OPAQUELINE | X11 | BPP8PACKED, TGA_MODE_REG); */
12277706df26Smrg
12287706df26Smrg  abs_dx = abs(x2 - x1);
12297706df26Smrg  abs_dy = abs(y2 - y1);
12307706df26Smrg
12317706df26Smrg  if(octant & YMAJOR) {
12327706df26Smrg      if(octant & YDECREASING) {
12337706df26Smrg	  if(octant & XDECREASING)
12347706df26Smrg	      octant_reg = TGA_NOSLOPE0_REG;
12357706df26Smrg	  else
12367706df26Smrg	      octant_reg = TGA_NOSLOPE2_REG;
12377706df26Smrg      }
12387706df26Smrg      else {
12397706df26Smrg	  if(octant & XDECREASING)
12407706df26Smrg	      octant_reg = TGA_NOSLOPE1_REG;
12417706df26Smrg	  else
12427706df26Smrg	      octant_reg = TGA_NOSLOPE3_REG;
12437706df26Smrg      }
12447706df26Smrg  }
12457706df26Smrg  else {
12467706df26Smrg      if(octant & YDECREASING) {
12477706df26Smrg	  if(octant & XDECREASING)
12487706df26Smrg	      octant_reg = TGA_NOSLOPE4_REG;
12497706df26Smrg	  else
12507706df26Smrg	      octant_reg = TGA_NOSLOPE6_REG;
12517706df26Smrg      }
12527706df26Smrg      else {
12537706df26Smrg	  if(octant & XDECREASING)
12547706df26Smrg	      octant_reg = TGA_NOSLOPE5_REG;
12557706df26Smrg	  else
12567706df26Smrg	      octant_reg = TGA_NOSLOPE7_REG;
12577706df26Smrg      }
12587706df26Smrg  }
12597706df26Smrg
12607706df26Smrg  TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
12617706df26Smrg
12627706df26Smrg  TGA_SAVE_OFFSET();
12637706df26Smrg  return;
12647706df26Smrg}
12657706df26Smrg
12667706df26Smrgvoid
12677706df26SmrgTGASubsequentClippedSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
12687706df26Smrg			      int err)
12697706df26Smrg    /* we are already in line mode, now we need to
12707706df26Smrg       1) write starting pixel address to gaddr
12717706df26Smrg       2) write initial error and line length to bresenham 3
12727706df26Smrg       3) write the gctr to draw the line, and repeat for lines > 16 pixels
12737706df26Smrg       4) set mode back to simple mode
12747706df26Smrg    */
12757706df26Smrg{
12767706df26Smrg#ifdef PROFILE
12777706df26Smrg  unsigned int start, stop;
12787706df26Smrg#endif
12797706df26Smrg  TGAPtr pTga = NULL;
12807706df26Smrg  CARD32 address = 0;
12817706df26Smrg  int length = 0;
12827706df26Smrg  TGA_DECL();
12837706df26Smrg
12847706df26Smrg  pTga = TGAPTR(pScrn);
12857706df26Smrg  TGA_GET_IOBASE();
12867706df26Smrg  TGA_GET_OFFSET();
12877706df26Smrg/*    ErrorF("TGASubsequentClippedSolidLine called\n"); */
12887706df26Smrg
12897706df26Smrg  address = FB_OFFSET(x1, y1);
12907706df26Smrg  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
12917706df26Smrg
12927706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_rop | pTga->depthflag, TGA_RASTEROP_REG);
12937706df26Smrg  TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag, TGA_MODE_REG);
12947706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
12957706df26Smrg
12967706df26Smrg  length = len;
12977706df26Smrg  TGA_FAST_WRITE_REG((err << 15) | (length & 0xF), TGA_BRES3_REG);
12987706df26Smrg
12997706df26Smrg  while(length > 0) {
13007706df26Smrg    TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_CONTINUE_REG);
13017706df26Smrg    if(length > 16 && length % 16)
13027706df26Smrg	length -= length % 16;
13037706df26Smrg    else
13047706df26Smrg	length -= 16;
13057706df26Smrg  }
13067706df26Smrg
13077706df26Smrg  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
13087706df26Smrg  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
13097706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
13107706df26Smrg
13117706df26Smrg  TGA_SAVE_OFFSET();
13127706df26Smrg
13137706df26Smrg  return;
13147706df26Smrg
13157706df26Smrg}
13167706df26Smrg
13177706df26Smrgvoid
13187706df26SmrgTGASetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
13197706df26Smrg		      unsigned int planemask, int length,
13207706df26Smrg		      unsigned char *pattern)
13217706df26Smrg{
13227706df26Smrg#ifdef PROFILE
13237706df26Smrg  unsigned int start = 0, stop = 0;
13247706df26Smrg#endif
13257706df26Smrg  TGAPtr pTga = NULL;
13267706df26Smrg  unsigned int color1 = 0, color2 = 0, pmask = 0;
13277706df26Smrg  TGA_DECL();
13287706df26Smrg
13297706df26Smrg  pTga = TGAPTR(pScrn);
13307706df26Smrg  TGA_GET_IOBASE();
13317706df26Smrg  TGA_GET_OFFSET();
13327706df26Smrg/*    ErrorF("TGASetupForDashedLine called\n"); */
13337706df26Smrg
13347706df26Smrg  if(pTga->depthflag == BPP8PACKED) {
13357706df26Smrg    color1 = fg | (fg << 8) | (fg << 16) | (fg << 24);
13367706df26Smrg    color2 = bg | (bg << 8) | (bg << 16) | (bg << 24);
13377706df26Smrg    pmask = planemask | (planemask << 8) | (planemask << 16)
13387706df26Smrg      | (planemask << 24);
13397706df26Smrg  }
13407706df26Smrg  else {
13417706df26Smrg    color1 = fg;
13427706df26Smrg    color2 = fg;
13437706df26Smrg    pmask = planemask;
13447706df26Smrg  }
13457706df26Smrg
13467706df26Smrg  pTga->current_rop = rop | pTga->depthflag;
13477706df26Smrg  TGA_FAST_WRITE_REG(color1, TGA_FOREGROUND_REG);
13487706df26Smrg  pTga->current_planemask = pmask;
13497706df26Smrg  if(bg == -1) /* transparent line */
13507706df26Smrg    pTga->transparent_pattern_p = 1;
13517706df26Smrg  else {
13527706df26Smrg    pTga->transparent_pattern_p = 0;
13537706df26Smrg    TGA_FAST_WRITE_REG(color2, TGA_BACKGROUND_REG);
13547706df26Smrg  }
13557706df26Smrg
13567706df26Smrg  pTga->line_pattern = pattern[0] | (pattern[1] << 8);
13577706df26Smrg  pTga->line_pattern_length = length;
13587706df26Smrg
13597706df26Smrg  TGA_FAST_WRITE_REG(pScrn->displayWidth, TGA_WIDTH_REG);
13607706df26Smrg  TGA_SAVE_OFFSET();
13617706df26Smrg
13627706df26Smrg  return;
13637706df26Smrg}
13647706df26Smrg
13657706df26Smrgvoid
13667706df26SmrgTGASubsequentDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
13677706df26Smrg				int y2, int octant, int flags, int phase)
13687706df26Smrg{
13697706df26Smrg#ifdef PROFILE
13707706df26Smrg  unsigned int start, stop;
13717706df26Smrg#endif
13727706df26Smrg  TGAPtr pTga = NULL;
13737706df26Smrg  CARD32 abs_dx = 0, abs_dy = 0, address = 0, octant_reg = 0;
13747706df26Smrg  int length = 0;
13757706df26Smrg  CARD16 line_mask = 0;
13767706df26Smrg  int pattern_overflow = 0;
13777706df26Smrg  int l = 0;
13787706df26Smrg  TGA_DECL();
13797706df26Smrg
13807706df26Smrg  pTga = TGAPTR(pScrn);
13817706df26Smrg  TGA_GET_IOBASE();
13827706df26Smrg  TGA_GET_OFFSET();
13837706df26Smrg/*    ErrorF("TGASubsequentDashedLine called\n"); */
13847706df26Smrg
13857706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
13867706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
13877706df26Smrg  if(pTga->transparent_pattern_p)
13887706df26Smrg    TGA_FAST_WRITE_REG(TRANSPARENTLINE | X11 | pTga->depthflag |
13897706df26Smrg		       ((flags & OMIT_LAST) ? 0x0 : CAP_ENDS),
13907706df26Smrg		       TGA_MODE_REG);
13917706df26Smrg  else
13927706df26Smrg    TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag |
13937706df26Smrg		       ((flags & OMIT_LAST) ? 0x0 : CAP_ENDS),
13947706df26Smrg		       TGA_MODE_REG);
13957706df26Smrg
13967706df26Smrg  address = FB_OFFSET(x1, y1);
13977706df26Smrg  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
13987706df26Smrg  abs_dx = abs(x2 - x1);
13997706df26Smrg  abs_dy = abs(y2 - y1);
14007706df26Smrg  if(abs_dx > abs_dy)
14017706df26Smrg    length = abs_dx;
14027706df26Smrg  else
14037706df26Smrg    length = abs_dy;
14047706df26Smrg
14057706df26Smrg  if(octant & YMAJOR) {
14067706df26Smrg      if(octant & YDECREASING) {
14077706df26Smrg	  if(octant & XDECREASING)
14087706df26Smrg	      octant_reg = TGA_SLOPE0_REG;
14097706df26Smrg	  else
14107706df26Smrg	      octant_reg = TGA_SLOPE2_REG;
14117706df26Smrg      }
14127706df26Smrg      else {
14137706df26Smrg	  if(octant & XDECREASING)
14147706df26Smrg	      octant_reg = TGA_SLOPE1_REG;
14157706df26Smrg	  else
14167706df26Smrg	      octant_reg = TGA_SLOPE3_REG;
14177706df26Smrg      }
14187706df26Smrg  }
14197706df26Smrg  else {
14207706df26Smrg      if(octant & YDECREASING) {
14217706df26Smrg	  if(octant & XDECREASING)
14227706df26Smrg	      octant_reg = TGA_SLOPE4_REG;
14237706df26Smrg	  else
14247706df26Smrg	      octant_reg = TGA_SLOPE6_REG;
14257706df26Smrg      }
14267706df26Smrg      else {
14277706df26Smrg	  if(octant & XDECREASING)
14287706df26Smrg	      octant_reg = TGA_SLOPE5_REG;
14297706df26Smrg	  else
14307706df26Smrg	      octant_reg = TGA_SLOPE7_REG;
14317706df26Smrg      }
14327706df26Smrg  }
14337706df26Smrg  /* set up our first pattern with phase.  Keep track of if we overflow the
14347706df26Smrg     pattern by pattern_overflow, and correct on the next write */
14357706df26Smrg
14367706df26Smrg  if(phase) {
14377706df26Smrg    line_mask = pTga->line_pattern >> phase;
14387706df26Smrg    l = (pTga->line_pattern_length - phase);
14397706df26Smrg  }
14407706df26Smrg  else {
14417706df26Smrg    line_mask = pTga->line_pattern;
14427706df26Smrg    l = pTga->line_pattern_length;
14437706df26Smrg  }
14447706df26Smrg
14457706df26Smrg  while(l < 16) {
14467706df26Smrg    line_mask |= pTga->line_pattern << l;
14477706df26Smrg    l += pTga->line_pattern_length;
14487706df26Smrg  }
14497706df26Smrg  pattern_overflow = l - 16;
14507706df26Smrg
14517706df26Smrg  TGA_FAST_WRITE_REG(line_mask, TGA_DATA_REG);
14527706df26Smrg
14537706df26Smrg  TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
14547706df26Smrg
14557706df26Smrg  if(length > 16 && length % 16)
14567706df26Smrg    length -= length % 16;
14577706df26Smrg  else
14587706df26Smrg    length -= 16;
14597706df26Smrg
14607706df26Smrg  while(length > 0) {
14617706df26Smrg
14627706df26Smrg    if(pattern_overflow) {
14637706df26Smrg      line_mask = pTga->line_pattern >> (pTga->line_pattern_length -
14647706df26Smrg					 pattern_overflow);
14657706df26Smrg      l = pattern_overflow;
14667706df26Smrg    }
14677706df26Smrg    else {
14687706df26Smrg      line_mask = pTga->line_pattern;
14697706df26Smrg      l = pTga->line_pattern_length;
14707706df26Smrg    }
14717706df26Smrg    while(l < 16) {
14727706df26Smrg      line_mask |= (pTga->line_pattern << l);
14737706df26Smrg      l += pTga->line_pattern_length;
14747706df26Smrg    }
14757706df26Smrg    pattern_overflow = l - 16;
14767706df26Smrg
14777706df26Smrg    TGA_FAST_WRITE_REG(line_mask, TGA_CONTINUE_REG);
14787706df26Smrg    length -= 16;
14797706df26Smrg  }
14807706df26Smrg
14817706df26Smrg  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
14827706df26Smrg  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
14837706df26Smrg  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
14847706df26Smrg
14857706df26Smrg  TGA_SAVE_OFFSET();
14867706df26Smrg
14877706df26Smrg  return;
14887706df26Smrg}
14897706df26Smrg
14907706df26Smrgvoid
14917706df26SmrgTGASubsequentClippedDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
14927706df26Smrg			      int err, int phase)
14937706df26Smrg{
14947706df26Smrg#ifdef PROFILE
14957706df26Smrg  unsigned int start, stop;
14967706df26Smrg#endif
14977706df26Smrg  TGAPtr pTga = NULL;
14987706df26Smrg  CARD32 address = 0;
14997706df26Smrg  int length = 0;
15007706df26Smrg  CARD16 line_mask = 0;
15017706df26Smrg  int pattern_overflow = 0;
15027706df26Smrg  int l = 0;
15037706df26Smrg  TGA_DECL();
15047706df26Smrg
15057706df26Smrg  pTga = TGAPTR(pScrn);
15067706df26Smrg  TGA_GET_IOBASE();
15077706df26Smrg  TGA_GET_OFFSET();
15087706df26Smrg  /*    ErrorF("TGASubsequentClippedDashedLine called\n"); */
15097706df26Smrg
15107706df26Smrg  address = FB_OFFSET(x1, y1);
15117706df26Smrg  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
15127706df26Smrg
15137706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
15147706df26Smrg  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
15157706df26Smrg
15167706df26Smrg  if(pTga->transparent_pattern_p)
15177706df26Smrg    TGA_FAST_WRITE_REG(TRANSPARENTLINE | X11 | pTga->depthflag, TGA_MODE_REG);
15187706df26Smrg  else
15197706df26Smrg    TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag, TGA_MODE_REG);
15207706df26Smrg
15217706df26Smrg  length = len;
15227706df26Smrg  TGA_FAST_WRITE_REG((err << 15) | (length & 0xF), TGA_BRES3_REG);
15237706df26Smrg
15247706df26Smrg
15257706df26Smrg  if(phase) {
15267706df26Smrg    line_mask = pTga->line_pattern >> phase;
15277706df26Smrg    l = (pTga->line_pattern_length - phase);
15287706df26Smrg  }
15297706df26Smrg  else {
15307706df26Smrg    line_mask = pTga->line_pattern;
15317706df26Smrg    l = pTga->line_pattern_length;
15327706df26Smrg  }
15337706df26Smrg
15347706df26Smrg  while(l < 16) {
15357706df26Smrg    line_mask |= pTga->line_pattern << l;
15367706df26Smrg    l += pTga->line_pattern_length;
15377706df26Smrg  }
15387706df26Smrg  pattern_overflow = l - 16;
15397706df26Smrg
15407706df26Smrg
15417706df26Smrg  while(length > 0) {
15427706df26Smrg    TGA_FAST_WRITE_REG(line_mask, TGA_CONTINUE_REG);
15437706df26Smrg
15447706df26Smrg    if(pattern_overflow) {
15457706df26Smrg      line_mask = pTga->line_pattern >> (pTga->line_pattern_length -
15467706df26Smrg					 pattern_overflow);
15477706df26Smrg      l = pattern_overflow;
15487706df26Smrg    }
15497706df26Smrg    else {
15507706df26Smrg      line_mask = pTga->line_pattern;
15517706df26Smrg      l = pTga->line_pattern_length;
15527706df26Smrg    }
15537706df26Smrg    while(l < 16) {
15547706df26Smrg      line_mask |= (pTga->line_pattern << l);
15557706df26Smrg      l += pTga->line_pattern_length;
15567706df26Smrg    }
15577706df26Smrg    pattern_overflow = l - 16;
15587706df26Smrg
15597706df26Smrg    if(length > 16 && length % 16)
15607706df26Smrg      length -= length % 16;
15617706df26Smrg    else
15627706df26Smrg      length -= 16;
15637706df26Smrg  }
15647706df26Smrg
15657706df26Smrg  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
15667706df26Smrg  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
15677706df26Smrg  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
15687706df26Smrg
15697706df26Smrg  TGA_SAVE_OFFSET();
15707706df26Smrg
15717706df26Smrg  return;
15727706df26Smrg}
1573