s3v_accel.c revision ba85709e
1
2/*
3Copyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9of the Software, and to permit persons to whom the Software is furnished to do
10so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of the XFree86 Project shall not
23be used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from the XFree86 Project.
25*/
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include "s3v.h"
32
33#include "miline.h"
34	/* fb includes are in s3v.h */
35#include "xaalocal.h"
36#include "xaarop.h"
37
38#include "servermd.h" /* LOG2_BYTES_PER_SCANLINE_PAD */
39
40static void S3VWriteMask(CARD32*, int);
41
42static void S3VEngineReset(ScrnInfoPtr pScrn);
43/* s3v.h - static void S3VAccelSync(ScrnInfoPtr); */
44static void S3VSetupForSolidFill(ScrnInfoPtr, int, int, unsigned);
45static void S3VSubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int);
46static void S3VSubsequentSolidFillRectPlaneMask(ScrnInfoPtr, int, int,
47				int, int);
48static void S3VSetupForMono8x8PatternFill(ScrnInfoPtr,int, int, int, int,
49                                int, unsigned int);
50static void S3VSubsequentMono8x8PatternFillRect(ScrnInfoPtr,int, int,
51                                int, int, int, int);
52static void S3VSubsequentMono8x8PatternFillRectPlaneMask(ScrnInfoPtr,int, int,
53                                int, int, int, int);
54static void S3VSetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int,
55				unsigned int, int);
56static void S3VSubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int,
57				int, int);
58static void S3VSetupForCPUToScreenColorExpand(ScrnInfoPtr, int, int, int,
59				unsigned int);
60static void S3VSubsequentCPUToScreenColorExpand(ScrnInfoPtr, int, int, int,
61				int, int);
62static void S3VSetupForImageWrite(ScrnInfoPtr, int, unsigned int, int,
63				int, int);
64static void S3VSubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int);
65static void S3VSubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int);
66static void S3VSubsequentSolidHorVertLinePlaneMask(ScrnInfoPtr, int, int,
67				int, int);
68#if 0
69static void S3VSubsequentSolidBresenhamLine(ScrnInfoPtr, int, int, int,
70				int, int, int, int);
71static void S3VPolylinesThinSolidWrapper(DrawablePtr, GCPtr, int, int,
72				DDXPointPtr);
73static void S3VPolySegmentThinSolidWrapper(DrawablePtr, GCPtr, int, xSegment*);
74#endif
75static void S3VNopAllCmdSets(ScrnInfoPtr pScrn);
76
77
78Bool
79S3VAccelInit(ScreenPtr pScreen)
80{
81    XAAInfoRecPtr infoPtr;
82    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
83    S3VPtr ps3v = S3VPTR(pScrn);
84    BoxRec AvailFBArea;
85
86    ps3v->AccelInfoRec = infoPtr = XAACreateInfoRec();
87    if(!infoPtr) return FALSE;
88
89    switch(ps3v->Chipset)
90      {
91      case S3_ViRGE:
92      case S3_ViRGE_VX:
93	ps3v->AccelFlags = BLT_BUG;
94	break;
95      default:
96	ps3v->AccelFlags = 0;
97	break;
98      }
99
100    ps3v->AccelFlags |= MONO_TRANS_BUG; /* which aren't broken ? */
101
102
103    infoPtr->Flags = PIXMAP_CACHE |
104		     LINEAR_FRAMEBUFFER |
105		     OFFSCREEN_PIXMAPS;
106
107    infoPtr->Sync = S3VAccelSync;
108
109    /* Problem reports with solid fill on trio3d */
110    if(!S3_TRIO_3D_SERIES(ps3v->Chipset))
111      {
112	/* Solid filled rects */
113	infoPtr->SetupForSolidFill =
114	  S3VSetupForSolidFill;
115	infoPtr->SubsequentSolidFillRect =
116	  S3VSubsequentSolidFillRect;
117      }
118
119    /* Screen to screen copies */
120    infoPtr->SetupForScreenToScreenCopy =
121        S3VSetupForScreenToScreenCopy;
122    infoPtr->SubsequentScreenToScreenCopy =
123        S3VSubsequentScreenToScreenCopy;
124    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
125
126    /* Mono 8x8 patterns */
127    infoPtr->SetupForMono8x8PatternFill =
128        S3VSetupForMono8x8PatternFill;
129    infoPtr->SubsequentMono8x8PatternFillRect =
130        S3VSubsequentMono8x8PatternFillRect;
131    infoPtr->Mono8x8PatternFillFlags = NO_TRANSPARENCY |
132				HARDWARE_PATTERN_PROGRAMMED_BITS |
133				HARDWARE_PATTERN_SCREEN_ORIGIN |
134				BIT_ORDER_IN_BYTE_MSBFIRST;
135
136
137#ifndef __alpha__
138
139    /* disable color expand on GX2 until we trace down */
140    /* lockups.  locate 'html'  in an xterm is a good  */
141    /* test case for an AGP GX2. */
142    if (!S3_ViRGE_GX2_SERIES(ps3v->Chipset))
143      {
144
145
146	/* CPU to screen color expansion */
147	infoPtr->CPUToScreenColorExpandFillFlags =  ROP_NEEDS_SOURCE |
148					CPU_TRANSFER_PAD_DWORD |
149                                        SCANLINE_PAD_DWORD |
150                                        BIT_ORDER_IN_BYTE_MSBFIRST |
151                                  	LEFT_EDGE_CLIPPING;
152
153	if(ps3v->AccelFlags & MONO_TRANS_BUG)
154	  infoPtr->CPUToScreenColorExpandFillFlags |=  NO_TRANSPARENCY;
155
156	infoPtr->ColorExpandRange = 0x8000;
157	infoPtr->ColorExpandBase = ps3v->MapBaseDense;
158	infoPtr->SetupForCPUToScreenColorExpandFill =
159                S3VSetupForCPUToScreenColorExpand;
160	infoPtr->SubsequentCPUToScreenColorExpandFill =
161                S3VSubsequentCPUToScreenColorExpand;
162
163      } /* if(!GX2...) */
164
165
166    /* Image Writes */
167    infoPtr->ImageWriteFlags =  	ROP_NEEDS_SOURCE |
168					NO_TRANSPARENCY |
169					CPU_TRANSFER_PAD_DWORD |
170					SCANLINE_PAD_DWORD |
171					NO_GXCOPY |  /* added - kjb */
172					LEFT_EDGE_CLIPPING;
173
174    infoPtr->ImageWriteRange = 0x8000;
175    infoPtr->ImageWriteBase = ps3v->MapBaseDense;
176    infoPtr->SetupForImageWrite = S3VSetupForImageWrite;
177    infoPtr->SubsequentImageWriteRect = S3VSubsequentImageWriteRect;
178
179    /* on alpha, I see corruption in the xscreensaver program "hypercube"
180       as the line acceleration is just stubs, it loses us nothing to
181       disable it on alphas */
182
183    /* Lines */
184#if 0
185    /* Bresenham lines are broken when passed through fb to xaa
186       so I pulled all the line functions.  This shouldn't hurt us
187       a whole lot, since the Subsequent..Bresen stuff doesn't have
188       any hardware accel yet anyway...  And xaa will do horiz/vert
189       lines with the rect fill (like we are doing here) anyway.
190       KJB 9/11/00
191    */
192    infoPtr->SetupForSolidLine = S3VSetupForSolidFill;
193    infoPtr->SubsequentSolidHorVertLine = S3VSubsequentSolidHorVertLine;
194    infoPtr->SubsequentSolidBresenhamLine = S3VSubsequentSolidBresenhamLine;
195    infoPtr->PolySegmentThinSolid = S3VPolySegmentThinSolidWrapper;
196    infoPtr->PolylinesThinSolid = S3VPolylinesThinSolidWrapper;
197#endif
198
199#endif /* !__alpha__ */
200
201    /* And these are screen parameters used to setup the GE */
202
203     ps3v->Width = pScrn->displayWidth;
204     					/* Bytes per pixel */
205     ps3v->Bpp = pScrn->bitsPerPixel / 8;
206     					/* Bytes per line */
207     ps3v->Bpl = ps3v->Width * ps3v->Bpp;
208     					/* ScissB is max height, minus 1k */
209					/* for hwcursor?, then limited by */
210					/* ViRGE max height register of   */
211					/* 2047 */
212     ps3v->ScissB = (pScrn->videoRam * 1024 - 1024) / ps3v->Bpl;
213     if (ps3v->ScissB > 2047)
214         ps3v->ScissB = 2047;
215
216
217    S3VEngineReset(pScrn);
218
219
220    AvailFBArea.x1 = 0;
221    AvailFBArea.y1 = 0;
222    AvailFBArea.x2 = pScrn->displayWidth;
223    AvailFBArea.y2 = (pScrn->videoRam * 1024 - 1024) /
224		     (pScrn->displayWidth * pScrn->bitsPerPixel / 8);
225
226    xf86InitFBManager(pScreen, &AvailFBArea);
227
228    /* make sure offscreen pixmaps aren't bigger than our address space */
229    infoPtr->maxOffPixWidth  = 2048;
230    infoPtr->maxOffPixHeight = 2048;
231
232    return (XAAInit(pScreen, infoPtr));
233}
234
235
236Bool
237S3VAccelInit32(ScreenPtr pScreen)
238{
239   return FALSE;
240}
241
242void
243S3VNopAllCmdSets(ScrnInfoPtr pScrn)
244{
245  int i;
246  int max_it=1000;
247  S3VPtr ps3v = S3VPTR(pScrn);
248
249  if (xf86GetVerbosity() > 1) {
250     ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#1 = 0x%08lx\n",
251        (unsigned long)IN_SUBSYS_STAT());
252  }
253
254  mem_barrier();
255  for(i=0;i<max_it;i++) {
256    if( (IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) == 0x20002000) {
257      break;
258    }
259  }
260
261  if(i!=max_it) {
262    if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state changed after %d iterations\n",i);
263  } else {
264    if (xf86GetVerbosity() > 1) ErrorF("\tTrio3D -- S3VNopAllCmdSets: state DIDN'T changed after %d iterations\n",max_it);
265  }
266
267  WaitQueue(5);
268
269  OUTREG(CMD_SET, CMD_NOP);
270
271  if (xf86GetVerbosity() > 1) {
272     ErrorF("\tTrio3D -- S3VNopAllCmdSets: SubsysStats#2 = 0x%08lx\n",
273        (unsigned long)IN_SUBSYS_STAT());
274  }
275}
276
277void
278S3VGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file)
279{
280    unsigned long gs1, gs2;   /* -- debug info for graphics state -- */
281    unsigned char tmp, sr1, resetidx=0x66;  /* FIXME */
282    int r;
283    int ge_was_on = 0;
284    CARD32 fifo_control = 0, miu_control = 0;
285    CARD32 streams_timeout = 0, misc_timeout = 0;
286    vgaHWPtr hwp = VGAHWPTR(pScrn);
287	S3VPtr ps3v = S3VPTR(pScrn);
288  	int vgaCRIndex, vgaCRReg, vgaIOBase;
289  	vgaIOBase = hwp->IOBase;
290  	vgaCRIndex = vgaIOBase + 4;
291  	vgaCRReg = vgaIOBase + 5;
292
293
294    if (S3_TRIO_3D_SERIES(ps3v->Chipset)) {
295      VGAOUT8(0x3c4,0x01);
296      sr1 = VGAIN8(0x3c5);
297
298      if (sr1 & 0x20) {
299        if (xf86GetVerbosity() > 1)
300          ErrorF("\tTrio3D -- Display is on...turning off\n");
301        VGAOUT8(0x3c5,sr1 & ~0x20);
302        VerticalRetraceWait();
303      }
304    }
305
306    if (from_timeout) {
307      if (ps3v->GEResetCnt++ < 10 || xf86GetVerbosity() > 1)
308	ErrorF("\tS3VGEReset called from %s line %d\n",file,line);
309    }
310    else {
311      if (S3_TRIO_3D_SERIES(ps3v->Chipset))
312        S3VNopAllCmdSets(pScrn);
313      WaitIdleEmpty();
314    }
315
316
317    if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX || ps3v->Chipset == S3_ViRGE_DXGX)) {
318      /* reset will trash these registers, so save them */
319      fifo_control    = INREG(FIFO_CONTROL_REG);
320      miu_control     = INREG(MIU_CONTROL_REG);
321      streams_timeout = INREG(STREAMS_TIMEOUT_REG);
322      misc_timeout    = INREG(MISC_TIMEOUT_REG);
323    }
324
325    if(ps3v->Chipset == S3_ViRGE_VX){
326        VGAOUT8(vgaCRIndex, 0x63);
327        }
328    else {
329        VGAOUT8(vgaCRIndex, 0x66);
330        }
331  if (!S3_TRIO_3D_SERIES(ps3v->Chipset)) {
332    tmp = VGAIN8(vgaCRReg);
333
334    usleep(10000);
335    for (r=1; r<10; r++) {  /* try multiple times to avoid lockup of ViRGE/MX */
336      VGAOUT8(vgaCRReg, tmp | 0x02);
337      usleep(10000);
338      VGAOUT8(vgaCRReg, tmp & ~0x02);
339      usleep(10000);
340
341      xf86ErrorFVerb(VERBLEV, "	S3VGEReset sub_stat=%lx \n",
342   	(unsigned long)IN_SUBSYS_STAT()
343	);
344
345      if (!from_timeout)
346        WaitIdleEmpty();
347
348      OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
349
350      usleep(10000);
351      if (((IN_SUBSYS_STAT() & 0x3f00) != 0x3000))
352	xf86ErrorFVerb(VERBLEV, "restarting S3 graphics engine reset %2d ...\n",r);
353      else
354	break;
355    }
356    } else {
357    usleep(10000);
358
359    for (r=1; r<10; r++) {
360      VerticalRetraceWait();
361      VGAOUT8(vgaCRIndex,resetidx);
362      tmp = VGAIN8(vgaCRReg);
363
364      VGAOUT8(0x3c4,0x01);
365      sr1 = VGAIN8(0x3c5);
366
367      if(sr1 & 0x20) {
368        if(xf86GetVerbosity() > 1) {
369          ErrorF("\tTrio3D -- Upps Display is on again ...turning off\n");
370        }
371        VGAOUT8(0x3c4,0x01);
372        VerticalRetraceWait();
373        VGAOUT8(0x3c5,sr1 & ~0x20);
374      }
375
376      VerticalRetraceWait();
377      gs1   = (long) IN_SUBSYS_STAT();
378
379      /* turn off the GE */
380
381      VGAOUT8(vgaCRIndex,resetidx);
382      if(tmp & 0x01) {
383	/*        tmp &= ~0x01; */
384        VGAOUT8(vgaCRReg, tmp);
385        ge_was_on = 1;
386        usleep(10000);
387      }
388
389      gs2   = (long) IN_SUBSYS_STAT();
390      VGAOUT8(vgaCRReg, (tmp | 0x02));
391      usleep(10000);
392
393      VerticalRetraceWait();
394      VGAOUT8(vgaCRIndex,resetidx);
395      VGAOUT8(vgaCRReg, (tmp & ~0x02));
396      usleep(10000);
397
398      if(ge_was_on) {
399        tmp |= 0x01;
400        VGAOUT8(vgaCRReg, tmp);
401        usleep(10000);
402      }
403
404      if (xf86GetVerbosity() > 2) {
405          ErrorF("\tTrio3D -- GE was %s ST#1: 0x%08lx ST#2: 0x%08lx\n",
406		 (ge_was_on) ? "on" : "off", gs1, gs2);
407      }
408
409      VerticalRetraceWait();
410
411      if (!from_timeout) {
412	S3VNopAllCmdSets(pScrn);
413        WaitIdleEmpty();
414      }
415
416      OUTREG(DEST_SRC_STR, ps3v->Bpl << 16 | ps3v->Bpl);
417      usleep(10000);
418
419      if((IN_SUBSYS_STAT() & 0x3f802000 & 0x20002000) != 0x20002000) {
420        if(xf86GetVerbosity() > 1)
421          ErrorF("restarting S3 graphics engine reset %2d ...%lx\n",
422		 r, (unsigned long)IN_SUBSYS_STAT());
423      }
424        else
425          break;
426    }
427    }
428
429    if (from_timeout && (ps3v->Chipset == S3_ViRGE || ps3v->Chipset == S3_ViRGE_VX
430			 || ps3v->Chipset == S3_ViRGE_DXGX)) {
431      /* restore trashed registers */
432      OUTREG(FIFO_CONTROL_REG, fifo_control);
433      OUTREG(MIU_CONTROL_REG, miu_control);
434      OUTREG(STREAMS_TIMEOUT_REG, streams_timeout);
435      OUTREG(MISC_TIMEOUT_REG, misc_timeout);
436    }
437
438    WAITFIFO(2);
439/*      SETB_SRC_BASE(0); */
440/*      SETB_DEST_BASE(0);    */
441    OUTREG(SRC_BASE, 0);
442    OUTREG(DEST_BASE, 0);
443
444  	WAITFIFO(4);
445    OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
446    OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
447    OUTREG(MONO_PAT_0, ~0);
448    OUTREG(MONO_PAT_1, ~0);
449
450    if (!from_timeout && S3_TRIO_3D_SERIES(ps3v->Chipset))
451      S3VNopAllCmdSets(pScrn);
452}
453
454/* The sync function for the GE */
455void
456S3VAccelSync(ScrnInfoPtr pScrn)
457{
458    S3VPtr ps3v = S3VPTR(pScrn);
459
460    WAITIDLE();
461}
462
463
464static void
465S3VEngineReset(ScrnInfoPtr pScrn)
466{
467    S3VPtr ps3v = S3VPTR(pScrn);
468
469    ps3v->SrcBaseY = 0;
470    ps3v->DestBaseY = 0;
471    ps3v->Stride = pScrn->displayWidth * pScrn->bitsPerPixel >> 3;
472
473    switch(pScrn->bitsPerPixel) {
474    case 8: 	ps3v->CommonCmd = DRAW | DST_8BPP;
475		ps3v->FullPlaneMask = 0x000000ff;
476		ps3v->bltbug_width1 = 51;
477		ps3v->bltbug_width2 = 64;
478		break;
479    case 16: 	ps3v->CommonCmd = DRAW | DST_16BPP;
480		ps3v->FullPlaneMask = 0x0000ffff;
481		ps3v->bltbug_width1 = 26;
482		ps3v->bltbug_width2 = 32;
483		break;
484    case 24: 	ps3v->CommonCmd = DRAW | DST_24BPP;
485		ps3v->FullPlaneMask = 0x00ffffff;
486		ps3v->bltbug_width1 = 16;
487		ps3v->bltbug_width2 = 22;
488		break;
489    }
490
491
492    WAITFIFO(5);
493    OUTREG(SRC_BASE, 0);
494    OUTREG(DEST_BASE, 0);
495    OUTREG(DEST_SRC_STR, ps3v->Stride | (ps3v->Stride << 16));
496
497    OUTREG(CLIP_L_R, ((0) << 16) | ps3v->Width);
498    OUTREG(CLIP_T_B, ((0) << 16) | ps3v->ScissB);
499}
500
501
502static void
503S3VWriteMask(
504   CARD32 *dstBase,
505   int dwords
506){
507  /* on alphas, be sure to call this with MapBaseDense, not MapBase! */
508   int numLeft;
509   CARD32 *dst = dstBase;
510
511   while(dwords >= 8192) {
512	numLeft = 8192;
513	while(numLeft) {
514	  dst[0] = ~0; dst[1] = ~0;
515	  dst[2] = ~0; dst[3] = ~0;
516	  dst += 4;
517	  numLeft -= 4;
518	}
519	dwords -= 8192;
520	dst = dstBase;
521   }
522   while(dwords >= 4) {
523	dst[0] = ~0; dst[1] = ~0;
524	dst[2] = ~0; dst[3] = ~0;
525	dst += 4;
526	dwords -= 4;
527   }
528   if(!dwords) return;
529   dst[0] = ~0;
530   if(dwords == 1) return;
531   dst[1] = ~0;
532   if(dwords == 2) return;
533   dst[2] = ~0;
534
535   return;
536}
537
538
539	/************************\
540	|  Solid Filled Rects    |
541	\************************/
542
543static void
544S3VSetupForSolidFill(
545   ScrnInfoPtr pScrn,
546   int color, int rop,
547   unsigned int planemask
548){
549    S3VPtr ps3v = S3VPTR(pScrn);
550    int mix;
551
552    mix = XAAHelpSolidROP(pScrn, &color, planemask, &rop);
553
554    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
555			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
556
557    if(mix & ROP_SRC) {
558	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
559	ps3v->AccelInfoRec->SubsequentSolidFillRect =
560		S3VSubsequentSolidFillRectPlaneMask;
561	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
562		S3VSubsequentSolidHorVertLinePlaneMask;
563	WAITFIFO(5);
564	OUTREG(SRC_FG_CLR, planemask);
565    } else {
566	ps3v->AccelInfoRec->SubsequentSolidFillRect =
567		S3VSubsequentSolidFillRect;
568	ps3v->AccelInfoRec->SubsequentSolidHorVertLine =
569		S3VSubsequentSolidHorVertLine;
570	WAITFIFO(4);
571    }
572
573    if(mix & ROP_PAT) {
574	ps3v->AccelCmd |= MIX_MONO_PATT;
575	OUTREG(PAT_FG_CLR, color);
576	OUTREG(MONO_PAT_0, ~0);
577	OUTREG(MONO_PAT_1, ~0);
578    }
579
580    OUTREG(CMD_SET, ps3v->AccelCmd);
581}
582
583
584void
585S3VSubsequentSolidFillRect(
586   ScrnInfoPtr pScrn,
587   int x, int y,
588   int w, int h
589){
590    S3VPtr ps3v = S3VPTR(pScrn);
591
592    CHECK_DEST_BASE(y,h);
593
594    WAITFIFO(2);
595    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
596    WAITCMD();
597    OUTREG(RDEST_XY, (x << 16) | y);
598}
599
600
601void
602S3VSubsequentSolidFillRectPlaneMask(
603   ScrnInfoPtr pScrn,
604   int x, int y,
605   int w, int h
606){
607    S3VPtr ps3v = S3VPTR(pScrn);
608    int dwords;
609
610    CHECK_DEST_BASE(y,h);
611
612    dwords = ((w + 31) >> 5) * h;
613
614    WAITFIFO(2);
615    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
616    WAITCMD();
617    OUTREG(RDEST_XY, (x << 16) | y);
618    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
619}
620
621
622	/**************************\
623	|  Screen to Screen Copies |
624	\**************************/
625
626static void
627S3VSetupForScreenToScreenCopy(
628   ScrnInfoPtr pScrn,
629   int xdir, int ydir,
630   int rop,
631   unsigned int planemask,
632   int trans
633){
634    S3VPtr ps3v = S3VPTR(pScrn);
635
636    planemask &= ps3v->FullPlaneMask;
637    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT;
638
639    if(planemask != ps3v->FullPlaneMask) {
640        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
641	WAITFIFO(4);
642	OUTREG(PAT_FG_CLR, planemask);
643	OUTREG(MONO_PAT_0, ~0);
644	OUTREG(MONO_PAT_1, ~0);
645        }
646    else {
647        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
648	WAITFIFO(1);
649        }
650    if(xdir == 1) ps3v->AccelCmd |= CMD_XP;
651    if(ydir == 1) ps3v->AccelCmd |= CMD_YP;
652
653    OUTREG(CMD_SET, ps3v->AccelCmd);
654}
655
656
657static void
658S3VSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
659        int x2, int y2, int w, int h)
660{
661    S3VPtr ps3v = S3VPTR(pScrn);
662
663    CHECK_SRC_BASE(y1,h);
664    CHECK_DEST_BASE(y2,h);
665
666    w--;
667
668    if(!(ps3v->AccelCmd & CMD_YP)) {
669	y1 += h - 1; y2 += h - 1;
670    }
671
672    if(!(ps3v->AccelCmd & CMD_XP)) {
673	x1 += w; x2 += w;
674    }
675
676    WAITFIFO(3);
677    OUTREG(RWIDTH_HEIGHT, (w << 16) | h);
678    OUTREG(RSRC_XY, (x1 << 16) | y1);
679    WAITCMD();
680    OUTREG(RDEST_XY, (x2 << 16) | y2);
681}
682
683
684	/*********************\
685	|  8x8 Pattern fills  |
686	\*********************/
687
688
689static void
690S3VSetupForMono8x8PatternFill(
691    ScrnInfoPtr pScrn,
692    int patx, int paty,
693    int fg, int bg,
694    int rop, unsigned int planemask
695){
696    S3VPtr ps3v = S3VPTR(pScrn);
697    int mix;
698
699    mix = XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop);
700
701    ps3v->AccelCmd = ps3v->CommonCmd | (rop << 17) |
702			CMD_XP | CMD_YP | CMD_AUTOEXEC | CMD_BITBLT;
703
704    if(mix & ROP_SRC) {
705 	ps3v->AccelCmd |= MIX_CPUDATA | CMD_ITA_DWORD | MIX_MONO_SRC;
706	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
707		S3VSubsequentMono8x8PatternFillRectPlaneMask;
708	WAITFIFO(6);
709	OUTREG(SRC_FG_CLR, planemask);
710    } else {
711	ps3v->AccelInfoRec->SubsequentMono8x8PatternFillRect =
712		S3VSubsequentMono8x8PatternFillRect;
713	WAITFIFO(5);
714    }
715
716    if(mix & ROP_PAT) {
717	ps3v->AccelCmd |= MIX_MONO_PATT;
718	OUTREG(PAT_FG_CLR, fg);
719	OUTREG(PAT_BG_CLR, bg);
720	OUTREG(MONO_PAT_0, patx);
721	OUTREG(MONO_PAT_1, paty);
722    }
723
724    OUTREG(CMD_SET, ps3v->AccelCmd);
725}
726
727
728static void
729S3VSubsequentMono8x8PatternFillRect(
730    ScrnInfoPtr pScrn,
731    int patx, int paty,
732    int x, int y, int w, int h
733){
734    S3VPtr ps3v = S3VPTR(pScrn);
735
736    CHECK_DEST_BASE(y,h);
737
738    WAITFIFO(2);
739    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
740    WAITCMD();
741    OUTREG(RDEST_XY, (x << 16) | y);
742}
743
744
745static void
746S3VSubsequentMono8x8PatternFillRectPlaneMask(
747    ScrnInfoPtr pScrn,
748    int patx, int paty,
749    int x, int y, int w, int h
750){
751    S3VPtr ps3v = S3VPTR(pScrn);
752    int dwords;
753
754    CHECK_DEST_BASE(y,h);
755
756    dwords = ((w + 31) >> 5) * h;
757
758    WAITFIFO(2);
759    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
760    WAITCMD();
761    OUTREG(RDEST_XY, (x << 16) | y);
762
763    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
764}
765
766	/*********************************\
767	|  CPU to Screen Color Expansion  |
768	\*********************************/
769
770
771static void
772S3VSetupForCPUToScreenColorExpand(
773    ScrnInfoPtr pScrn,
774    int fg, int bg,
775    int rop,
776    unsigned int planemask
777){
778    S3VPtr ps3v = S3VPTR(pScrn);
779
780    planemask &= ps3v->FullPlaneMask;
781    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
782		CMD_XP | CMD_YP | CMD_ITA_DWORD | CMD_HWCLIP |
783		MIX_CPUDATA | MIX_MONO_SRC;
784
785
786    if(planemask == ps3v->FullPlaneMask) {
787        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
788	WAITFIFO(3);
789    } else {
790        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
791	WAITFIFO(6);
792	OUTREG(MONO_PAT_0, ~0);
793	OUTREG(MONO_PAT_1, ~0);
794        OUTREG(PAT_FG_CLR, planemask);
795    }
796
797    if(bg == -1)
798	ps3v->AccelCmd |= MIX_MONO_TRANSP;
799    else
800	OUTREG(SRC_BG_CLR, bg);
801
802    OUTREG(SRC_FG_CLR, fg);
803    OUTREG(CMD_SET, ps3v->AccelCmd);
804}
805
806
807void
808S3VSubsequentCPUToScreenColorExpand(
809    ScrnInfoPtr pScrn,
810    int x, int y,
811    int w, int h,
812    int skipleft
813){
814    S3VPtr ps3v = S3VPTR(pScrn);
815
816    CHECK_DEST_BASE(y,h);
817    WAITFIFO(3);
818    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
819    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
820    WAITCMD();
821    OUTREG(RDEST_XY, (x << 16) | y);
822}
823
824
825    /****************\
826    |  Image Writes  |
827    \****************/
828
829
830static void
831S3VSetupForImageWrite(
832   ScrnInfoPtr pScrn,
833   int rop, unsigned int planemask,
834   int trans_color, int bpp, int depth
835){
836    S3VPtr ps3v = S3VPTR(pScrn);
837
838    planemask &= ps3v->FullPlaneMask;
839    ps3v->AccelCmd = ps3v->CommonCmd | CMD_AUTOEXEC | CMD_BITBLT |
840		MIX_CPUDATA | CMD_ITA_DWORD | CMD_HWCLIP | CMD_XP | CMD_YP;
841
842    if(planemask != ps3v->FullPlaneMask) {
843        ps3v->AccelCmd |= (XAAGetCopyROP_PM(rop) << 17) | MIX_MONO_PATT;
844	WAITFIFO(4);
845	OUTREG(PAT_FG_CLR, planemask);
846	OUTREG(MONO_PAT_0, ~0);
847	OUTREG(MONO_PAT_1, ~0);
848    } else {
849        ps3v->AccelCmd |= XAAGetCopyROP(rop) << 17;
850	WAITFIFO(1);
851    }
852
853    OUTREG(CMD_SET, ps3v->AccelCmd);
854}
855
856
857static void
858S3VSubsequentImageWriteRect(
859    ScrnInfoPtr pScrn,
860    int x, int y,
861    int w, int h,
862    int skipleft
863){
864    S3VPtr ps3v = S3VPTR(pScrn);
865
866    CHECK_DEST_BASE(y,h);
867
868    WAITFIFO(3);
869    OUTREG(CLIP_L_R, ((x + skipleft) << 16) | 0xffff);
870    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
871    WAITCMD();
872    OUTREG(RDEST_XY, (x << 16) | y);
873}
874
875
876	/***********\
877	|   Lines   |
878	\***********/
879
880
881#if 0   /* Some line funcs are disabled at the moment */
882
883static void
884S3VPolylinesThinSolidWrapper(
885   DrawablePtr     pDraw,
886   GCPtr           pGC,
887   int             mode,
888   int             npt,
889   DDXPointPtr     pPts
890){
891    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
892    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
893    ps3v->CurrentGC = pGC;
894    /* fb support */
895    ps3v->CurrentDrawable = pDraw;
896    if(infoRec->NeedToSync)
897	S3VAccelSync(infoRec->pScrn);
898    XAAPolyLines(pDraw, pGC, mode, npt, pPts);
899}
900
901static void
902S3VPolySegmentThinSolidWrapper(
903   DrawablePtr     pDraw,
904   GCPtr           pGC,
905   int             nseg,
906   xSegment        *pSeg
907){
908    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
909    S3VPtr ps3v = S3VPTR(infoRec->pScrn);
910    ps3v->CurrentGC = pGC;
911    /* fb support */
912    ps3v->CurrentDrawable = pDraw;
913    if(infoRec->NeedToSync)
914	S3VAccelSync(infoRec->pScrn);
915    XAAPolySegment(pDraw, pGC, nseg, pSeg);
916}
917
918#endif
919
920static void
921S3VSubsequentSolidHorVertLine(
922    ScrnInfoPtr pScrn,
923    int x, int y,
924    int len, int dir
925){
926    S3VPtr ps3v = S3VPTR(pScrn);
927    int w, h;
928
929    if(dir == DEGREES_0) {
930	w = len; h = 1;
931    } else {
932	w = 1; h = len;
933    }
934
935    CHECK_DEST_BASE(y,h);
936
937    WAITFIFO(2);
938    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
939    WAITCMD();
940    OUTREG(RDEST_XY, (x << 16) | y);
941}
942
943static void
944S3VSubsequentSolidHorVertLinePlaneMask(
945    ScrnInfoPtr pScrn,
946    int x, int y,
947    int len, int dir
948){
949    S3VPtr ps3v = S3VPTR(pScrn);
950    int w, h, dwords;
951
952    if(dir == DEGREES_0) {
953	w = len; h = 1; dwords = (len + 31) >> 5;
954    } else {
955	w = 1; h = len; dwords = len;
956    }
957
958    CHECK_DEST_BASE(y,h);
959
960    WAITFIFO(2);
961    OUTREG(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
962    WAITCMD();
963    OUTREG(RDEST_XY, (x << 16) | y);
964
965    S3VWriteMask((CARD32*)ps3v->MapBaseDense, dwords);
966}
967
968
969void
970S3VWaitFifoGX2(S3VPtr ps3v, int slots )
971{
972  if(ps3v->NoPCIRetry)
973    while(((INREG(SUBSYS_STAT_REG) >> 9) & 0x60) < slots){}
974}
975
976
977
978void
979S3VWaitFifoMain(S3VPtr ps3v, int slots )
980{
981  if(ps3v->NoPCIRetry)
982    while(((INREG(SUBSYS_STAT_REG) >> 8) & 0x1f) < slots){}
983}
984
985
986void
987S3VWaitCmdGX2(S3VPtr ps3v)
988{
989  while(((INREG(ADV_FUNC_CNTR) >> 6) & 0x1f) != 16){}
990}
991
992
993void
994S3VWaitDummy(S3VPtr ps3v)
995{
996  /* do nothing */
997}
998
999/*EOF*/
1000
1001