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