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