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