tga_accel.c revision 7706df26
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tga/tga_accel.c,v 1.15 2001/11/21 22:32:59 alanh Exp $ */
2
3/*
4 * Copyright 1996,1997 by Alan Hourihane, Wigan, England.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Alan Hourihane not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission.  Alan Hourihane makes no representations
13 * about the suitability of this software for any purpose.  It is provided
14 * "as is" without express or implied warranty.
15 *
16 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 *
24 * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
25 *
26 * DEC TGA accelerated options.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "fb.h"
34#include "micmap.h"
35#include "xf86.h"
36#include "xf86_OSproc.h"
37#include "xf86PciInfo.h"
38#include "xf86Pci.h"
39#include "xf86cmap.h"
40#include "mipointer.h"
41
42#include "mibstore.h"
43#include "miline.h"
44
45#include "tga_regs.h"
46#include "BT.h"
47#include "tga.h"
48
49/* defines */
50
51#define BLIT_FORWARDS 0
52#define BLIT_BACKWARDS 1
53#define USE_BLOCK_FILL 2
54#define USE_OPAQUE_FILL 3
55#define MIX_SRC 0x03
56
57#define CE_BUFSIZE 256
58
59#define FB_OFFSET(x, y) (((long)(y) * pScrn->displayWidth * (pTga->Bpp)) + (long)(x) * pTga->Bpp)
60
61/* prototypes */
62
63static void TGACopyLineForwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
64			 int y2, int w);
65static void TGACopyLineBackwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
66			  int y2, int w);
67extern void TGASync(ScrnInfoPtr pScrn);
68static void TGASetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
69			  unsigned int planemask);
70static void TGASubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h);
71static void TGASetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
72				   int rop, unsigned int planemask,
73				   int transparency_color);
74static void TGASubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
75				     int x2, int y2, int w, int h);
76static void TGASetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
77				   int fg, int bg, int rop,
78				   unsigned int planemask);
79static void TGASubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx,
80					 int paty, int x, int y, int w,
81					 int h);
82static void TGASetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
83							  int fg, int bg,
84							  int rop,
85							  unsigned int planemask);
86
87static void
88TGASubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
89						int x, int y, int w,
90						int h, int skipleft);
91static void
92TGASubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
93
94
95/*
96 * The following function sets up the supported acceleration. Call it
97 * from the FbInit() function in the SVGA driver.
98 */
99Bool
100DEC21030AccelInit(ScreenPtr pScreen)
101{
102  XAAInfoRecPtr TGA_AccelInfoRec;
103  BoxRec AvailFBArea;
104  ScrnInfoPtr pScrn;
105  TGAPtr pTga;
106
107  pScrn = xf86Screens[pScreen->myNum];
108  pTga = TGAPTR(pScrn);
109
110  /*  ErrorF("DEC21030AccelInit called!"); */
111
112  /* first, create the XAAInfoRec */
113  TGA_AccelInfoRec = XAACreateInfoRec();
114
115  /*  ErrorF("XAACreateInfoRec called"); */
116
117  if(pScrn->depth == 8) {
118    pTga->depthflag = BPP8PACKED;
119    pTga->Bpp = 1;
120  } else {
121    pTga->depthflag = BPP24;
122    pTga->Bpp = 4;
123  }
124
125  TGA_AccelInfoRec->Flags =  PIXMAP_CACHE | LINEAR_FRAMEBUFFER |
126    OFFSCREEN_PIXMAPS;
127
128  TGA_AccelInfoRec->Sync = TGASync;
129
130  /* solid fill */
131
132  TGA_AccelInfoRec->SolidFillFlags = 0;
133  TGA_AccelInfoRec->SetupForSolidFill = TGASetupForSolidFill;
134  TGA_AccelInfoRec->SubsequentSolidFillRect = TGASubsequentSolidFillRect;
135
136  /* screen to screen copy */
137  TGA_AccelInfoRec->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
138  TGA_AccelInfoRec->SetupForScreenToScreenCopy =
139    TGASetupForScreenToScreenCopy;
140  TGA_AccelInfoRec->SubsequentScreenToScreenCopy =
141    TGASubsequentScreenToScreenCopy;
142
143  /* mono 8x8 pattern fill */
144
145  TGA_AccelInfoRec->Mono8x8PatternFillFlags =
146    HARDWARE_PATTERN_PROGRAMMED_BITS | BIT_ORDER_IN_BYTE_LSBFIRST;
147  TGA_AccelInfoRec->SetupForMono8x8PatternFill =
148    TGASetupForMono8x8PatternFill;
149  TGA_AccelInfoRec->SubsequentMono8x8PatternFillRect =
150    TGASubsequentMono8x8PatternFillRect;
151
152  /* color expand */
153  /* does not work for 32bpp (yet) */
154  TGA_AccelInfoRec->ScanlineCPUToScreenColorExpandFillFlags =
155    BIT_ORDER_IN_BYTE_LSBFIRST;
156
157  TGA_AccelInfoRec->NumScanlineColorExpandBuffers = 1;
158  pTga->buffers[0] = (CARD32 *)xnfalloc(CE_BUFSIZE);
159  TGA_AccelInfoRec->ScanlineColorExpandBuffers =
160    (unsigned char **)pTga->buffers;
161  TGA_AccelInfoRec->SetupForScanlineCPUToScreenColorExpandFill =
162    TGASetupForScanlineCPUToScreenColorExpandFill;
163  TGA_AccelInfoRec->SubsequentScanlineCPUToScreenColorExpandFill =
164    TGASubsequentScanlineCPUToScreenColorExpandFill;
165  TGA_AccelInfoRec->SubsequentColorExpandScanline =
166    TGASubsequentColorExpandScanline;
167
168  /* lines */
169
170  TGA_AccelInfoRec->PolylinesThinSolid = TGAPolyLines;
171  if(pTga->NoXaaPolySegment == FALSE)
172    TGA_AccelInfoRec->PolySegmentThinSolid = TGAPolySegment;
173  TGA_AccelInfoRec->PolylinesThinSolidFlags = 0x0;
174  TGA_AccelInfoRec->PolySegmentThinSolidFlags = 0x0;
175
176  TGA_AccelInfoRec->PolylinesThinDashed = TGAPolyLinesDashed;
177  if(pTga->NoXaaPolySegment == FALSE)
178    TGA_AccelInfoRec->PolySegmentThinDashed = TGAPolySegmentDashed;
179  TGA_AccelInfoRec->PolylinesThinDashedFlags = 0x0;
180  TGA_AccelInfoRec->PolySegmentThinDashedFlags = 0x0;
181  TGA_AccelInfoRec->DashedLineFlags = LINE_PATTERN_LSBFIRST_LSBJUSTIFIED;
182  TGA_AccelInfoRec->DashPatternMaxLength = 16;
183
184  /* initialize the pixmap cache */
185
186  AvailFBArea.x1 = 0;
187  AvailFBArea.y1 = 0; /* these gotta be 0 */
188  AvailFBArea.x2 = pScrn->displayWidth;
189  AvailFBArea.y2 = (pScrn->videoRam * 1024) / (pScrn->displayWidth *
190					       pTga->Bpp);
191  xf86InitFBManager(pScreen, &AvailFBArea);
192
193  TGA_AccelInfoRec->PixmapCacheFlags = 0;
194
195  /* initialize XAA */
196  return(XAAInit(pScreen, TGA_AccelInfoRec));
197}
198
199static void
200TGASetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
201					      int fg, int bg, int rop,
202					      unsigned int planemask)
203{
204#ifdef PROFILE
205    unsigned int start, stop;
206#endif
207    TGAPtr pTga = NULL;
208    unsigned int fgcolor = 0, bgcolor = 0, pmask = 0;
209    TGA_DECL();
210
211    pTga = TGAPTR(pScrn);
212    TGA_GET_IOBASE();
213    TGA_GET_OFFSET();
214
215/*      ErrorF("TGASetupForScanlineCPUToScreenColorExpandFill called\n"); */
216    if(pTga->depthflag == BPP8PACKED) {
217      fgcolor = (fg | (fg << 8) | (fg << 16) | (fg << 24));
218      bgcolor = bg | (bg << 8) | (bg << 16) | (bg << 24);
219      pmask = planemask | (planemask << 8) | (planemask << 16)
220	| (planemask << 24);
221    }
222    else {
223      bgcolor = bg;
224      fgcolor = fg;
225      pmask = planemask;
226    }
227    pTga->current_rop = rop | pTga->depthflag;
228
229    if(bg == -1) {
230	pTga->transparent_pattern_p = 1;
231	if(rop == MIX_SRC) {
232	  pTga->block_or_opaque_p = USE_BLOCK_FILL;
233	  TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
234	  TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
235	  if(pTga->depthflag == BPP24) {
236	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
237	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
238	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
239	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
240	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
241	    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
242	  }
243	}
244	else {
245	  pTga->block_or_opaque_p = USE_OPAQUE_FILL;
246	  TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
247	}
248    }
249    else {
250	pTga->transparent_pattern_p = 0;
251	TGA_FAST_WRITE_REG(bgcolor, TGA_BACKGROUND_REG);
252	TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
253    }
254    TGA_FAST_WRITE_REG(pmask, TGA_PLANEMASK_REG); /* we know when to
255						     reset this */
256    TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
257
258    TGA_SAVE_OFFSET();
259
260    return;
261}
262
263static void
264TGASubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
265						int x, int y, int w,
266						int h, int skipleft)
267{
268#ifdef PROFILE
269    unsigned int start, stop;
270#endif
271    TGAPtr pTga;
272    TGA_DECL();
273
274    pTga = TGAPTR(pScrn);
275    TGA_GET_IOBASE();
276    TGA_GET_OFFSET();
277
278/*      ErrorF("TGASubsequentScanlineCPUToScreenColorExpandFill called\n"); */
279/*      ErrorF("w = %d, h = %d\n", w, h); */
280
281    pTga->ce_height = h;
282    pTga->ce_width = w;
283    pTga->ce_x = x;
284    pTga->ce_y = y;
285    pTga->ce_skipleft = skipleft;
286/*      ErrorF("skipleft is %d\n", skipleft); */
287
288    if(pTga->transparent_pattern_p) {
289	if(pTga->block_or_opaque_p == USE_BLOCK_FILL)
290	    TGA_FAST_WRITE_REG(BLOCKSTIPPLE | X11 | pTga->depthflag,
291			       TGA_MODE_REG);
292	else
293	    TGA_FAST_WRITE_REG(TRANSPARENTSTIPPLE | X11 | pTga->depthflag,
294			       TGA_MODE_REG);
295/*  	ErrorF("transparent stipple with x = %d, y = %d, w = %d, h = %d\n", */
296/*  	       x, y, w, h); */
297    }
298    else
299	TGA_FAST_WRITE_REG(OPAQUESTIPPLE | X11 | pTga->depthflag,
300			   TGA_MODE_REG);
301
302    TGA_SAVE_OFFSET();
303    return;
304}
305
306static void
307TGASubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
308{
309#ifdef PROFILE
310    unsigned int start, stop;
311#endif
312    TGAPtr pTga;
313    unsigned char *p = NULL;
314    int width = 0;
315    unsigned int addr;
316    unsigned int pixelmask = 0;
317    unsigned int stipple;
318    unsigned int align_mask;
319    int align = 0;
320    int skipleft;
321
322    CARD32 c = 0, d = 0;
323    CARD32 *e = NULL;
324    int i = 0, num_dwords = 0;
325    TGA_DECL();
326
327    pTga = TGAPTR(pScrn);
328    TGA_GET_IOBASE();
329    TGA_GET_OFFSET();
330
331    align_mask = (pTga->depthflag == BPP24) ? 0x0f : 0x03;
332
333#if 0
334    ErrorF("TGASubsequentColorExpandScanline called\n");
335    if(pTga->transparent_pattern_p)
336      ErrorF("transparent color expand\n");
337#endif
338
339    p = (unsigned char *)pTga->buffers[0];
340    addr = FB_OFFSET(pTga->ce_x, pTga->ce_y);
341    width = pTga->ce_width;
342    skipleft = pTga->ce_skipleft;
343
344    while(width > 0) {
345	if(!pTga->transparent_pattern_p)
346	    pixelmask = 0xFFFFFFFF;
347
348	align = (addr & align_mask) / pTga->Bpp; /* no. pixels out of align */
349	if (align) {
350	    if (!pTga->transparent_pattern_p)
351		pixelmask <<= align;
352/*  	    ErrorF("alignment is %d\n", align); */
353	    addr -= align * pTga->Bpp;
354	    width += align;
355
356	    e = (CARD32 *)p;
357	    num_dwords = (width / 32) + 1;
358	    if(num_dwords > (CE_BUFSIZE / 4)) { /* shouldn't happen */
359		ErrorF("TGASubsequentColorExpandScanline passed scanline %d bytes long, truncating\n", num_dwords * 4);
360		num_dwords = CE_BUFSIZE / 4;
361	    }
362	    for(i = 0; i < num_dwords; i++) {
363		c = e[i];
364		if(i == 0)
365		    e[i] = c << align;
366		else
367		    e[i] = (d >> (32 - align)) | (c << align);
368		d = c;
369	    }
370	}
371
372	if (!pTga->transparent_pattern_p) {
373	    if (skipleft) {
374		pixelmask <<= skipleft;
375		skipleft = 0;
376	    }
377	    if (width < 32) {
378		pixelmask &= (0xFFFFFFFF >> (32 - width));
379	    }
380	    TGA_FAST_WRITE_REG(pixelmask, TGA_PIXELMASK_REG);
381	}
382	else {
383	    unsigned int *i = NULL;
384
385/*  	    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); */
386	    if (skipleft) {
387		i = (unsigned int *)p;
388		*i &= (0xFFFFFFFF << skipleft);
389		skipleft = 0;
390	    }
391	    if (width < 32) {
392		i = (unsigned int *)p;
393		*i &= (0xFFFFFFFF >> (32 - width));
394	    }
395	}
396
397	stipple = *((unsigned int *)p);
398	switch (pTga->Chipset) {
399	case PCI_CHIP_TGA2:
400	    *(unsigned int *)(pTga->FbBase + addr) = stipple; WMB;
401	    break;
402	case PCI_CHIP_DEC21030:
403	    TGA_FAST_WRITE_REG(addr, TGA_ADDRESS_REG);
404	    TGA_FAST_WRITE_REG(stipple, TGA_CONTINUE_REG);
405	}
406	addr += 32 * pTga->Bpp;
407	p += 4;
408	width -= 32;
409    }
410    pTga->ce_height--;
411    if(pTga->ce_height == 0) {
412	TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag,
413			   TGA_MODE_REG);
414	TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
415	TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
416    }
417    else
418	pTga->ce_y += 1;
419
420    TGA_SAVE_OFFSET();
421    return;
422}
423
424/* Block Fill mode is faster, but only works for certain rops.  So we will
425   have to implement Opaque Fill anyway, so we will do that first, then
426   do Block Fill for the special cases
427*/
428void
429TGASetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
430		     unsigned int planemask)
431{
432#ifdef PROFILE
433  unsigned int start, stop;
434#endif
435  TGAPtr pTga;
436  unsigned int fgcolor = 0, pmask = 0;
437  TGA_DECL();
438
439  pTga = TGAPTR(pScrn);
440  TGA_GET_IOBASE();
441  TGA_GET_OFFSET();
442  /*  ErrorF("TGASetupForSolidFill called"); */
443
444  if(pTga->depthflag == BPP8PACKED) {
445    fgcolor = color | (color << 8) | (color << 16) | (color << 24);
446    pmask = planemask | (planemask << 8) | (planemask << 16) |
447		     (planemask << 24);
448  }
449  else {
450    fgcolor = color;
451    pmask = planemask;
452  }
453
454
455  if(rop == MIX_SRC) { /* we can just do a block copy */
456    pTga->block_or_opaque_p = USE_BLOCK_FILL;
457    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
458    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
459    if(pTga->depthflag == BPP24) {
460      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
461      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
462      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
463      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
464      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
465      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
466    }
467  }
468  else {
469    pTga->block_or_opaque_p = USE_OPAQUE_FILL;
470    pTga->current_rop = rop | pTga->depthflag;
471    TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
472/*      ErrorF("opaque fill called\n"); */
473  }
474
475  pTga->current_planemask = pmask;
476  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_DATA_REG);
477  TGA_SAVE_OFFSET();
478  return;
479}
480
481void
482TGASubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
483{
484  unsigned int mode_reg = 0;
485  int i = 0;
486  unsigned int pixel_count = 0; /* the actual # of pixels to be written */
487  unsigned int write_data = 0; /* the actual data written */
488  int a1 = 0;
489#ifdef PROFILE
490  unsigned int stop, start;
491#endif
492  TGAPtr pTga;
493  TGA_DECL();
494
495  pTga = TGAPTR(pScrn);
496  TGA_GET_IOBASE();
497  TGA_GET_OFFSET();
498
499  /*  ErrorF("TGASubsequentFillRectSolid called\n"); */
500
501  if(pTga->block_or_opaque_p == USE_OPAQUE_FILL) {
502    mode_reg = OPAQUEFILL | X11 | pTga->depthflag;
503    TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
504    /* we have to set this to GXCOPY every time before we exit */
505  }
506  else
507    mode_reg = BLOCKFILL | X11 | pTga->depthflag;
508
509  TGA_FAST_WRITE_REG(mode_reg, TGA_MODE_REG);
510  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
511
512  if(w > 2048) {
513    ErrorF("TGASubsequentSolidFillRect called with w = %d, truncating.\n", w);
514    w = 2048;
515  }
516  pixel_count = w - 1;
517
518  for(i = 0; i < h; i++) {
519    a1 = FB_OFFSET(x, y + i);
520    if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
521      TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
522    write_data = pixel_count;
523    TGA_FAST_WRITE_REG(a1, TGA_ADDRESS_REG);
524    TGA_FAST_WRITE_REG(write_data, TGA_CONTINUE_REG);
525  }
526
527  mode_reg = SIMPLE | X11 | pTga->depthflag;
528  TGA_FAST_WRITE_REG(mode_reg, TGA_MODE_REG);
529  if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
530    TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag,
531		       TGA_RASTEROP_REG); /* GXCOPY */
532  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
533
534  TGA_SAVE_OFFSET();
535  return;
536}
537
538/* we only need to calculate the direction of a move once per move,
539   so we do it in the setup function and leave it */
540
541void
542TGASetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
543			      int rop, unsigned int planemask,
544			      int transparency_color)
545    /* xdir 1 = left-to-right, -1 = right to left
546       ydir 1 = top-to-bottom, -1 = bottom to top
547    */
548{
549#ifdef PROFILE
550  unsigned int start, stop;
551#endif
552  TGAPtr pTga;
553  unsigned int pmask = 0;
554  TGA_DECL();
555
556  pTga = TGAPTR(pScrn);
557  TGA_GET_IOBASE();
558  TGA_GET_OFFSET();
559
560  /* see section 6.2.9 */
561
562  if (pTga->depthflag == BPP8PACKED) {
563    pmask = planemask | (planemask << 8) | (planemask << 16) |
564		 (planemask << 24);
565  }
566  else
567    pmask = planemask;
568
569  pTga->current_planemask = pmask;
570  TGA_FAST_WRITE_REG(pmask, TGA_PLANEMASK_REG);
571
572  pTga->current_rop = rop | pTga->depthflag;
573
574  /* do we copy a rectangle from top to bottom or bottom to top? */
575  if (ydir == -1) {
576    pTga->blitdir = BLIT_FORWARDS;
577  }
578  else {
579    pTga->blitdir = BLIT_BACKWARDS;
580  }
581  TGA_SAVE_OFFSET();
582  return;
583}
584
585/*
586 * This is the implementation of the SubsequentForScreenToScreenCopy
587 * that sends commands to the coprocessor to perform a screen-to-screen
588 * copy of the specified areas, with the parameters from the SetUp call.
589 */
590void
591TGASubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
592				int y2, int w, int h)
593{
594  /* x1, y1 = source coords
595     x2, y2 = destination coords
596     w = width
597     h = height
598  */
599
600  int i = 0;
601  void (*copy_func)(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w);
602#ifdef PROFILE
603  unsigned int stop, start;
604#endif
605  TGAPtr pTga;
606  TGA_DECL();
607
608  pTga = TGAPTR(pScrn);
609  TGA_GET_IOBASE();
610  TGA_GET_OFFSET();
611#if 0
612  ErrorF("TGASubsequentScreenToScreenCopy(,%d,%d,%d,%d,%d,%d):"
613	 " COPY %s BLIT %s\n",
614	 x1, y1, x2, y2, w, h, (x2 > x1 && (x1 + w) > x2)?"BWD":"FWD",
615	 (pTga->blitdir == BLIT_FORWARDS)?"FWD":"BWD");
616#endif
617  TGASync(pScrn); /* ?? */
618
619  TGA_FAST_WRITE_REG(COPY | X11 | pTga->depthflag, TGA_MODE_REG);
620  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
621  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
622
623  if(x2 > x1 && (x1 + w) > x2)
624    copy_func = TGACopyLineBackwards;
625  else
626    copy_func = TGACopyLineForwards;
627
628  TGA_SAVE_OFFSET();
629  if(pTga->blitdir == BLIT_FORWARDS) {
630    for(i = h - 1; i >= 0; i--) { /* copy from bottom to top */
631      (*copy_func)(pScrn, x1, y1 + i, x2, y2 + i, w);
632    }
633  }
634  else {
635    for(i = 0; i < h; i++) {
636      (*copy_func)(pScrn, x1, y1 + i, x2, y2 + i, w);
637    }
638  }
639
640  TGASync(pScrn); /* ?? */
641
642  TGA_GET_OFFSET();
643  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
644  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
645  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
646  TGA_SAVE_OFFSET();
647
648  return;
649}
650
651
652void
653TGACopyLineForwards(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w)
654{
655  /* copy a line of width w from x1,y1 to x2,y2 using copy mode */
656  int read;
657  unsigned long source_address, destination_address;
658  unsigned int mask_source, mask_destination;
659  int cando;
660  unsigned int cando_mask;
661  int source_align, destination_align;
662  int pixel_shift;
663#ifdef PROFILE
664  unsigned int start, stop;
665#endif
666  TGAPtr pTga;
667  TGA_DECL();
668
669  pTga = TGAPTR(pScrn);
670  TGA_GET_IOBASE();
671  TGA_GET_OFFSET();
672
673  cando = 32;
674  cando_mask = 0xFFFFFFFFU;
675  if (pTga->Chipset == PCI_CHIP_DEC21030 && pTga->depthflag == BPP24) {
676    cando = 16;
677    cando_mask = 0x0000FFFFU;
678  }
679
680  source_address = FB_OFFSET(x1, y1);
681  destination_address = FB_OFFSET(x2, y2);
682#if 0
683  ErrorF("CPY-FWD(,%d,%d,%d,%d,%d): sadr = 0x%lx, dadr = 0x%lx\n",
684	 x1, y1, x2, y2, w, source_address, destination_address);
685#endif
686  read = 0;
687  while (read < w) {
688
689    mask_source = cando_mask;
690    if ((w - read) >= cando)
691      mask_destination = cando_mask;
692    else
693      mask_destination = cando_mask >> (cando - (w - read));
694
695    source_align = source_address & 0x07;
696    source_address -= source_align;
697    mask_source <<= source_align / pTga->Bpp;
698    /*    mask_source &= cando_mask; */
699
700    destination_align = destination_address & 0x07;
701    destination_address -= destination_align;
702    mask_destination <<= destination_align / pTga->Bpp;
703    /*    mask_destination &= cando_mask; */
704
705    if (destination_align >= source_align)
706      pixel_shift = destination_align - source_align;
707    else {
708      pixel_shift = 8 - (source_align - destination_align);
709      /* we need to prime the residue register in this case */
710      destination_address -= 8;
711      mask_destination <<= 8 / pTga->Bpp;
712      mask_destination &= cando_mask;/* ?? */
713    }
714
715    TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
716    switch (pTga->Chipset) {
717    case PCI_CHIP_TGA2:
718        *(unsigned int *)(pTga->FbBase + source_address) = mask_source; WMB;
719	*(unsigned int *)(pTga->FbBase + destination_address) = mask_destination; WMB;
720	break;
721    case PCI_CHIP_DEC21030:
722        /* use GADR and GCTR */
723        TGA_FAST_WRITE_REG(source_address, TGA_ADDRESS_REG);
724	TGA_FAST_WRITE_REG(mask_source, TGA_CONTINUE_REG);
725	TGA_FAST_WRITE_REG(destination_address, TGA_ADDRESS_REG);
726	TGA_FAST_WRITE_REG(mask_destination, TGA_CONTINUE_REG);
727	break;
728    }
729
730    source_address += (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
731    destination_address += cando * pTga->Bpp;
732
733    read += cando;
734    read -= destination_align / pTga->Bpp; /* "read" is perhaps better
735				    called "written"... */
736    if (destination_align < source_align) {
737      read -= 8 / pTga->Bpp;
738    }
739  }
740
741  TGA_SAVE_OFFSET();
742  return;
743}
744
745
746void
747TGACopyLineBackwards(ScrnInfoPtr pScrn, int x1, int y1, int x2,
748			  int y2, int w)
749     /* x1, y1 = source
750	x2, y2 = destination
751	w = width
752     */
753{
754  unsigned long a1, a2;
755  unsigned long source_address, destination_address;
756  unsigned int mask_source, mask_destination;
757  int cando;
758  unsigned int cando_mask;
759  int source_align, destination_align;
760  int pixel_shift;
761  int read;
762#ifdef PROFILE
763  unsigned int start, stop;
764#endif
765  TGAPtr pTga;
766  TGA_DECL();
767
768  pTga = TGAPTR(pScrn);
769  TGA_GET_IOBASE();
770  TGA_GET_OFFSET();
771
772  cando = 32;
773  cando_mask = 0xFFFFFFFFU;
774  if (pTga->Chipset == PCI_CHIP_DEC21030 && pTga->depthflag == BPP24) {
775    cando = 16;
776    cando_mask = 0x0000FFFFU;
777  }
778
779  a1 = FB_OFFSET(x1, y1);
780  a2 = FB_OFFSET(x2, y2);
781
782  source_address = FB_OFFSET((x1 + w) - cando, y1);
783  destination_address = FB_OFFSET((x2 + w) - cando, y2);
784
785#if 0
786  ErrorF("CPY-BWD(,%d,%d,%d,%d,%d): sadr = 0x%lx, dadr = 0x%lx"
787	 " a1 0x%lx a2 0x%lx\n",
788	 x1, y1, x2, y2, w, source_address, destination_address, a1, a2);
789#endif
790
791  read = 0;
792  while (read < w) {
793    mask_source = cando_mask;
794    if ((w - read) >= cando)
795      mask_destination = cando_mask;
796    else {
797      mask_destination = ((unsigned int)cando_mask) << (cando - (w - read));
798      mask_destination &= cando_mask; /* esp. for cando==16 */
799    }
800
801    source_align = source_address & 0x07;
802    destination_align = destination_address & 0x07;
803
804    if (read == 0 && destination_align &&
805       (source_align > destination_align)) {
806      /* we want to take out all the destination_align pixels in one
807	 little copy first, then move on to the main stuff */
808      unsigned long tmp_src, tmp_dest;
809      unsigned int tmp_src_mask, tmp_dest_mask;
810
811      tmp_src = a1 + (w - (source_align / pTga->Bpp)) * pTga->Bpp;
812      tmp_dest = a2 + (w - (destination_align / pTga->Bpp) - (8 / pTga->Bpp)) * pTga->Bpp;
813      tmp_src_mask = cando_mask;
814      tmp_dest_mask = ((unsigned int)0x000000FF) >> (8 - destination_align) / pTga->Bpp;
815      tmp_dest_mask <<= 8 / pTga->Bpp;
816      pixel_shift = (8 - source_align) + destination_align;
817#if 0
818      ErrorF("CPY-BWD - preliminary copy: sa = %d, da = %d, ps =%d\n",
819	     source_align, destination_align, pixel_shift);
820#endif
821      TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
822      switch (pTga->Chipset)
823      {
824      case PCI_CHIP_TGA2:
825	  *(unsigned int *)(pTga->FbBase + tmp_src) = tmp_src_mask; WMB;
826	  *(unsigned int *)(pTga->FbBase + tmp_dest) = tmp_dest_mask; WMB;
827	  break;
828      case PCI_CHIP_DEC21030:
829	  /* use GADR and GCTR */
830	  TGA_FAST_WRITE_REG(tmp_src, TGA_ADDRESS_REG);
831	  TGA_FAST_WRITE_REG(tmp_src_mask, TGA_CONTINUE_REG);
832	  TGA_FAST_WRITE_REG(tmp_dest, TGA_ADDRESS_REG);
833	  TGA_FAST_WRITE_REG(tmp_dest_mask, TGA_CONTINUE_REG);
834	  break;
835      }
836
837      source_address += (8 - source_align);
838      mask_source >>= (8 - source_align) / pTga->Bpp;
839      mask_source >>= destination_align / pTga->Bpp;
840      mask_destination >>= destination_align / pTga->Bpp;
841    }
842    else if (read == 0 && (source_align != destination_align)) {
843      source_address += (8 - source_align);
844      /*    	mask_source >>= (8 - source_align); */
845      /* if we uncomment this, it breaks...TGA tries to
846	 optimize away a read of our last pixels... */
847    }
848    else if (source_align) {
849      source_address += (8 - source_align);
850      mask_source >>= (8 - source_align) / pTga->Bpp;
851    }
852
853    if (destination_align) {
854      destination_address += (8 - destination_align);
855      mask_destination >>= (8 - destination_align) / pTga->Bpp;
856    }
857
858    if (destination_align >= source_align)
859      pixel_shift = destination_align - source_align;
860    else {
861      pixel_shift = (8 - source_align) + destination_align;
862      if (destination_align) {
863	source_address += 8;
864	mask_source >>= 8 / pTga->Bpp;
865      }
866    }
867
868#if 0
869    ErrorF("CPY-BWD - normal: sadr 0x%lx sm 0x%x dadr 0x%lx dm 0x%x"
870	   " sa %d da %d ps %d read %d\n",
871	   source_address, mask_source,
872	   destination_address, mask_destination,
873	   source_align, destination_align, pixel_shift, read);
874#endif
875    TGA_FAST_WRITE_REG(pixel_shift, TGA_PIXELSHIFT_REG);
876    switch (pTga->Chipset) {
877    case PCI_CHIP_TGA2:
878        *(unsigned int *)(pTga->FbBase + source_address) = mask_source; WMB;
879	*(unsigned int *)(pTga->FbBase + destination_address) = mask_destination; WMB;
880	break;
881    case PCI_CHIP_DEC21030:
882        /* use GADR and GCTR */
883        TGA_FAST_WRITE_REG(source_address, TGA_ADDRESS_REG);
884	TGA_FAST_WRITE_REG(mask_source, TGA_CONTINUE_REG);
885	TGA_FAST_WRITE_REG(destination_address, TGA_ADDRESS_REG);
886	TGA_FAST_WRITE_REG(mask_destination, TGA_CONTINUE_REG);
887	break;
888    }
889
890/*      if(read == 0) */
891/*        ErrorF("sa = %d, da = %d, ps = %d\n", source_align, destination_align, */
892/*      	     pixel_shift); */
893
894    if (destination_align > source_align) {
895      source_address -= cando * pTga->Bpp - 8;
896      destination_address -= (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
897      if (read == 0)
898	read += (cando - 8 / pTga->Bpp) + source_align / pTga->Bpp;
899      else
900	read += cando - 8 / pTga->Bpp;
901    }
902    else if (destination_align == source_align) {
903      source_address -= cando * pTga->Bpp;
904      destination_address -= cando * pTga->Bpp;
905      if (read == 0 && destination_align)
906	read += (cando - (8 - destination_align) / pTga->Bpp);
907      else
908	read += cando;
909    }
910    else if (source_align > destination_align) {
911      source_address -= cando * pTga->Bpp - 8;
912      destination_address -= (cando - (pixel_shift / pTga->Bpp)) * pTga->Bpp;
913      /* only happens when read == 0 */
914      if (destination_align)
915	read += (cando - 16 / pTga->Bpp) + source_align / pTga->Bpp;
916      else
917	read += cando - pixel_shift / pTga->Bpp;
918    }
919  }
920
921  TGA_SAVE_OFFSET();
922  return;
923}
924
925void
926TGASetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
927			      int fg, int bg, int rop, unsigned int planemask)
928{
929#ifdef PROFILE
930  unsigned int start, stop;
931#endif
932  TGAPtr pTga;
933  unsigned int fgcolor = 0, bgcolor = 0, pmask = 0;
934  TGA_DECL();
935
936  pTga = TGAPTR(pScrn);
937  TGA_GET_IOBASE();
938  TGA_GET_OFFSET();
939
940/*    ErrorF("TGASetupForMono8x8PatternFill called with patx = %d, paty = %d, fg = %d, bg = %d, rop = %d, planemask = %d\n", */
941/*  	 patx, paty, fg, bg, rop, planemask);  */
942
943  if(bg == -1)  /* we are transparent */
944    pTga->transparent_pattern_p = 1;
945  else
946    pTga->transparent_pattern_p = 0;
947
948  if(rop == MIX_SRC)
949    pTga->block_or_opaque_p = USE_BLOCK_FILL;
950  else
951    pTga->block_or_opaque_p = USE_OPAQUE_FILL;
952
953  if(pTga->depthflag == BPP8PACKED) {
954    fgcolor = fg | (fg << 8) | (fg << 16) | (fg << 24);
955    bgcolor = bg | (bg << 8) | (bg << 16) | (bg << 24);
956    pmask = planemask | (planemask << 8) | (planemask << 16) |
957      (planemask << 24);
958  }
959  else {
960    fgcolor = fg;
961    bgcolor = bg;
962    pmask = planemask;
963  }
964
965
966  if(pTga->transparent_pattern_p &&
967     pTga->block_or_opaque_p == USE_BLOCK_FILL) {
968    /* we can use block fill mode to draw a transparent stipple */
969    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR0_REG);
970    TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR1_REG);
971    if(pTga->depthflag == BPP24) {
972      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR2_REG);
973      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR3_REG);
974      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR4_REG);
975      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR5_REG);
976      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR6_REG);
977      TGA_FAST_WRITE_REG(fgcolor, TGA_BLOCK_COLOR7_REG);
978    }
979  }
980  else if(pTga->transparent_pattern_p) {
981    TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
982  }
983  else {
984    TGA_FAST_WRITE_REG(bgcolor, TGA_BACKGROUND_REG);
985    TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
986    TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PIXELMASK_REG);
987  }
988  pTga->current_rop = rop;
989  pTga->current_planemask = pmask;
990  TGA_SAVE_OFFSET();
991  return;
992}
993
994void
995TGASubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
996				    int x, int y, int w, int h)
997/* patx and paty = first & second dwords of pattern to be rendered, packed */
998{
999  TGAPtr pTga;
1000  int i, j;
1001  unsigned int stipple_mask[8], align, tmp;
1002#ifdef PROFILE
1003  register unsigned int stop, start;
1004#endif
1005  TGA_DECL();
1006
1007
1008/*    ErrorF("TGASubsequentMono8x8PatternFillRect called with x = %d, y = %d, w = %d, h = %d\n", x, y, w, h); */
1009
1010  pTga = TGAPTR(pScrn);
1011  TGA_GET_IOBASE();
1012  TGA_GET_OFFSET();
1013
1014  if(w > 2048)
1015    ErrorF("TGASubsequentMono8x8PatternFillRect called with w > 2048, truncating\n");
1016  if(pTga->block_or_opaque_p == USE_OPAQUE_FILL)
1017    TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
1018
1019  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
1020  if(pTga->depthflag == BPP8PACKED)
1021    align = FB_OFFSET(x, y) % 4;
1022  else
1023    align = x % 4;
1024
1025  for(i = 0; i < 4; i++) {
1026    tmp = (patx >> (i * 8)) & 0xFF;
1027    stipple_mask[i] = (tmp | (tmp << 8) | (tmp << 16) | (tmp << 24));
1028  }
1029  for(i = 4; i < 8; i++) {
1030    tmp = (paty >> ((i - 4) * 8)) & 0xFF;
1031    stipple_mask[i] = (tmp | (tmp << 8) | (tmp << 16) | (tmp << 24));
1032  }
1033  if(align) { /* stipples must be aligned to four bytes */
1034    for(i = 0; i < 8; i++) {
1035      stipple_mask[i] = (stipple_mask[i] << align) |
1036	((stipple_mask[i] & 0xFF000000) >> (32 - align));
1037    }
1038  }
1039
1040  if((pTga->block_or_opaque_p == USE_BLOCK_FILL) && pTga->transparent_pattern_p) {
1041    /* use block fill */
1042    TGA_FAST_WRITE_REG(BLOCKFILL | X11 | pTga->depthflag, TGA_MODE_REG);
1043
1044    for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
1045      TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
1046      TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
1047      TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
1048    }
1049  }
1050  else if(pTga->transparent_pattern_p) {
1051    /* if we can't use block fill, we'll use transparent fill */
1052    TGA_FAST_WRITE_REG(TRANSPARENTFILL | X11 | pTga->depthflag, TGA_MODE_REG);
1053    for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
1054      TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
1055      TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
1056      TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
1057    }
1058  }
1059  else { /* use opaque fill mode */
1060/*      ErrorF("Using opaque fill mode\n"); */
1061    TGA_FAST_WRITE_REG(OPAQUEFILL | X11 | pTga->depthflag, TGA_MODE_REG);
1062    for(i = 0, j = 0; i < h; i++, (j == 7) ? (j = 0) : (j++)) {
1063      TGA_FAST_WRITE_REG(stipple_mask[j], TGA_DATA_REG);
1064      TGA_FAST_WRITE_REG(FB_OFFSET(x, y + i), TGA_ADDRESS_REG);
1065      TGA_FAST_WRITE_REG(w - 1, TGA_CONTINUE_REG);
1066    }
1067  }
1068
1069  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
1070  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
1071  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
1072
1073  TGA_SAVE_OFFSET();
1074
1075  return;
1076}
1077
1078void
1079TGASetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
1080		     unsigned int planemask)
1081{
1082#ifdef PROFILE
1083  unsigned int start, stop;
1084#endif
1085  TGAPtr pTga = NULL;
1086  unsigned int fgcolor = 0, pmask = 0;
1087  TGA_DECL();
1088
1089  pTga = TGAPTR(pScrn);
1090  TGA_GET_IOBASE();
1091  TGA_GET_OFFSET();
1092/*    ErrorF("TGASetupForSolidLine called\n"); */
1093
1094  if(pTga->depthflag == BPP8PACKED) {
1095    fgcolor = color | (color << 8) | (color << 16) | (color << 24);
1096    pmask = planemask | (planemask << 8) | (planemask << 16) |
1097      (planemask << 24);
1098  }
1099  else {
1100    fgcolor = color;
1101    pmask = planemask;
1102  }
1103
1104
1105  pTga->current_rop = rop | pTga->depthflag;
1106  TGA_FAST_WRITE_REG(fgcolor, TGA_FOREGROUND_REG);
1107  pTga->current_planemask = pmask;
1108  TGA_FAST_WRITE_REG(0xFFFF, TGA_DATA_REG);
1109  TGA_FAST_WRITE_REG(pScrn->displayWidth, TGA_WIDTH_REG);
1110  TGA_SAVE_OFFSET();
1111
1112  return;
1113}
1114
1115void
1116TGASubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
1117			      int dir)
1118{
1119  if(dir == DEGREES_0)  /* line is to the right */
1120      TGASubsequentSolidLine(pScrn, x, y, x + len, y, 0x0, OMIT_LAST);
1121  else if(dir == DEGREES_270) /* line is down */
1122      TGASubsequentSolidLine(pScrn, x, y, x, y + len, YMAJOR, OMIT_LAST);
1123  else
1124      ErrorF("TGASubsequentSolidHorVertLine passed dir %d!\n", dir);
1125
1126  return;
1127}
1128
1129void
1130TGASubsequentSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
1131		       int octant, int flags)
1132{
1133#ifdef PROFILE
1134  unsigned int start, stop;
1135#endif
1136  TGAPtr pTga = NULL;
1137  CARD32 abs_dx = 0, abs_dy = 0, address = 0, octant_reg = 0;
1138  int length = 0;
1139  TGA_DECL();
1140
1141  pTga = TGAPTR(pScrn);
1142  TGA_GET_IOBASE();
1143  TGA_GET_OFFSET();
1144/*    ErrorF("TGASubsequentSolidLine called\n"); */
1145
1146  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
1147  TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag |
1148		     ((flags & OMIT_LAST) ? 0x0 : CAP_ENDS), TGA_MODE_REG);
1149  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
1150
1151  address = FB_OFFSET(x1, y1);
1152  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
1153  abs_dx = abs(x2 - x1);
1154  abs_dy = abs(y2 - y1);
1155  if(octant & YMAJOR)
1156    length = abs_dy;
1157  else
1158    length = abs_dx;
1159
1160  if(octant & YMAJOR) {
1161      if(octant & YDECREASING) {
1162	  if(octant & XDECREASING)
1163	      octant_reg = TGA_SLOPE0_REG;
1164	  else
1165	      octant_reg = TGA_SLOPE2_REG;
1166      }
1167      else {
1168	  if(octant & XDECREASING)
1169	      octant_reg = TGA_SLOPE1_REG;
1170	  else
1171	      octant_reg = TGA_SLOPE3_REG;
1172      }
1173  }
1174  else {
1175      if(octant & YDECREASING) {
1176	  if(octant & XDECREASING)
1177	      octant_reg = TGA_SLOPE4_REG;
1178	  else
1179	      octant_reg = TGA_SLOPE6_REG;
1180      }
1181      else {
1182	  if(octant & XDECREASING)
1183	      octant_reg = TGA_SLOPE5_REG;
1184	  else
1185	      octant_reg = TGA_SLOPE7_REG;
1186      }
1187  }
1188
1189  TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
1190  if(length > 16 && length % 16)
1191    length -= length % 16;
1192  else
1193    length -= 16;
1194
1195  while(length > 0) {
1196    TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_CONTINUE_REG);
1197    length -= 16;
1198  }
1199
1200  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
1201  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
1202  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
1203
1204  TGA_SAVE_OFFSET();
1205
1206  return;
1207}
1208
1209void
1210TGASetupForClippedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2,
1211		       int octant)
1212{
1213#ifdef PROFILE
1214  unsigned int start, stop;
1215#endif
1216  TGAPtr pTga = NULL;
1217  CARD32 abs_dx = 0, abs_dy = 0, octant_reg = 0;
1218  TGA_DECL();
1219
1220  pTga = TGAPTR(pScrn);
1221  TGA_GET_IOBASE();
1222  TGA_GET_OFFSET();
1223/*    ErrorF("TGASetupForClippedLine called\n"); */
1224
1225/*    TGA_FAST_WRITE_REG(pTga->current_rop | BPP8PACKED, TGA_RASTEROP_REG); */
1226/*    TGA_FAST_WRITE_REG(OPAQUELINE | X11 | BPP8PACKED, TGA_MODE_REG); */
1227
1228  abs_dx = abs(x2 - x1);
1229  abs_dy = abs(y2 - y1);
1230
1231  if(octant & YMAJOR) {
1232      if(octant & YDECREASING) {
1233	  if(octant & XDECREASING)
1234	      octant_reg = TGA_NOSLOPE0_REG;
1235	  else
1236	      octant_reg = TGA_NOSLOPE2_REG;
1237      }
1238      else {
1239	  if(octant & XDECREASING)
1240	      octant_reg = TGA_NOSLOPE1_REG;
1241	  else
1242	      octant_reg = TGA_NOSLOPE3_REG;
1243      }
1244  }
1245  else {
1246      if(octant & YDECREASING) {
1247	  if(octant & XDECREASING)
1248	      octant_reg = TGA_NOSLOPE4_REG;
1249	  else
1250	      octant_reg = TGA_NOSLOPE6_REG;
1251      }
1252      else {
1253	  if(octant & XDECREASING)
1254	      octant_reg = TGA_NOSLOPE5_REG;
1255	  else
1256	      octant_reg = TGA_NOSLOPE7_REG;
1257      }
1258  }
1259
1260  TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
1261
1262  TGA_SAVE_OFFSET();
1263  return;
1264}
1265
1266void
1267TGASubsequentClippedSolidLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
1268			      int err)
1269    /* we are already in line mode, now we need to
1270       1) write starting pixel address to gaddr
1271       2) write initial error and line length to bresenham 3
1272       3) write the gctr to draw the line, and repeat for lines > 16 pixels
1273       4) set mode back to simple mode
1274    */
1275{
1276#ifdef PROFILE
1277  unsigned int start, stop;
1278#endif
1279  TGAPtr pTga = NULL;
1280  CARD32 address = 0;
1281  int length = 0;
1282  TGA_DECL();
1283
1284  pTga = TGAPTR(pScrn);
1285  TGA_GET_IOBASE();
1286  TGA_GET_OFFSET();
1287/*    ErrorF("TGASubsequentClippedSolidLine called\n"); */
1288
1289  address = FB_OFFSET(x1, y1);
1290  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
1291
1292  TGA_FAST_WRITE_REG(pTga->current_rop | pTga->depthflag, TGA_RASTEROP_REG);
1293  TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag, TGA_MODE_REG);
1294  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
1295
1296  length = len;
1297  TGA_FAST_WRITE_REG((err << 15) | (length & 0xF), TGA_BRES3_REG);
1298
1299  while(length > 0) {
1300    TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_CONTINUE_REG);
1301    if(length > 16 && length % 16)
1302	length -= length % 16;
1303    else
1304	length -= 16;
1305  }
1306
1307  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
1308  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
1309  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
1310
1311  TGA_SAVE_OFFSET();
1312
1313  return;
1314
1315}
1316
1317void
1318TGASetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
1319		      unsigned int planemask, int length,
1320		      unsigned char *pattern)
1321{
1322#ifdef PROFILE
1323  unsigned int start = 0, stop = 0;
1324#endif
1325  TGAPtr pTga = NULL;
1326  unsigned int color1 = 0, color2 = 0, pmask = 0;
1327  TGA_DECL();
1328
1329  pTga = TGAPTR(pScrn);
1330  TGA_GET_IOBASE();
1331  TGA_GET_OFFSET();
1332/*    ErrorF("TGASetupForDashedLine called\n"); */
1333
1334  if(pTga->depthflag == BPP8PACKED) {
1335    color1 = fg | (fg << 8) | (fg << 16) | (fg << 24);
1336    color2 = bg | (bg << 8) | (bg << 16) | (bg << 24);
1337    pmask = planemask | (planemask << 8) | (planemask << 16)
1338      | (planemask << 24);
1339  }
1340  else {
1341    color1 = fg;
1342    color2 = fg;
1343    pmask = planemask;
1344  }
1345
1346  pTga->current_rop = rop | pTga->depthflag;
1347  TGA_FAST_WRITE_REG(color1, TGA_FOREGROUND_REG);
1348  pTga->current_planemask = pmask;
1349  if(bg == -1) /* transparent line */
1350    pTga->transparent_pattern_p = 1;
1351  else {
1352    pTga->transparent_pattern_p = 0;
1353    TGA_FAST_WRITE_REG(color2, TGA_BACKGROUND_REG);
1354  }
1355
1356  pTga->line_pattern = pattern[0] | (pattern[1] << 8);
1357  pTga->line_pattern_length = length;
1358
1359  TGA_FAST_WRITE_REG(pScrn->displayWidth, TGA_WIDTH_REG);
1360  TGA_SAVE_OFFSET();
1361
1362  return;
1363}
1364
1365void
1366TGASubsequentDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int x2,
1367				int y2, int octant, int flags, int phase)
1368{
1369#ifdef PROFILE
1370  unsigned int start, stop;
1371#endif
1372  TGAPtr pTga = NULL;
1373  CARD32 abs_dx = 0, abs_dy = 0, address = 0, octant_reg = 0;
1374  int length = 0;
1375  CARD16 line_mask = 0;
1376  int pattern_overflow = 0;
1377  int l = 0;
1378  TGA_DECL();
1379
1380  pTga = TGAPTR(pScrn);
1381  TGA_GET_IOBASE();
1382  TGA_GET_OFFSET();
1383/*    ErrorF("TGASubsequentDashedLine called\n"); */
1384
1385  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
1386  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
1387  if(pTga->transparent_pattern_p)
1388    TGA_FAST_WRITE_REG(TRANSPARENTLINE | X11 | pTga->depthflag |
1389		       ((flags & OMIT_LAST) ? 0x0 : CAP_ENDS),
1390		       TGA_MODE_REG);
1391  else
1392    TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag |
1393		       ((flags & OMIT_LAST) ? 0x0 : CAP_ENDS),
1394		       TGA_MODE_REG);
1395
1396  address = FB_OFFSET(x1, y1);
1397  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
1398  abs_dx = abs(x2 - x1);
1399  abs_dy = abs(y2 - y1);
1400  if(abs_dx > abs_dy)
1401    length = abs_dx;
1402  else
1403    length = abs_dy;
1404
1405  if(octant & YMAJOR) {
1406      if(octant & YDECREASING) {
1407	  if(octant & XDECREASING)
1408	      octant_reg = TGA_SLOPE0_REG;
1409	  else
1410	      octant_reg = TGA_SLOPE2_REG;
1411      }
1412      else {
1413	  if(octant & XDECREASING)
1414	      octant_reg = TGA_SLOPE1_REG;
1415	  else
1416	      octant_reg = TGA_SLOPE3_REG;
1417      }
1418  }
1419  else {
1420      if(octant & YDECREASING) {
1421	  if(octant & XDECREASING)
1422	      octant_reg = TGA_SLOPE4_REG;
1423	  else
1424	      octant_reg = TGA_SLOPE6_REG;
1425      }
1426      else {
1427	  if(octant & XDECREASING)
1428	      octant_reg = TGA_SLOPE5_REG;
1429	  else
1430	      octant_reg = TGA_SLOPE7_REG;
1431      }
1432  }
1433  /* set up our first pattern with phase.  Keep track of if we overflow the
1434     pattern by pattern_overflow, and correct on the next write */
1435
1436  if(phase) {
1437    line_mask = pTga->line_pattern >> phase;
1438    l = (pTga->line_pattern_length - phase);
1439  }
1440  else {
1441    line_mask = pTga->line_pattern;
1442    l = pTga->line_pattern_length;
1443  }
1444
1445  while(l < 16) {
1446    line_mask |= pTga->line_pattern << l;
1447    l += pTga->line_pattern_length;
1448  }
1449  pattern_overflow = l - 16;
1450
1451  TGA_FAST_WRITE_REG(line_mask, TGA_DATA_REG);
1452
1453  TGA_FAST_WRITE_REG(abs_dx | (abs_dy << 16), octant_reg);
1454
1455  if(length > 16 && length % 16)
1456    length -= length % 16;
1457  else
1458    length -= 16;
1459
1460  while(length > 0) {
1461
1462    if(pattern_overflow) {
1463      line_mask = pTga->line_pattern >> (pTga->line_pattern_length -
1464					 pattern_overflow);
1465      l = pattern_overflow;
1466    }
1467    else {
1468      line_mask = pTga->line_pattern;
1469      l = pTga->line_pattern_length;
1470    }
1471    while(l < 16) {
1472      line_mask |= (pTga->line_pattern << l);
1473      l += pTga->line_pattern_length;
1474    }
1475    pattern_overflow = l - 16;
1476
1477    TGA_FAST_WRITE_REG(line_mask, TGA_CONTINUE_REG);
1478    length -= 16;
1479  }
1480
1481  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
1482  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
1483  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
1484
1485  TGA_SAVE_OFFSET();
1486
1487  return;
1488}
1489
1490void
1491TGASubsequentClippedDashedLine(ScrnInfoPtr pScrn, int x1, int y1, int len,
1492			      int err, int phase)
1493{
1494#ifdef PROFILE
1495  unsigned int start, stop;
1496#endif
1497  TGAPtr pTga = NULL;
1498  CARD32 address = 0;
1499  int length = 0;
1500  CARD16 line_mask = 0;
1501  int pattern_overflow = 0;
1502  int l = 0;
1503  TGA_DECL();
1504
1505  pTga = TGAPTR(pScrn);
1506  TGA_GET_IOBASE();
1507  TGA_GET_OFFSET();
1508  /*    ErrorF("TGASubsequentClippedDashedLine called\n"); */
1509
1510  address = FB_OFFSET(x1, y1);
1511  TGA_FAST_WRITE_REG(address, TGA_ADDRESS_REG);
1512
1513  TGA_FAST_WRITE_REG(pTga->current_rop, TGA_RASTEROP_REG);
1514  TGA_FAST_WRITE_REG(pTga->current_planemask, TGA_PLANEMASK_REG);
1515
1516  if(pTga->transparent_pattern_p)
1517    TGA_FAST_WRITE_REG(TRANSPARENTLINE | X11 | pTga->depthflag, TGA_MODE_REG);
1518  else
1519    TGA_FAST_WRITE_REG(OPAQUELINE | X11 | pTga->depthflag, TGA_MODE_REG);
1520
1521  length = len;
1522  TGA_FAST_WRITE_REG((err << 15) | (length & 0xF), TGA_BRES3_REG);
1523
1524
1525  if(phase) {
1526    line_mask = pTga->line_pattern >> phase;
1527    l = (pTga->line_pattern_length - phase);
1528  }
1529  else {
1530    line_mask = pTga->line_pattern;
1531    l = pTga->line_pattern_length;
1532  }
1533
1534  while(l < 16) {
1535    line_mask |= pTga->line_pattern << l;
1536    l += pTga->line_pattern_length;
1537  }
1538  pattern_overflow = l - 16;
1539
1540
1541  while(length > 0) {
1542    TGA_FAST_WRITE_REG(line_mask, TGA_CONTINUE_REG);
1543
1544    if(pattern_overflow) {
1545      line_mask = pTga->line_pattern >> (pTga->line_pattern_length -
1546					 pattern_overflow);
1547      l = pattern_overflow;
1548    }
1549    else {
1550      line_mask = pTga->line_pattern;
1551      l = pTga->line_pattern_length;
1552    }
1553    while(l < 16) {
1554      line_mask |= (pTga->line_pattern << l);
1555      l += pTga->line_pattern_length;
1556    }
1557    pattern_overflow = l - 16;
1558
1559    if(length > 16 && length % 16)
1560      length -= length % 16;
1561    else
1562      length -= 16;
1563  }
1564
1565  TGA_FAST_WRITE_REG(SIMPLE | X11 | pTga->depthflag, TGA_MODE_REG);
1566  TGA_FAST_WRITE_REG(MIX_SRC | pTga->depthflag, TGA_RASTEROP_REG);
1567  TGA_FAST_WRITE_REG(0xFFFFFFFF, TGA_PLANEMASK_REG);
1568
1569  TGA_SAVE_OFFSET();
1570
1571  return;
1572}
1573