3 * 2D acceleration for SiS5597/5598 and 6326
5 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England.
6 * Parts Copyright (C) 2001-2004 Thomas Winischhofer, Vienna, Austria.
8 * Licensed under the following terms:
10 * Permission to use, copy, modify, distribute, and sell this software and its
11 * documentation for any purpose is hereby granted without fee, provided that
12 * the above copyright notice appears in all copies and that both that copyright
13 * notice and this permission notice appear in supporting documentation, and
14 * and that the name of the copyright holder not be used in advertising
15 * or publicity pertaining to distribution of the software without specific,
16 * written prior permission. The copyright holder makes no representations
17 * about the suitability of this software for any purpose. It is provided
18 * "as is" without expressed or implied warranty.
20 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
22 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
23 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
24 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
25 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
26 * PERFORMANCE OF THIS SOFTWARE.
28 * Authors: Alan Hourihane <alanh@fairlite.demon.co.uk>,
29 * Mike Chapman <mike@paranoia.com>,
30 * Juanjo Santamarta <santamarta@ctv.es>,
31 * Mitani Hiroshi <hmitani@drl.mei.co.jp>,
32 * David Thomas <davtom@dream.org.uk>,
33 * Thomas Winischhofer <thomas@winischhofer.net>.
37 #define CTSCE /* TW: Include enhanced color expansion code */
38 #endif /* This produces drawing errors sometimes */
41 #include "xf86_OSproc.h"
42 #include "xf86_ansic.h"
44 #include "xf86PciInfo.h"
47 #include "sis_accel.h"
52 static void SiSSync(ScrnInfoPtr pScrn
);
53 static void SiSSetupForFillRectSolid(ScrnInfoPtr pScrn
, int color
,
54 int rop
, unsigned int planemask
);
55 static void SiSSubsequentFillRectSolid(ScrnInfoPtr pScrn
, int x
,
57 static void SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn
,
58 int xdir
, int ydir
, int rop
,
59 unsigned int planemask
, int transparency_color
);
60 static void SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn
,
61 int x1
, int y1
, int x2
,
62 int y2
, int w
, int h
);
63 static void SiSSetupForMono8x8PatternFill(ScrnInfoPtr pScrn
,
64 int patternx
, int patterny
, int fg
, int bg
,
65 int rop
, unsigned int planemask
);
66 static void SiSSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn
,
67 int patternx
, int patterny
, int x
, int y
,
70 static void SiSSetupForScreenToScreenColorExpandFill (ScrnInfoPtr pScrn
,
72 int rop
, unsigned int planemask
);
73 static void SiSSubsequentScreenToScreenColorExpandFill( ScrnInfoPtr pScrn
,
74 int x
, int y
, int w
, int h
,
75 int srcx
, int srcy
, int offset
);
77 static void SiSSetClippingRectangle ( ScrnInfoPtr pScrn
,
78 int left
, int top
, int right
, int bottom
);
79 static void SiSDisableClipping (ScrnInfoPtr pScrn
);
80 static void SiSSetupForSolidLine(ScrnInfoPtr pScrn
,
81 int color
, int rop
, unsigned int planemask
);
82 static void SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn
,
83 int x1
, int y1
, int x2
, int y2
, int flags
);
84 static void SiSSubsequentSolidHorVertLine(ScrnInfoPtr pScrn
,
85 int x
, int y
, int len
, int dir
);
87 static void SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn
,
88 int fg
, int bg
, int rop
,
89 unsigned int planemask
);
90 static void SiSSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn
,
91 int x
, int y
, int w
, int h
,
93 static void SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn
, int bufno
);
97 SiSAccelInit(ScreenPtr pScreen
)
99 XAAInfoRecPtr infoPtr
;
100 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
101 SISPtr pSiS
= SISPTR(pScrn
);
106 unsigned char *AvailBufBase
;
108 pSiS
->AccelInfoPtr
= infoPtr
= XAACreateInfoRec();
109 if (!infoPtr
) return FALSE
;
111 infoPtr
->Flags
= LINEAR_FRAMEBUFFER
|
116 infoPtr
->Sync
= SiSSync
;
118 /* Screen To Screen copy */
119 infoPtr
->SetupForScreenToScreenCopy
= SiSSetupForScreenToScreenCopy
;
120 infoPtr
->SubsequentScreenToScreenCopy
= SiSSubsequentScreenToScreenCopy
;
121 infoPtr
->ScreenToScreenCopyFlags
= NO_TRANSPARENCY
| NO_PLANEMASK
;
124 infoPtr
->SetupForSolidFill
= SiSSetupForFillRectSolid
;
125 infoPtr
->SubsequentSolidFillRect
= SiSSubsequentFillRectSolid
;
126 infoPtr
->SolidFillFlags
= NO_PLANEMASK
;
128 /* On 5597/5598 and 6326, clipping and lines only work
129 for 1024, 2048, 4096 logical width */
130 if(pSiS
->ValidWidth
) {
132 infoPtr
->SetClippingRectangle
= SiSSetClippingRectangle
;
133 infoPtr
->DisableClipping
= SiSDisableClipping
;
134 infoPtr
->ClippingFlags
=
135 HARDWARE_CLIP_SOLID_LINE
|
136 HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY
|
137 HARDWARE_CLIP_MONO_8x8_FILL
|
138 HARDWARE_CLIP_SOLID_FILL
;
141 infoPtr
->SetupForSolidLine
= SiSSetupForSolidLine
;
142 infoPtr
->SubsequentSolidTwoPointLine
= SiSSubsequentSolidTwoPointLine
;
143 infoPtr
->SubsequentSolidHorVertLine
= SiSSubsequentSolidHorVertLine
;
144 infoPtr
->SolidLineFlags
= NO_PLANEMASK
;
147 if(pScrn
->bitsPerPixel
!= 24) {
148 /* 8x8 mono pattern */
149 infoPtr
->SetupForMono8x8PatternFill
= SiSSetupForMono8x8PatternFill
;
150 infoPtr
->SubsequentMono8x8PatternFillRect
= SiSSubsequentMono8x8PatternFillRect
;
151 infoPtr
->Mono8x8PatternFillFlags
=
153 HARDWARE_PATTERN_PROGRAMMED_BITS
|
154 HARDWARE_PATTERN_PROGRAMMED_ORIGIN
|
155 BIT_ORDER_IN_BYTE_MSBFIRST
;
159 if(pScrn
->bitsPerPixel
!= 24) {
160 /* TW: per-scanline color expansion (using indirect method) */
161 pSiS
->ColorExpandBufferNumber
= 4;
162 pSiS
->ColorExpandBufferCountMask
= 0x03;
163 pSiS
->PerColorExpandBufferSize
= ((pScrn
->virtualX
+ 31) / 32) * 4;
165 infoPtr
->NumScanlineColorExpandBuffers
= pSiS
->ColorExpandBufferNumber
;
166 infoPtr
->ScanlineColorExpandBuffers
= (unsigned char **)&pSiS
->ColorExpandBufferAddr
[0];
168 infoPtr
->SetupForScanlineCPUToScreenColorExpandFill
=
169 SiSSetupForScanlineCPUToScreenColorExpandFill
;
170 infoPtr
->SubsequentScanlineCPUToScreenColorExpandFill
=
171 SiSSubsequentScanlineCPUToScreenColorExpandFill
;
172 infoPtr
->SubsequentColorExpandScanline
=
173 SiSSubsequentColorExpandScanline
;
174 infoPtr
->ScanlineCPUToScreenColorExpandFillFlags
=
176 CPU_TRANSFER_PAD_DWORD
|
178 BIT_ORDER_IN_BYTE_MSBFIRST
|
181 pSiS
->ColorExpandBufferNumber
= 0;
184 pSiS
->ColorExpandBufferNumber
= 0;
187 topFB
= pSiS
->maxxfbmem
;
189 reservedFbSize
= pSiS
->ColorExpandBufferNumber
* pSiS
->PerColorExpandBufferSize
;
191 UsableFbSize
= topFB
- reservedFbSize
;
193 /* Layout: (Sizes do not reflect correct proportions)
194 * |--------------++++++++++++++++++++| ====================~~~~~~~~~~~~|
195 * UsableFbSize ColorExpandBuffers | TurboQueue HWCursor
199 if(pSiS
->ColorExpandBufferNumber
) {
200 AvailBufBase
= pSiS
->FbBase
+ UsableFbSize
;
201 for (i
= 0; i
< pSiS
->ColorExpandBufferNumber
; i
++) {
202 pSiS
->ColorExpandBufferAddr
[i
] = AvailBufBase
+
203 i
* pSiS
->PerColorExpandBufferSize
;
204 pSiS
->ColorExpandBufferScreenOffset
[i
] = UsableFbSize
+
205 i
* pSiS
->PerColorExpandBufferSize
;
210 AvailFBArea
.x2
= pScrn
->displayWidth
;
211 AvailFBArea
.y2
= UsableFbSize
/ (pScrn
->displayWidth
* pScrn
->bitsPerPixel
/ 8) - 1;
213 if (AvailFBArea
.y2
< 0)
214 AvailFBArea
.y2
= 32767;
216 if(AvailFBArea
.y2
< pScrn
->currentMode
->VDisplay
) {
217 xf86DrvMsg(pScrn
->scrnIndex
, X_ERROR
,
218 "Not enough video RAM for accelerator. At least "
219 "%dKB needed, %ldKB available\n",
220 ((((pScrn
->displayWidth
* pScrn
->bitsPerPixel
/8) /* TW: +8 for make it sure */
221 * pScrn
->currentMode
->VDisplay
) + reservedFbSize
) / 1024) + 8,
222 pSiS
->maxxfbmem
/1024);
223 pSiS
->NoAccel
= TRUE
;
224 pSiS
->NoXvideo
= TRUE
;
225 XAADestroyInfoRec(pSiS
->AccelInfoPtr
);
226 pSiS
->AccelInfoPtr
= NULL
;
230 xf86DrvMsg(pScrn
->scrnIndex
, X_INFO
,
231 "Frame Buffer From (%d,%d) To (%d,%d)\n",
232 AvailFBArea
.x1
, AvailFBArea
.y1
, AvailFBArea
.x2
, AvailFBArea
.y2
);
234 xf86InitFBManager(pScreen
, &AvailFBArea
);
236 return(XAAInit(pScreen
, infoPtr
));
241 SiSSync(ScrnInfoPtr pScrn
) {
242 SISPtr pSiS
= SISPTR(pScrn
);
247 static void SiSSetClippingRectangle( ScrnInfoPtr pScrn
,
248 int left
, int top
, int right
, int bottom
)
250 SISPtr pSiS
= SISPTR(pScrn
);
253 sisSETCLIPTOP(left
,top
);
254 sisSETCLIPBOTTOM(right
,bottom
);
255 pSiS
->ClipEnabled
= TRUE
;
258 static void SiSDisableClipping(ScrnInfoPtr pScrn
)
260 SISPtr pSiS
= SISPTR(pScrn
);
261 pSiS
->ClipEnabled
= FALSE
;
264 /* Screen to screen copy */
266 SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn
, int xdir
, int ydir
,
267 int rop
, unsigned int planemask
,
268 int transparency_color
)
270 SISPtr pSiS
= SISPTR(pScrn
);
272 sisSETPITCH(pSiS
->scrnOffset
, pSiS
->scrnOffset
);
274 sisSETROP(XAACopyROP
[rop
]);
275 pSiS
->Xdirection
= xdir
;
276 pSiS
->Ydirection
= ydir
;
280 SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn
, int x1
, int y1
, int x2
,
281 int y2
, int w
, int h
)
283 SISPtr pSiS
= SISPTR(pScrn
);
284 int srcaddr
, destaddr
;
287 op
= sisCMDBLT
| sisSRCVIDEO
;
288 if(pSiS
->Ydirection
== -1) {
290 srcaddr
= (y1
+ h
- 1) * pSiS
->CurrentLayout
.displayWidth
;
291 destaddr
= (y2
+ h
- 1) * pSiS
->CurrentLayout
.displayWidth
;
294 srcaddr
= y1
* pSiS
->CurrentLayout
.displayWidth
;
295 destaddr
= y2
* pSiS
->CurrentLayout
.displayWidth
;
297 if(pSiS
->Xdirection
== -1) {
299 srcaddr
+= x1
+ w
- 1;
300 destaddr
+= x2
+ w
- 1;
306 if (pSiS
->ClipEnabled
)
307 op
|= sisCLIPINTRN
| sisCLIPENABL
;
309 srcaddr
*= (pSiS
->CurrentLayout
.bitsPerPixel
/8);
310 destaddr
*= (pSiS
->CurrentLayout
.bitsPerPixel
/8);
311 if(((pSiS
->CurrentLayout
.bitsPerPixel
/ 8) > 1) && (pSiS
->Xdirection
== -1)) {
312 srcaddr
+= (pSiS
->CurrentLayout
.bitsPerPixel
/8)-1;
313 destaddr
+= (pSiS
->CurrentLayout
.bitsPerPixel
/8)-1;
317 sisSETSRCADDR(srcaddr
);
318 sisSETDSTADDR(destaddr
);
319 sisSETHEIGHTWIDTH(h
-1, w
* (pSiS
->CurrentLayout
.bitsPerPixel
/8)-1);
325 SiSSetupForFillRectSolid(ScrnInfoPtr pScrn
, int color
, int rop
,
326 unsigned int planemask
)
328 SISPtr pSiS
= SISPTR(pScrn
);
331 sisSETBGROPCOL(XAACopyROP
[rop
], color
);
332 sisSETFGROPCOL(XAACopyROP
[rop
], color
);
333 sisSETPITCH(pSiS
->scrnOffset
, pSiS
->scrnOffset
);
337 SiSSubsequentFillRectSolid(ScrnInfoPtr pScrn
, int x
, int y
, int w
, int h
)
339 SISPtr pSiS
= SISPTR(pScrn
);
342 destaddr
= y
* pSiS
->CurrentLayout
.displayWidth
+ x
;
344 op
= sisCMDBLT
| sisSRCBG
| sisTOP2BOTTOM
| sisLEFT2RIGHT
;
346 if(pSiS
->ClipEnabled
)
347 op
|= sisCLIPINTRN
| sisCLIPENABL
;
349 destaddr
*= (pSiS
->CurrentLayout
.bitsPerPixel
/ 8);
352 sisSETHEIGHTWIDTH(h
-1, w
* (pSiS
->CurrentLayout
.bitsPerPixel
/8)-1);
353 sisSETDSTADDR(destaddr
);
359 SiSSetupForMono8x8PatternFill(ScrnInfoPtr pScrn
, int patternx
, int patterny
,
360 int fg
, int bg
, int rop
, unsigned int planemask
)
362 SISPtr pSiS
= SISPTR(pScrn
);
363 unsigned int *patternRegPtr
;
366 (void)XAAHelpPatternROP(pScrn
, &fg
, &bg
, planemask
, &rop
);
370 sisSETBGROPCOL(0xcc, bg
); /* copy */
372 sisSETBGROPCOL(0xAA, bg
); /* noop */
374 sisSETFGROPCOL(rop
, fg
);
375 sisSETPITCH(0, pSiS
->scrnOffset
);
377 patternRegPtr
= (unsigned int *)sisSETPATREG();
378 pSiS
->sisPatternReg
[0] = pSiS
->sisPatternReg
[2] = patternx
;
379 pSiS
->sisPatternReg
[1] = pSiS
->sisPatternReg
[3] = patterny
;
380 for ( i
= 0 ; i
< 16 /* sisPatternHeight */ ; ) {
381 patternRegPtr
[i
++] = patternx
;
382 patternRegPtr
[i
++] = patterny
;
387 SiSSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn
, int patternx
,
388 int patterny
, int x
, int y
, int w
, int h
)
390 SISPtr pSiS
= SISPTR(pScrn
);
392 register unsigned char *patternRegPtr
;
393 register unsigned char *srcPatternRegPtr
;
394 register unsigned int *patternRegPtrL
;
398 int op
= sisCMDCOLEXP
|
404 if (pSiS
->ClipEnabled
)
405 op
|= sisCLIPINTRN
| sisCLIPENABL
;
407 dstaddr
= ( y
* pSiS
->CurrentLayout
.displayWidth
+ x
) *
408 pSiS
->CurrentLayout
.bitsPerPixel
/ 8;
412 patternRegPtr
= sisSETPATREG();
413 srcPatternRegPtr
= (unsigned char *)pSiS
->sisPatternReg
;
414 shift
= 8 - patternx
;
415 for ( i
= 0, k
= patterny
; i
< 8 ; i
++, k
++ ) {
416 tmp
= srcPatternRegPtr
[k
]<<8 | srcPatternRegPtr
[k
] ;
418 patternRegPtr
[i
] = tmp
& 0xff;
420 patternRegPtrL
= (unsigned int *)sisSETPATREG();
421 for ( i
= 2 ; i
< 16 /* sisPatternHeight */; ) {
422 patternRegPtrL
[i
++] = patternRegPtrL
[0];
423 patternRegPtrL
[i
++] = patternRegPtrL
[1];
426 sisSETDSTADDR(dstaddr
);
427 sisSETHEIGHTWIDTH(h
-1, w
*(pSiS
->CurrentLayout
.bitsPerPixel
/8)-1);
432 static void SiSSetupForSolidLine(ScrnInfoPtr pScrn
,
433 int color
, int rop
, unsigned int planemask
)
435 SISPtr pSiS
= SISPTR(pScrn
);
438 sisSETBGROPCOL(XAACopyROP
[rop
], 0);
439 sisSETFGROPCOL(XAACopyROP
[rop
], color
);
442 static void SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn
,
443 int x1
, int y1
, int x2
, int y2
, int flags
)
446 SISPtr pSiS
= SISPTR(pScrn
);
448 int major
, minor
, err
,K1
,K2
, tmp
;
450 op
= sisCMDLINE
| sisSRCFG
;
452 if ((flags
& OMIT_LAST
))
455 if (pSiS
->ClipEnabled
)
456 op
|= sisCLIPINTRN
| sisCLIPENABL
;
458 if ((major
= x2
- x1
) <= 0) {
463 if ((minor
= y2
- y1
) <= 0) {
468 if (minor
>= major
) {
475 K1
= (minor
- major
)<<1;
477 err
= (minor
<<1) - major
;
482 sisSETLineSteps((short)K1
,(short)K2
);
483 sisSETLineErrorTerm((short)err
);
484 sisSETLineMajorCount((short)major
);
488 static void SiSSubsequentSolidHorVertLine(ScrnInfoPtr pScrn
,
489 int x
, int y
, int len
, int dir
)
491 SISPtr pSiS
= SISPTR(pScrn
);
494 destaddr
= y
* pSiS
->CurrentLayout
.displayWidth
+ x
;
496 op
= sisCMDBLT
| sisSRCFG
| sisTOP2BOTTOM
| sisLEFT2RIGHT
;
498 if (pSiS
->ClipEnabled
)
499 op
|= sisCLIPINTRN
| sisCLIPENABL
;
501 destaddr
*= (pSiS
->CurrentLayout
.bitsPerPixel
/ 8);
505 sisSETPITCH(pSiS
->scrnOffset
, pSiS
->scrnOffset
);
507 if(dir
== DEGREES_0
) {
508 sisSETHEIGHTWIDTH(0, len
* (pSiS
->CurrentLayout
.bitsPerPixel
>> 3) - 1);
510 sisSETHEIGHTWIDTH(len
- 1, (pSiS
->CurrentLayout
.bitsPerPixel
>> 3) - 1);
513 sisSETDSTADDR(destaddr
);
518 /* TW: ----- CPU To Screen Color Expand (scanline-wise) ------ */
520 SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn
,
521 int fg
, int bg
, int rop
, unsigned int planemask
)
523 SISPtr pSiS
=SISPTR(pScrn
);
525 pSiS
->CommandReg
= 0;
527 pSiS
->CommandReg
|= (sisCMDECOLEXP
|
533 /* TW: The combination of flags in the following
534 * is not understandable. However, this is the
535 * only combination that seems to work.
538 sisSETROPBG(0xAA); /* dst = dst (=noop) */
539 pSiS
->CommandReg
|= sisSRCFG
;
541 sisSETBGROPCOL(XAAPatternROP
[rop
], bg
);
542 pSiS
->CommandReg
|= sisSRCFG
| sisPATBG
;
545 sisSETFGROPCOL(XAACopyROP
[rop
], fg
);
547 sisSETDSTPITCH(pSiS
->scrnOffset
);
552 SiSSubsequentScanlineCPUToScreenColorExpandFill(
553 ScrnInfoPtr pScrn
, int x
, int y
, int w
,
556 SISPtr pSiS
= SISPTR(pScrn
);
557 int _x0
, _y0
, _x1
, _y1
;
558 int op
= pSiS
->CommandReg
;
565 sisSETCLIPTOP(_x0
, _y0
);
566 sisSETCLIPBOTTOM(_x1
, _y1
);
569 op
&= (~(sisCLIPINTRN
| sisCLIPENABL
));
572 sisSETSRCPITCH(((((w
+7)/8)+3) >> 2) * 4);
574 sisSETHEIGHTWIDTH(1-1, (w
* (pSiS
->CurrentLayout
.bitsPerPixel
/8)) - 1);
579 pSiS
->CommandReg
= op
;
583 SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn
, int bufno
)
585 SISPtr pSiS
= SISPTR(pScrn
);
586 long cbo
= pSiS
->ColorExpandBufferScreenOffset
[bufno
];
587 int op
= pSiS
->CommandReg
;
590 destaddr
= (pSiS
->ycurrent
* pSiS
->CurrentLayout
.displayWidth
) + pSiS
->xcurrent
;
591 destaddr
*= (pSiS
->CurrentLayout
.bitsPerPixel
/ 8);
593 /* TW: Wait until there is no color expansion command in queue */
598 sisSETDSTADDR(destaddr
);
604 /* TW: Wait for eventual color expand commands to finish */
605 /* (needs to be done, otherwise the data in the buffer may
606 * be overwritten while accessed by the hardware)
608 while((MMIO_IN32(pSiS
->IOBase
, 0x8284) & 0x80000000)) {}