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