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