tdfx_accel.c revision 02be438a
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_accel.c,v 1.19 2001/04/05 21:29:17 dawes Exp $ */
2
3#ifdef HAVE_CONFIG_H
4#include "config.h"
5#endif
6
7/* All drivers should typically include these */
8#include "xf86.h"
9#include "xf86_OSproc.h"
10#include "compiler.h"
11
12/* Drivers that need to access the PCI config space directly need this */
13#include "xf86Pci.h"
14
15/* Drivers for PCI hardware need this */
16#include "xf86PciInfo.h"
17
18/* Drivers that use XAA need this */
19#include "xaa.h"
20#include "xaalocal.h"
21#include "xf86fbman.h"
22
23#include "miline.h"
24
25#include "tdfx.h"
26
27#ifdef TDFX_DEBUG_CMDS
28static int cmdCnt=0;
29static int lastAddr=0;
30#endif
31
32static int TDFXROPCvt[] = {0x00, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE,
33			   0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF,
34			   0x00, 0xA0, 0x50, 0xF0, 0x0A, 0xAA, 0x5A, 0xFA,
35			   0x05, 0xA5, 0x55, 0xF5, 0x0F, 0xAF, 0x5F, 0xFF};
36#define ROP_PATTERN_OFFSET 16
37
38static void TDFXSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top,
39				     int right, int bottom);
40static void TDFXDisableClipping(ScrnInfoPtr pScrn);
41static void TDFXSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx,
42					   int paty, int fg, int bg, int rop,
43					   unsigned int planemask);
44static void TDFXSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx,
45						 int pay, int x, int y,
46						 int w, int h);
47static void TDFXSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
48				  unsigned int planemask);
49static void TDFXSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int srcx,
50					    int srcy, int dstx, int dsty,
51					    int flags);
52static void TDFXSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y,
53					   int len, int dir);
54static void TDFXNonTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int n,
55				   NonTEGlyphPtr glyphs, BoxPtr pbox, int fg,
56				   int rop, unsigned int planemask);
57static void TDFXSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
58                                   unsigned int planemask, int length,
59		                   unsigned char *pattern);
60static void TDFXSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
61                                             int x2, int y2, int flags,
62                                             int phase);
63#ifdef ENABLE_SS_COLOR_EXPAND_FILL
64static void TDFXSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrn,
65                                                      int fg, int bg, int rop,
66                                                      unsigned int planemask);
67static void TDFXSubsequentScreenToScreenColorExpandFill(ScrnInfoPtr pScrn,
68                                                        int x, int y, int w,
69                                                        int h, int srcx,
70                                                        int srcy, int offset);
71#endif
72static void TDFXSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
73                                                   int fg, int bg, int rop,
74                                                   unsigned int planemask);
75static void TDFXSubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
76                                                     int x, int y,
77                                                     int w, int h,
78                                                     int skipleft);
79static void TDFXSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
80
81void
82TDFXNeedSync(ScrnInfoPtr pScrn) {
83  TDFXPtr pTDFX = TDFXPTR(pScrn);
84  pTDFX->syncDone=FALSE;
85  pTDFX->AccelInfoRec->NeedToSync = TRUE;
86}
87
88void
89TDFXFirstSync(ScrnInfoPtr pScrn) {
90  TDFXPtr pTDFX = TDFXPTR(pScrn);
91
92  if (!pTDFX->syncDone) {
93#ifdef XF86DRI
94    if (pTDFX->directRenderingEnabled) {
95      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
96      TDFXSwapContextFifo(screenInfo.screens[pScrn->scrnIndex]);
97    }
98#endif
99    pTDFX->syncDone=TRUE;
100    pTDFX->sync(pScrn);
101  }
102}
103
104void
105TDFXCheckSync(ScrnInfoPtr pScrn) {
106  TDFXPtr pTDFX = TDFXPTR(pScrn);
107
108  if (pTDFX->syncDone) {
109    pTDFX->sync(pScrn);
110    pTDFX->syncDone=FALSE;
111#ifdef XF86DRI
112    if (pTDFX->directRenderingEnabled) {
113      DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
114    }
115#endif
116  }
117}
118
119void
120TDFXSelectBuffer(TDFXPtr pTDFX, int which) {
121  int fmt;
122
123  TDFXMakeRoom(pTDFX, 4);
124  DECLARE(SSTCP_SRCBASEADDR|SSTCP_DSTBASEADDR|SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
125  switch (which) {
126  case TDFX_FRONT:
127    if (pTDFX->cpp==1) fmt=pTDFX->stride|(1<<16);
128    else fmt=pTDFX->stride|((pTDFX->cpp+1)<<16);
129    TDFXWriteLong(pTDFX, SST_2D_DSTBASEADDR, pTDFX->fbOffset);
130    TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
131    pTDFX->sst2DDstFmtShadow = fmt;
132    TDFXWriteLong(pTDFX, SST_2D_SRCBASEADDR, pTDFX->fbOffset);
133    TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
134    pTDFX->sst2DSrcFmtShadow = fmt;
135    break;
136  case TDFX_BACK:
137    if (pTDFX->cpp==2)
138      fmt=((pTDFX->stride+127)/128)|(3<<16); /* Tiled 16bpp */
139    else
140      fmt=((pTDFX->stride+127)/128)|(5<<16); /* Tiled 32bpp */
141    TDFXWriteLong(pTDFX, SST_2D_DSTBASEADDR, pTDFX->backOffset|BIT(31));
142    TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
143    pTDFX->sst2DDstFmtShadow = fmt;
144    TDFXWriteLong(pTDFX, SST_2D_SRCBASEADDR, pTDFX->backOffset|BIT(31));
145    TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
146    pTDFX->sst2DSrcFmtShadow = fmt;
147    break;
148  case TDFX_DEPTH:
149    if (pTDFX->cpp==2)
150      fmt=((pTDFX->stride+127)/128)|(3<<16); /* Tiled 16bpp */
151    else
152      fmt=((pTDFX->stride+127)/128)|(5<<16); /* Tiled 32bpp */
153    TDFXWriteLong(pTDFX, SST_2D_DSTBASEADDR, pTDFX->depthOffset|BIT(31));
154    TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
155    pTDFX->sst2DDstFmtShadow = fmt;
156    TDFXWriteLong(pTDFX, SST_2D_SRCBASEADDR, pTDFX->depthOffset|BIT(31));
157    TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
158    pTDFX->sst2DSrcFmtShadow = fmt;
159    break;
160  default:
161    ;
162  }
163}
164
165void
166TDFXSetLFBConfig(TDFXPtr pTDFX) {
167  if (pTDFX->ChipType<=PCI_CHIP_VOODOO3) {
168#if X_BYTE_ORDER == X_BIG_ENDIAN
169    unsigned int lfbmode;
170    lfbmode=TDFXReadLongMMIO(pTDFX, SST_3D_LFBMODE);
171
172    lfbmode&=~BIT(12); /* 0 bit 12 is byte swizzle */
173    lfbmode|=BIT(11); /* 1 bit 11 is word swizzle */
174    lfbmode&=~BIT(10); /* 0 bit 10  ARGB or ABGR */
175    lfbmode&=~BIT(9); /* 0 bit 9 if bit10 = 0:  ARGB else ABGR */
176
177    TDFXWriteLongMMIO(pTDFX, SST_3D_LFBMODE, lfbmode);
178#endif
179    TDFXWriteLongMMIO(pTDFX, LFBMEMORYCONFIG, (pTDFX->backOffset>>12) |
180		      SST_RAW_LFB_ADDR_STRIDE_4K |
181		      ((pTDFX->stride+127)/128)<<SST_RAW_LFB_TILE_STRIDE_SHIFT);
182  } else {
183    int chip;
184    int stride, bits;
185    int TileAperturePitch, lg2TileAperturePitch;
186    if (pTDFX->cpp==2) stride=pTDFX->stride;
187    else stride=4*pTDFX->stride/pTDFX->cpp;
188    bits=pTDFX->backOffset>>12;
189    for (lg2TileAperturePitch = 0, TileAperturePitch = 1024;
190         (lg2TileAperturePitch < 5) &&
191             TileAperturePitch < stride;
192         lg2TileAperturePitch += 1, TileAperturePitch <<= 1);
193#if	0
194    fprintf(stderr, "Using %d (== lg2(%d)-10) for tile aperture pitch\n",
195            lg2TileAperturePitch, TileAperturePitch);
196    fprintf(stderr, "stride == %d\n", stride);
197#endif
198    for (chip=0; chip<pTDFX->numChips; chip++) {
199      TDFXWriteChipLongMMIO(pTDFX, chip, LFBMEMORYCONFIG, (bits&0x1FFF) |
200			    SST_RAW_LFB_ADDR_STRIDE(lg2TileAperturePitch) |
201			    ((bits&0x6000)<<10) |
202			    ((stride+127)/128)<<SST_RAW_LFB_TILE_STRIDE_SHIFT);
203    }
204  }
205}
206
207Bool
208TDFXAccelInit(ScreenPtr pScreen)
209{
210  XAAInfoRecPtr infoPtr;
211  ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
212  TDFXPtr pTDFX = TDFXPTR(pScrn);
213  CARD32 commonFlags;
214
215  pTDFX->AccelInfoRec = infoPtr = XAACreateInfoRec();
216  if (!infoPtr) return FALSE;
217
218  infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER;
219
220  infoPtr->Sync = pTDFX->sync;
221
222  infoPtr->SetClippingRectangle = TDFXSetClippingRectangle;
223  infoPtr->DisableClipping = TDFXDisableClipping;
224  infoPtr->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COLOR_EXPAND |
225    HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
226    HARDWARE_CLIP_MONO_8x8_FILL |
227    HARDWARE_CLIP_COLOR_8x8_FILL |
228    HARDWARE_CLIP_SOLID_FILL |
229    HARDWARE_CLIP_DASHED_LINE |
230    HARDWARE_CLIP_SOLID_LINE;
231
232  miSetZeroLineBias(pScreen, OCTANT2 | OCTANT5 | OCTANT7 | OCTANT8);
233
234  commonFlags = BIT_ORDER_IN_BYTE_MSBFIRST | NO_PLANEMASK;
235
236  infoPtr->SetupForSolidFill = TDFXSetupForSolidFill;
237  infoPtr->SubsequentSolidFillRect = TDFXSubsequentSolidFillRect;
238  infoPtr->SolidFillFlags = commonFlags;
239
240  infoPtr->SetupForSolidLine = TDFXSetupForSolidLine;
241  infoPtr->SubsequentSolidTwoPointLine = TDFXSubsequentSolidTwoPointLine;
242  infoPtr->SubsequentSolidHorVertLine = TDFXSubsequentSolidHorVertLine;
243  infoPtr->SolidLineFlags = commonFlags;
244
245  infoPtr->SetupForDashedLine = TDFXSetupForDashedLine;
246  infoPtr->SubsequentDashedTwoPointLine = TDFXSubsequentDashedTwoPointLine;
247  infoPtr->DashedLineFlags = commonFlags | LINE_PATTERN_LSBFIRST_LSBJUSTIFIED;
248  infoPtr->DashPatternMaxLength = 32;
249
250  infoPtr->NonTEGlyphRenderer = TDFXNonTEGlyphRenderer;
251  infoPtr->NonTEGlyphRendererFlags = commonFlags;
252
253  infoPtr->SetupForScreenToScreenCopy = TDFXSetupForScreenToScreenCopy;
254  infoPtr->SubsequentScreenToScreenCopy = TDFXSubsequentScreenToScreenCopy;
255  infoPtr->ScreenToScreenCopyFlags = commonFlags;
256
257  /* When we're using the fifo we have to use indirect expansion */
258  pTDFX->scanlineColorExpandBuffers[0] = xalloc((pScrn->virtualX+62)/32*4);
259  pTDFX->scanlineColorExpandBuffers[1] = xalloc((pScrn->virtualX+62)/32*4);
260  infoPtr->NumScanlineColorExpandBuffers=2;
261  infoPtr->ScanlineColorExpandBuffers=pTDFX->scanlineColorExpandBuffers;
262  infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
263    TDFXSetupForCPUToScreenColorExpandFill;
264  infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
265    TDFXSubsequentCPUToScreenColorExpandFill;
266  infoPtr->SubsequentColorExpandScanline =
267    TDFXSubsequentColorExpandScanline;
268  infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
269#if X_BYTE_ORDER == X_LITTLE_ENDIAN
270    BIT_ORDER_IN_BYTE_MSBFIRST |
271#endif
272    CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD |
273    LEFT_EDGE_CLIPPING; /* | LEFT_EDGE_CLIPPING_NEGATIVE_X; */
274
275  infoPtr->SetupForMono8x8PatternFill = TDFXSetupForMono8x8PatternFill;
276  infoPtr->SubsequentMono8x8PatternFillRect =
277    TDFXSubsequentMono8x8PatternFillRect;
278  infoPtr->Mono8x8PatternFillFlags = commonFlags |
279    HARDWARE_PATTERN_PROGRAMMED_BITS |
280    HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
281    HARDWARE_PATTERN_SCREEN_ORIGIN;
282
283#ifdef ENABLE_SS_COLOR_EXPAND_FILL
284  /* This causes us to fail compliance */
285  /* I suspect 1bpp pixmaps are getting written to cache incorrectly */
286  infoPtr->SetupForScreenToScreenColorExpandFill =
287    TDFXSetupForScreenToScreenColorExpandFill;
288  infoPtr->SubsequentScreenToScreenColorExpandFill =
289    TDFXSubsequentScreenToScreenColorExpandFill;
290  infoPtr->ScreenToScreenColorExpandFillFlags = commonFlags;
291#endif
292
293  pTDFX->PciCnt=TDFXReadLongMMIO(pTDFX, 0)&0x1F;
294  pTDFX->PrevDrawState=pTDFX->DrawState=0;
295
296  pTDFX->ModeReg.srcbaseaddr=pTDFX->fbOffset;
297  TDFXWriteLongMMIO(pTDFX, SST_2D_SRCBASEADDR, pTDFX->ModeReg.srcbaseaddr);
298  pTDFX->ModeReg.dstbaseaddr=pTDFX->fbOffset;
299  TDFXWriteLongMMIO(pTDFX, SST_2D_DSTBASEADDR, pTDFX->ModeReg.dstbaseaddr);
300
301  pTDFX->sst2DSrcFmtShadow = TDFXReadLongMMIO(pTDFX, SST_2D_SRCFORMAT);
302  pTDFX->sst2DDstFmtShadow = TDFXReadLongMMIO(pTDFX, SST_2D_DSTFORMAT);
303
304  /* Fill in acceleration functions */
305  return XAAInit(pScreen, infoPtr);
306}
307
308static void TDFXMakeRoomNoProp(TDFXPtr pTDFX, int size) {
309  int stat;
310
311  pTDFX->PciCnt-=size;
312  if (pTDFX->PciCnt<1) {
313    do {
314      stat=TDFXReadLongMMIO(pTDFX, 0);
315      pTDFX->PciCnt=stat&0x1F;
316    } while (pTDFX->PciCnt<size);
317  }
318}
319
320static void TDFXSendNOPNoProp(ScrnInfoPtr pScrn)
321{
322  TDFXPtr pTDFX;
323
324  pTDFX=TDFXPTR(pScrn);
325  TDFXMakeRoomNoProp(pTDFX, 1);
326  TDFXWriteLongMMIO(pTDFX, SST_2D_COMMAND, SST_2D_NOP);
327}
328
329void TDFXSync(ScrnInfoPtr pScrn)
330{
331  TDFXPtr pTDFX;
332  int i;
333  int stat;
334
335  TDFXTRACEACCEL("TDFXSync\n");
336  pTDFX=TDFXPTR(pScrn);
337
338  TDFXSendNOPNoProp(pScrn);
339  i=0;
340  do {
341    stat=TDFXReadLongMMIO(pTDFX, 0);
342    if (stat&SST_BUSY) i=0; else i++;
343  } while (i<3);
344  pTDFX->PciCnt=stat&0x1F;
345}
346
347static void
348TDFXMatchState(TDFXPtr pTDFX)
349{
350  if (pTDFX->PrevDrawState==pTDFX->DrawState) return;
351
352  /* Do we need to set a clipping rectangle? */
353  if (pTDFX->DrawState&DRAW_STATE_CLIPPING)
354    pTDFX->Cmd |= SST_2D_USECLIP1;
355  else
356    pTDFX->Cmd &= ~SST_2D_USECLIP1;
357
358  /* Do we need to set transparency? */
359  TDFXMakeRoom(pTDFX, 1);
360  DECLARE(SSTCP_COMMANDEXTRA);
361  if (pTDFX->DrawState&DRAW_STATE_TRANSPARENT) {
362    TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, SST_2D_SRC_COLORKEY_EX);
363  } else {
364    TDFXWriteLong(pTDFX, SST_2D_COMMANDEXTRA, 0);
365  }
366
367  /* Has the previous routine left clip1 changed? Reset it. */
368  if (pTDFX->DrawState&DRAW_STATE_CLIP1CHANGED) {
369    TDFXMakeRoom(pTDFX, 2);
370    DECLARE(SSTCP_CLIP1MIN|SSTCP_CLIP1MAX);
371    TDFXWriteLong(pTDFX, SST_2D_CLIP1MIN, pTDFX->ModeReg.clip1min);
372    TDFXWriteLong(pTDFX, SST_2D_CLIP1MAX, pTDFX->ModeReg.clip1max);
373    pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
374  }
375
376  pTDFX->PrevDrawState=pTDFX->DrawState;
377}
378
379static void
380TDFXClearState(ScrnInfoPtr pScrn)
381{
382  TDFXPtr pTDFX;
383
384  pTDFX=TDFXPTR(pScrn);
385  pTDFX->Cmd=0;
386  pTDFX->DrawState&=~DRAW_STATE_TRANSPARENT;
387  /* Make sure we've done a sync */
388  TDFXFirstSync(pScrn);
389}
390
391static void
392TDFXSetClippingRectangle(ScrnInfoPtr pScrn, int left, int top, int right,
393			 int bottom)
394{
395  TDFXPtr pTDFX;
396
397  TDFXTRACEACCEL("TDFXSetClippingRectangle %d,%d to %d,%d\n", left, top,
398		 right, bottom);
399  pTDFX=TDFXPTR(pScrn);
400
401  pTDFX->ModeReg.clip1min=(top&0xFFF)<<16 | (left&0xFFF);
402  pTDFX->ModeReg.clip1max=((bottom+1)&0xFFF)<<16 | ((right+1)&0xFFF);
403
404  pTDFX->DrawState|=DRAW_STATE_CLIPPING|DRAW_STATE_CLIP1CHANGED;
405}
406
407static void
408TDFXDisableClipping(ScrnInfoPtr pScrn)
409{
410  TDFXPtr pTDFX;
411
412  TDFXTRACEACCEL("TDFXDisableClippingRectangle\n");
413  pTDFX=TDFXPTR(pScrn);
414
415  pTDFX->DrawState&=~DRAW_STATE_CLIPPING;
416}
417
418void
419TDFXSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
420			       unsigned int planemask, int trans_color)
421{
422  TDFXPtr pTDFX;
423  int fmt;
424
425  TDFXTRACEACCEL("TDFXSetupForScreenToScreenCopy\n xdir=%d ydir=%d "
426		 "rop=%d planemask=%d trans_color=%d\n",
427		 xdir, ydir, rop, planemask, trans_color);
428  pTDFX=TDFXPTR(pScrn);
429  TDFXClearState(pScrn);
430
431  if (trans_color!=-1) {
432    TDFXMakeRoom(pTDFX, 3);
433    DECLARE(SSTCP_SRCCOLORKEYMIN|SSTCP_SRCCOLORKEYMAX|SSTCP_ROP);
434    TDFXWriteLong(pTDFX, SST_2D_SRCCOLORKEYMIN, trans_color);
435    TDFXWriteLong(pTDFX, SST_2D_SRCCOLORKEYMAX, trans_color);
436    TDFXWriteLong(pTDFX, SST_2D_ROP, TDFXROPCvt[GXnoop]<<8);
437    pTDFX->DrawState|=DRAW_STATE_TRANSPARENT;
438  }
439  pTDFX->Cmd = (TDFXROPCvt[rop]<<24) | SST_2D_SCRNTOSCRNBLIT;
440  if (xdir==-1) pTDFX->Cmd |= SST_2D_X_RIGHT_TO_LEFT;
441  if (ydir==-1) pTDFX->Cmd |= SST_2D_Y_BOTTOM_TO_TOP;
442  if (pTDFX->cpp==1) fmt=pTDFX->stride|(1<<16);
443  else fmt=pTDFX->stride|((pTDFX->cpp+1)<<16);
444
445  TDFXMakeRoom(pTDFX, 2);
446  DECLARE(SSTCP_SRCFORMAT|SSTCP_DSTFORMAT);
447  TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
448  pTDFX->sst2DDstFmtShadow = fmt;
449  TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, fmt);
450  pTDFX->sst2DSrcFmtShadow = fmt;
451}
452
453void
454TDFXSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX, int srcY,
455				 int dstX, int dstY, int w, int h)
456{
457  TDFXPtr pTDFX;
458
459  TDFXTRACEACCEL("TDFXSubsequentScreenToScreenCopy\n srcX=%d srcY=%d"
460                 " dstX=%d dstY=%d w=%d h=%d\n", srcX, srcY, dstX, dstY, w, h);
461  pTDFX=TDFXPTR(pScrn);
462  TDFXMatchState(pTDFX);
463
464  if (pTDFX->Cmd&SST_2D_Y_BOTTOM_TO_TOP) {
465    srcY += h-1;
466    dstY += h-1;
467  }
468  if (pTDFX->Cmd&SST_2D_X_RIGHT_TO_LEFT) {
469    srcX += w-1;
470    dstX += w-1;
471  }
472  if ((srcY>=dstY-32 && srcY<=dstY)||
473      (srcY>=pTDFX->prevBlitDest.y1-32 && srcY<=pTDFX->prevBlitDest.y1)) {
474    TDFXSendNOP(pScrn);
475  }
476  pTDFX->sync(pScrn);
477
478  TDFXMakeRoom(pTDFX, 4);
479  DECLARE(SSTCP_DSTSIZE|SSTCP_DSTXY|SSTCP_SRCXY|SSTCP_COMMAND);
480  TDFXWriteLong(pTDFX, SST_2D_SRCXY, (srcX&0x1FFF) | ((srcY&0x1FFF)<<16));
481  TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, (w&0x1FFF) | ((h&0x1FFF)<<16));
482  TDFXWriteLong(pTDFX, SST_2D_DSTXY, (dstX&0x1FFF) | ((dstY&0x1FFF)<<16));
483  TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
484
485  pTDFX->prevBlitDest.y1=dstY;
486}
487
488void
489TDFXSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
490		      unsigned int planemask)
491{
492  TDFXPtr pTDFX;
493  int fmt;
494
495  TDFXTRACEACCEL("TDFXSetupForSolidFill color=%d rop=%d planemask=%d\n",
496                 color, rop, planemask);
497  pTDFX=TDFXPTR(pScrn);
498  TDFXClearState(pScrn);
499
500  pTDFX->Cmd=TDFXROPCvt[rop]<<24;
501  if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
502  else fmt=((pTDFX->cpp+1)<<16)|pTDFX->stride;
503
504  TDFXMakeRoom(pTDFX, 3);
505  DECLARE(SSTCP_DSTFORMAT|SSTCP_COLORFORE|
506		 SSTCP_COLORBACK);
507  TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
508  pTDFX->sst2DDstFmtShadow = fmt;
509  TDFXWriteLong(pTDFX, SST_2D_COLORBACK, color);
510  TDFXWriteLong(pTDFX, SST_2D_COLORFORE, color);
511}
512
513void
514TDFXSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
515{
516  /* Also called by TDFXSubsequentMono8x8PatternFillRect */
517  TDFXPtr pTDFX;
518
519  TDFXTRACEACCEL("TDFXSubsequentSolidFillRect x=%d y=%d w=%d h=%d\n",
520		 x, y, w, h);
521  pTDFX=TDFXPTR(pScrn);
522  TDFXMatchState(pTDFX);
523
524  TDFXMakeRoom(pTDFX, 3);
525  DECLARE(SSTCP_DSTSIZE|SSTCP_DSTXY|SSTCP_COMMAND);
526  TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, ((h&0x1FFF)<<16) | (w&0x1FFF));
527  TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((y&0x1FFF)<<16) | (x&0x1FFF));
528  TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd | SST_2D_RECTANGLEFILL |
529		SST_2D_GO);
530}
531
532static void
533TDFXSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty,
534			       int fg, int bg, int rop, unsigned int planemask)
535{
536  TDFXPtr pTDFX;
537  int fmt;
538
539  TDFXTRACEACCEL("TDFXSetupForMono8x8PatternFill patx=%x paty=%x fg=%d"
540                 " bg=%d rop=%d planemask=%d\n", patx, paty, fg, bg, rop,
541		 planemask);
542  pTDFX=TDFXPTR(pScrn);
543  TDFXClearState(pScrn);
544
545  pTDFX->Cmd = (TDFXROPCvt[rop+ROP_PATTERN_OFFSET]<<24) |
546    SST_2D_MONOCHROME_PATTERN;
547  if (bg==-1) {
548    pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
549  }
550  if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
551  else fmt=((pTDFX->cpp+1)<<16)|pTDFX->stride;
552
553  TDFXMakeRoom(pTDFX, 5);
554  DECLARE(SSTCP_DSTFORMAT|SSTCP_PATTERN0ALIAS
555		  |SSTCP_PATTERN1ALIAS|SSTCP_COLORFORE|
556		  SSTCP_COLORBACK);
557  TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
558  pTDFX->sst2DDstFmtShadow = fmt;
559  TDFXWriteLong(pTDFX, SST_2D_PATTERN0, patx);
560  TDFXWriteLong(pTDFX, SST_2D_PATTERN1, paty);
561  TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
562  TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
563}
564
565static void
566TDFXSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
567				     int x, int y, int w, int h)
568{
569  TDFXPtr pTDFX;
570
571  TDFXTRACEACCEL("TDFXSubsequentMono8x8PatternFillRect patx=%x paty=%x"
572                 " x=%d y=%d w=%d h=%d\n", patx, paty, x, y, w, h);
573  pTDFX=TDFXPTR(pScrn);
574
575  pTDFX->Cmd |= ((patx&0x7)<<SST_2D_X_PATOFFSET_SHIFT) |
576    ((paty&0x7)<<SST_2D_Y_PATOFFSET_SHIFT);
577
578  TDFXSubsequentSolidFillRect(pScrn, x, y, w, h);
579}
580
581static void
582TDFXSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
583		      unsigned int planemask)
584{
585  TDFXPtr pTDFX;
586
587  TDFXTRACEACCEL("TDFXSetupForSolidLine\n");
588  pTDFX=TDFXPTR(pScrn);
589  TDFXClearState(pScrn);
590
591  pTDFX->Cmd = (TDFXROPCvt[rop]<<24);
592
593  TDFXMakeRoom(pTDFX, 2);
594  DECLARE(SSTCP_COLORFORE|SSTCP_COLORBACK);
595  TDFXWriteLong(pTDFX, SST_2D_COLORBACK, color);
596  TDFXWriteLong(pTDFX, SST_2D_COLORFORE, color);
597}
598
599static void
600TDFXSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int srcx, int srcy,
601				int dstx, int dsty, int flags)
602{
603  /* Also used by TDFXSubsequentDashedTwoPointLine */
604  TDFXPtr pTDFX;
605
606  TDFXTRACEACCEL("TDFXSubsequentSolidTwoPointLine "
607		 "srcx=%d srcy=%d dstx=%d dsty=%d flags=%d\n",
608		 srcx, srcy, dstx, dsty, flags);
609  pTDFX=TDFXPTR(pScrn);
610  TDFXMatchState(pTDFX);
611
612  if (flags&OMIT_LAST) pTDFX->Cmd|=SST_2D_POLYLINE;
613  else pTDFX->Cmd|=SST_2D_LINE;
614
615  TDFXMakeRoom(pTDFX, 3);
616  DECLARE(SSTCP_SRCXY|SSTCP_DSTXY|SSTCP_COMMAND);
617  TDFXWriteLong(pTDFX, SST_2D_SRCXY, (srcy&0x1FFF)<<16 | (srcx&0x1FFF));
618  TDFXWriteLong(pTDFX, SST_2D_DSTXY, (dsty&0x1FFF)<<16 | (dstx&0x1FFF));
619  TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
620}
621
622static void
623TDFXSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
624			       int dir)
625{
626  TDFXPtr pTDFX;
627
628  TDFXTRACEACCEL("TDFXSubsequentSolidHorVertLine\n");
629  pTDFX=TDFXPTR(pScrn);
630  TDFXMatchState(pTDFX);
631
632  TDFXMakeRoom(pTDFX, 3);
633  DECLARE(SSTCP_SRCXY|SSTCP_DSTXY|SSTCP_COMMAND);
634  TDFXWriteLong(pTDFX, SST_2D_SRCXY, (y&0x1FFF)<<16 | (x&0x1FFF));
635  if (dir == DEGREES_0)
636    TDFXWriteLong(pTDFX, SST_2D_DSTXY, (y&0x1FFF)<<16 | ((x+len)&0x1FFF));
637  else
638    TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((y+len)&0x1FFF)<<16 | (x&0x1FFF));
639  TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_POLYLINE|SST_2D_GO);
640}
641
642static void
643TDFXNonTEGlyphRenderer(ScrnInfoPtr pScrn, int x, int y, int n,
644		       NonTEGlyphPtr glyphs, BoxPtr pbox, int fg, int rop,
645		       unsigned int planemask)
646{
647  TDFXPtr pTDFX;
648  int ndwords;
649  int g;
650  NonTEGlyphPtr glyph;
651
652  TDFXTRACEACCEL("TDFXNonTEGlyphRenderer\n");
653  pTDFX=TDFXPTR(pScrn);
654  TDFXClearState(pScrn);
655  /* Don't bother fixing clip1, we're going to change it anyway */
656  pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
657  TDFXMatchState(pTDFX);
658  /* We're changing clip1 so make sure we use it and flag it */
659  pTDFX->Cmd|=SST_2D_USECLIP1;
660  pTDFX->DrawState|=DRAW_STATE_CLIP1CHANGED;
661
662  pTDFX->Cmd|=(TDFXROPCvt[rop]<<24)|SST_2D_TRANSPARENT_MONOCHROME;
663  pTDFX->Cmd|=SST_2D_HOSTTOSCRNBLIT;
664
665  TDFXMakeRoom(pTDFX, 6);
666  DECLARE(SSTCP_CLIP1MIN|SSTCP_CLIP1MAX|SSTCP_SRCFORMAT|
667	  SSTCP_SRCXY|SSTCP_COLORFORE|SSTCP_COMMAND);
668  TDFXWriteLong(pTDFX, SST_2D_CLIP1MIN, ((pbox->y1&0x1FFF)<<16) |
669		(pbox->x1&0x1FFF));
670  TDFXWriteLong(pTDFX, SST_2D_CLIP1MAX, ((pbox->y2&0x1FFF)<<16) |
671		(pbox->x2&0x1FFF));
672#if X_BYTE_ORDER == X_BIG_ENDIAN
673  TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, SST_2D_PIXFMT_1BPP |
674		SST_2D_SOURCE_PACKING_DWORD | BIT(20));
675#else
676  TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, SST_2D_PIXFMT_1BPP |
677		SST_2D_SOURCE_PACKING_DWORD);
678#endif
679  pTDFX->sst2DSrcFmtShadow = SST_2D_PIXFMT_1BPP | SST_2D_SOURCE_PACKING_DWORD;
680  TDFXWriteLong(pTDFX, SST_2D_SRCXY, 0);
681  TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
682  TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd);
683
684  for (g=0, glyph=glyphs; g<n; g++, glyph++) {
685    int dx = x+glyph->start;
686    int dy = y-glyph->yoff;
687    int w = glyph->end - glyph->start;
688    int *glyph_data = (int*)glyph->bits;
689
690    if (!glyph->srcwidth) continue;
691    ndwords = (glyph->srcwidth+3)>>2;
692    ndwords *= glyph->height;
693
694    TDFXMakeRoom(pTDFX, 2);
695    DECLARE(SSTCP_DSTSIZE|SSTCP_DSTXY);
696    TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, ((glyph->height&0x1FFF)<<16) |
697		  (w&0x1FFF));
698    TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((dy&0x1FFF)<<16) | (dx&0x1FFF));
699
700    do {
701      int i = ndwords;
702      int j;
703
704      if (i>30) i=30;
705      TDFXMakeRoom(pTDFX, i);
706      DECLARE_LAUNCH(i, 0);
707      for (j=0; j<i; j++) {
708#if X_BYTE_ORDER == X_BIG_ENDIAN
709	TDFXWriteLong(pTDFX, SST_2D_LAUNCH, *glyph_data);
710#else
711	TDFXWriteLong(pTDFX, SST_2D_LAUNCH, XAAReverseBitOrder(*glyph_data));
712#endif
713	glyph_data++;
714      }
715      ndwords -= i;
716    } while (ndwords);
717  }
718}
719
720static void
721TDFXSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop,
722                       unsigned int planemask, int length,
723		       unsigned char *pattern)
724{
725  TDFXPtr pTDFX;
726#if X_BYTE_ORDER == X_BIG_ENDIAN
727  unsigned int pat = *(unsigned int *)pattern;
728#endif
729
730  TDFXTRACEACCEL("TDFXSetupForDashedLine\n");
731  pTDFX=TDFXPTR(pScrn);
732
733#if X_BYTE_ORDER == X_BIG_ENDIAN
734  pat=((pat & 0xAAAAAAAA) >> 1) | ((pat & 0x55555555) << 1);
735  pat=((pat & 0xCCCCCCCC) >> 2) | ((pat & 0x33333333) << 2);
736  pat=((pat & 0xF0F0F0F0) >> 4) | ((pat & 0x0F0F0F0F) << 4);
737  pat=((pat & 0xFF00FF00) >> 8) | ((pat & 0x00FF00FF) << 8);
738  pat=((pat & 0xFFFF0000) >> 16) | ((pat & 0x0000FFFF) << 16);
739#endif
740
741  TDFXClearState(pScrn);
742
743  pTDFX->Cmd = (TDFXROPCvt[rop]<<24) | SST_2D_STIPPLE_LINE;
744  if(bg == -1) {
745    pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
746  }
747  pTDFX->DashedLineSize = ((length-1)&0xFF)+1;
748
749  TDFXMakeRoom(pTDFX, 3);
750  DECLARE(SSTCP_COLORFORE|SSTCP_COLORBACK|SSTCP_LINESTIPPLE);
751#if X_BYTE_ORDER == X_BIG_ENDIAN
752  TDFXWriteLong(pTDFX, SST_2D_LINESTIPPLE, pat);
753#else
754  TDFXWriteLong(pTDFX, SST_2D_LINESTIPPLE, *(int *)pattern);
755#endif
756  TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
757  TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
758}
759
760static void
761TDFXSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
762                                 int x2, int y2, int flags, int phase)
763{
764  TDFXPtr pTDFX;
765  int linestyle;
766
767  TDFXTRACEACCEL("TDFXSubsequentDashedTwoPointLine\n");
768  pTDFX=TDFXPTR(pScrn);
769
770  linestyle = ((pTDFX->DashedLineSize-1)<<8) |
771              (((phase%pTDFX->DashedLineSize)&0x1F)<<24);
772
773  TDFXMakeRoom(pTDFX, 1);
774  DECLARE(SSTCP_LINESTYLE);
775  TDFXWriteLong(pTDFX, SST_2D_LINESTYLE, linestyle);
776
777  TDFXSubsequentSolidTwoPointLine(pScrn, x1, y1, x2, y2, flags);
778}
779
780#ifdef ENABLE_SS_COLOR_EXPAND_FILL
781static void
782TDFXSetupForScreenToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg,
783                                          int rop, unsigned int planemask)
784{
785  TDFXPtr pTDFX;
786
787  TDFXTRACEACCEL("TDFXSetupForScreenToScreenColorExpandFill\n");
788  pTDFX=TDFXPTR(pScrn);
789  TDFXClearState(pScrn);
790
791  TDFXMatchState(pTDFX);
792  pTDFX->Cmd|=SST_2D_SCRNTOSCRNBLIT|(TDFXROPCvt[rop]<<24);
793
794  if (bg==-1) {
795    pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
796  }
797  TDFXMakeRoom(pTDFX, 2);
798  DECLARE(SSTCP_COLORFORE|SSTCP_COLORBACK);
799  TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
800  TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
801}
802
803static void
804TDFXSubsequentScreenToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y,
805                                            int w, int h, int srcx, int srcy,
806                                            int offset)
807{
808  TDFXPtr pTDFX;
809  int fmt;
810
811  TDFXTRACEACCEL("TDFXSubsequentScreenToScreenColorExpandFill "
812		 "x=%d y=%d w=%d h=%d srcx=%d srcy=%d offset=%d\n",
813		 x, y, w, h, srcx, srcy, offset);
814  pTDFX=TDFXPTR(pScrn);
815  /* Don't bother resetting clip1 since we're changing it anyway */
816  pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
817  TDFXMatchState(pTDFX);
818  /* We're changing clip1 so make sure we use it and flag it */
819  pTDFX->Cmd|=SST_2D_USECLIP1;
820  pTDFX->DrawState|=DRAW_STATE_CLIP1CHANGED;
821
822  if (srcy>=pTDFX->prevBlitDest.y1-8 && srcy<=pTDFX->prevBlitDest.y1) {
823    TDFXSendNOP(pScrn);
824  }
825
826  if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
827  else fmt=(pTDFX->cpp+1)<<16|pTDFX->stride;
828
829  TDFXMakeRoom(pTDFX, 8);
830  DECLARE(SSTCP_SRCFORMAT|SSTCP_SRCXY|SSTCP_DSTFORMAT |
831	  SSTCP_DSTSIZE|SSTCP_DSTXY|SSTCP_COMMAND |
832	  SSTCP_CLIP1MIN|SSTCP_CLIP1MAX);
833  TDFXWriteLong(pTDFX,SST_2D_DSTFORMAT, fmt);
834  pTDFX->sst2DDstFmtShadow = fmt;
835  TDFXWriteLong(pTDFX,SST_2D_CLIP1MIN, (x&0x1FFF) | ((y&0x1FFF)<<16));
836  TDFXWriteLong(pTDFX,SST_2D_CLIP1MAX, ((x+w)&0x1FFF) | (((y+h)&0x1FFF)<<16));
837  TDFXWriteLong(pTDFX,SST_2D_SRCFORMAT, pTDFX->stride);
838  pTDFX->sst2DSrcFmtShadow = pTDFX->stride;
839  TDFXWriteLong(pTDFX,SST_2D_SRCXY, (srcx&0x1FFF) | ((srcy&0x1FFF)<<16));
840  TDFXWriteLong(pTDFX,SST_2D_DSTSIZE, ((w+offset)&0x1FFF) | ((h&0x1FFF)<<16));
841  TDFXWriteLong(pTDFX,SST_2D_DSTXY, ((x-offset)&0x1FFF) | ((y&0x1FFF)<<16));
842  TDFXWriteLong(pTDFX,SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
843
844  pTDFX->prevBlitDest.y1=y;
845}
846#endif
847
848static void
849TDFXSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg,
850                                       int rop, unsigned int planemask)
851{
852  TDFXPtr pTDFX;
853
854  TDFXTRACEACCEL("SetupForCPUToScreenColorExpandFill bg=%x fg=%x rop=%d\n",
855                 bg, fg, rop);
856  pTDFX=TDFXPTR(pScrn);
857  TDFXClearState(pScrn);
858
859  pTDFX->Cmd|=SST_2D_HOSTTOSCRNBLIT|(TDFXROPCvt[rop]<<24);
860
861  if (bg == -1) {
862    pTDFX->Cmd |= SST_2D_TRANSPARENT_MONOCHROME;
863  }
864
865  TDFXMakeRoom(pTDFX, 2);
866  DECLARE(SSTCP_COLORBACK|SSTCP_COLORFORE);
867  TDFXWriteLong(pTDFX, SST_2D_COLORBACK, bg);
868  TDFXWriteLong(pTDFX, SST_2D_COLORFORE, fg);
869}
870
871static void
872TDFXSubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y,
873                                         int w, int h, int skipleft)
874{
875  TDFXPtr pTDFX;
876  int fmt;
877
878  TDFXTRACEACCEL("SubsequentCPUToScreenColorExpandFill x=%d y=%d w=%d h=%d"
879                 " skipleft=%d\n", x, y, w, h, skipleft);
880  pTDFX = TDFXPTR(pScrn);
881
882  /* We're changing clip1 anyway, so don't bother to reset it */
883  pTDFX->DrawState&=~DRAW_STATE_CLIP1CHANGED;
884  TDFXMatchState(pTDFX);
885  /* Make sure we use clip1 and flag it */
886  pTDFX->Cmd|=SST_2D_USECLIP1;
887  pTDFX->DrawState|=DRAW_STATE_CLIP1CHANGED;
888
889  if (pTDFX->cpp==1) fmt=(1<<16)|pTDFX->stride;
890  else fmt=((pTDFX->cpp+1)<<16)|pTDFX->stride;
891  pTDFX->scanlineWidth=w;
892
893  TDFXMakeRoom(pTDFX, 8);
894  DECLARE(SSTCP_CLIP1MIN|SSTCP_CLIP1MAX|SSTCP_SRCFORMAT|
895	  SSTCP_DSTFORMAT|SSTCP_DSTSIZE|SSTCP_SRCXY|
896	  SSTCP_DSTXY|SSTCP_COMMAND);
897  TDFXWriteLong(pTDFX, SST_2D_DSTFORMAT, fmt);
898  pTDFX->sst2DDstFmtShadow = fmt;
899  TDFXWriteLong(pTDFX, SST_2D_CLIP1MIN, ((y&0x1FFF)<<16)|(x&0x1FFF));
900  TDFXWriteLong(pTDFX, SST_2D_CLIP1MAX, (((y+h)&0x1FFF)<<16)|((x+w)&0x1FFF));
901#if X_BYTE_ORDER == X_BIG_ENDIAN
902  /* bit 20 byte swizzle */
903  TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT, ((((w+31)/32)*4) & 0x3FFF) | BIT(20));
904#else
905  TDFXWriteLong(pTDFX, SST_2D_SRCFORMAT,  (((w+31)/32)*4) & 0x3FFF);
906#endif
907  pTDFX->sst2DSrcFmtShadow = (((w+31)/32)*4) & 0x3FFF;
908  TDFXWriteLong(pTDFX, SST_2D_SRCXY, skipleft&0x1F);
909  TDFXWriteLong(pTDFX, SST_2D_DSTSIZE, ((w-skipleft)&0x1FFF)|((h&0x1FFF)<<16));
910  TDFXWriteLong(pTDFX, SST_2D_DSTXY, ((x+skipleft)&0x1FFF) | ((y&0x1FFF)<<16));
911  TDFXWriteLong(pTDFX, SST_2D_COMMAND, pTDFX->Cmd|SST_2D_GO);
912}
913
914static void TDFXSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
915{
916  TDFXPtr pTDFX;
917  int i, size, cnt;
918  CARD32 *pos;
919
920  TDFXTRACEACCEL("SubsequentColorExpandScanline bufno=%d\n", bufno);
921  pTDFX = TDFXPTR(pScrn);
922
923  cnt=(pTDFX->scanlineWidth+31)/32;
924  pos=(CARD32 *)pTDFX->scanlineColorExpandBuffers[bufno];
925  while (cnt>0) {
926    if (cnt>64) size=64;
927    else size=cnt;
928    TDFXMakeRoom(pTDFX, size);
929    DECLARE_LAUNCH(size, 0);
930    for (i=0; i<size; i++, pos++) {
931      TDFXWriteLong(pTDFX, SST_2D_LAUNCH, *pos);
932    }
933    cnt-=size;
934  }
935}
936
937