1/*
2 * 2D acceleration for SiS5597/5598 and 6326
3 *
4 * Copyright (C) 1998, 1999 by Alan Hourihane, Wigan, England.
5 * Parts Copyright (C) 2001-2005 Thomas Winischhofer, Vienna, Austria.
6 *
7 * Licensed under the following terms:
8 *
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appears in all copies and that both that copyright
12 * notice and this permission notice appear in supporting documentation, and
13 * and that the name of the copyright holder not be used in advertising
14 * or publicity pertaining to distribution of the software without specific,
15 * written prior permission. The copyright holder makes no representations
16 * about the suitability of this software for any purpose.  It is provided
17 * "as is" without expressed or implied warranty.
18 *
19 * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
21 * EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
23 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
24 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
25 * PERFORMANCE OF THIS SOFTWARE.
26 *
27 * Authors:  Alan Hourihane <alanh@fairlite.demon.co.uk>,
28 *           Mike Chapman <mike@paranoia.com>,
29 *           Juanjo Santamarta <santamarta@ctv.es>,
30 *           Mitani Hiroshi <hmitani@drl.mei.co.jp>,
31 *           David Thomas <davtom@dream.org.uk>,
32 *	     Thomas Winischhofer <thomas@winischhofer.net>.
33 */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include "sis.h"
40#include "sis_regs.h"
41#ifdef SIS_USE_XAA
42#include "xaarop.h"
43#endif
44#include "sis_accel.h"
45
46#ifdef SIS_USE_XAA
47
48#if 0
49#define CTSCE		/* Include enhanced color expansion code */
50#endif			/* This produces drawing errors sometimes */
51
52#endif /* XAA */
53
54#ifdef SIS_USE_EXA
55extern void SiSScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area);
56extern Bool SiSUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst);
57#endif /* EXA */
58
59extern UChar SiSGetCopyROP(int rop);
60extern UChar SiSGetPatternROP(int rop);
61
62static void
63SiSInitializeAccelerator(ScrnInfoPtr pScrn)
64{
65    /* Nothing here yet */
66}
67
68/* sync */
69static void
70SiSSync(ScrnInfoPtr pScrn)
71{
72    SISPtr pSiS = SISPTR(pScrn);
73
74    sisBLTSync;
75}
76
77static void
78SiSSyncAccel(ScrnInfoPtr pScrn)
79{
80    SISPtr pSiS = SISPTR(pScrn);
81
82    if(!pSiS->NoAccel) SiSSync(pScrn);
83}
84
85/* Screen to screen copy */
86static void
87SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir,
88			int rop, unsigned int planemask,
89			int transparency_color)
90{
91    SISPtr pSiS = SISPTR(pScrn);
92
93    sisBLTSync;
94    sisSETPITCH(pSiS->scrnOffset, pSiS->scrnOffset);
95
96    sisSETROP(SiSGetCopyROP(rop));
97    pSiS->Xdirection = xdir;
98    pSiS->Ydirection = ydir;
99}
100
101static void
102SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
103			int y2, int w, int h)
104{
105    SISPtr pSiS = SISPTR(pScrn);
106    int srcaddr, destaddr, op;
107
108    op = sisCMDBLT | sisSRCVIDEO;
109
110    if(pSiS->Ydirection == -1) {
111       op |= sisBOTTOM2TOP;
112       srcaddr = (y1 + h - 1) * pSiS->CurrentLayout.displayWidth;
113       destaddr = (y2 + h - 1) * pSiS->CurrentLayout.displayWidth;
114    } else {
115       op |= sisTOP2BOTTOM;
116       srcaddr = y1 * pSiS->CurrentLayout.displayWidth;
117       destaddr = y2 * pSiS->CurrentLayout.displayWidth;
118    }
119
120    if(pSiS->Xdirection == -1) {
121       op |= sisRIGHT2LEFT;
122       srcaddr += x1 + w - 1;
123       destaddr += x2 + w - 1;
124    } else {
125       op |= sisLEFT2RIGHT;
126       srcaddr += x1;
127       destaddr += x2;
128    }
129
130    if(pSiS->ClipEnabled)
131       op |= sisCLIPINTRN | sisCLIPENABL;
132
133    srcaddr *= (pSiS->CurrentLayout.bitsPerPixel/8);
134    destaddr *= (pSiS->CurrentLayout.bitsPerPixel/8);
135    if(((pSiS->CurrentLayout.bitsPerPixel / 8) > 1) && (pSiS->Xdirection == -1)) {
136       srcaddr += (pSiS->CurrentLayout.bitsPerPixel/8)-1;
137       destaddr += (pSiS->CurrentLayout.bitsPerPixel/8)-1;
138    }
139
140    sisBLTSync;
141    sisSETSRCADDR(srcaddr);
142    sisSETDSTADDR(destaddr);
143    sisSETHEIGHTWIDTH(h-1, w * (pSiS->CurrentLayout.bitsPerPixel/8)-1);
144    sisSETCMD(op);
145}
146
147/* solid fill */
148static void
149SiSSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, int rop,
150			unsigned int planemask)
151{
152    SISPtr pSiS = SISPTR(pScrn);
153
154    sisBLTSync;
155    sisSETBGROPCOL(SiSGetCopyROP(rop), color);
156    sisSETFGROPCOL(SiSGetCopyROP(rop), color);
157    sisSETPITCH(pSiS->scrnOffset, pSiS->scrnOffset);
158}
159
160static void
161SiSSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h)
162{
163    SISPtr pSiS = SISPTR(pScrn);
164    int destaddr, op;
165
166    destaddr = y * pSiS->CurrentLayout.displayWidth + x;
167
168    op = sisCMDBLT | sisSRCBG | sisTOP2BOTTOM | sisLEFT2RIGHT;
169
170    if(pSiS->ClipEnabled)
171       op |= sisCLIPINTRN | sisCLIPENABL;
172
173    destaddr *= (pSiS->CurrentLayout.bitsPerPixel / 8);
174
175    sisBLTSync;
176    sisSETHEIGHTWIDTH(h-1, w * (pSiS->CurrentLayout.bitsPerPixel/8)-1);
177    sisSETDSTADDR(destaddr);
178    sisSETCMD(op);
179}
180
181#ifdef SIS_USE_XAA  /* ---------------------------- XAA -------------------------- */
182
183/* Clipping */
184static void
185SiSSetClippingRectangle(ScrnInfoPtr pScrn,
186			int left, int top, int right, int bottom)
187{
188    SISPtr pSiS = SISPTR(pScrn);
189
190    sisBLTSync;
191    sisSETCLIPTOP(left,top);
192    sisSETCLIPBOTTOM(right,bottom);
193    pSiS->ClipEnabled = TRUE;
194}
195
196static void
197SiSDisableClipping(ScrnInfoPtr pScrn)
198{
199    SISPtr pSiS = SISPTR(pScrn);
200    pSiS->ClipEnabled = FALSE;
201}
202
203/* 8x8 mono */
204static void
205SiSSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny,
206			int fg, int bg, int rop, unsigned int planemask)
207{
208    SISPtr pSiS = SISPTR(pScrn);
209    unsigned int  *patternRegPtr;
210    int  i;
211
212    (void)XAAHelpPatternROP(pScrn, &fg, &bg, planemask, &rop);
213
214    sisBLTSync;
215    if(bg != -1) {
216       sisSETBGROPCOL(0xcc, bg);  /* copy */
217    } else {
218       sisSETBGROPCOL(0xAA, bg);  /* noop */
219    }
220    sisSETFGROPCOL(rop, fg);
221    sisSETPITCH(0, pSiS->scrnOffset);
222    sisSETSRCADDR(0);
223    patternRegPtr =  (unsigned int *)sisSETPATREG();
224    pSiS->sisPatternReg[0] = pSiS->sisPatternReg[2] = patternx ;
225    pSiS->sisPatternReg[1] = pSiS->sisPatternReg[3] = patterny ;
226    for(i = 0 ; i < 16 /* sisPatternHeight */ ; ) {
227       patternRegPtr[i++] = patternx ;
228       patternRegPtr[i++] = patterny ;
229    }
230}
231
232static void
233SiSSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patternx,
234			int patterny, int x, int y, int w, int h)
235{
236    SISPtr   pSiS = SISPTR(pScrn);
237    register UChar  *patternRegPtr;
238    register UChar  *srcPatternRegPtr;
239    register unsigned int   *patternRegPtrL;
240    UShort   tmp;
241    int      dstaddr, i, k, shift;
242    int      op  = sisCMDCOLEXP |
243		  sisTOP2BOTTOM |
244		  sisLEFT2RIGHT |
245		       sisPATFG |
246		       sisSRCBG;
247
248    if(pSiS->ClipEnabled)
249       op |= sisCLIPINTRN | sisCLIPENABL;
250
251    dstaddr = ( y * pSiS->CurrentLayout.displayWidth + x ) *
252			pSiS->CurrentLayout.bitsPerPixel / 8;
253
254    sisBLTSync;
255
256    patternRegPtr = sisSETPATREG();
257    srcPatternRegPtr = (UChar *)pSiS->sisPatternReg ;
258    shift = 8 - patternx ;
259    for(i = 0, k = patterny ; i < 8 ; i++, k++ ) {
260       tmp = srcPatternRegPtr[k]<<8 | srcPatternRegPtr[k] ;
261       tmp >>= shift ;
262       patternRegPtr[i] = tmp & 0xff;
263    }
264    patternRegPtrL = (unsigned int *)sisSETPATREG();
265    for(i = 2 ; i < 16 /* sisPatternHeight */; ) {
266       patternRegPtrL[i++] = patternRegPtrL[0];
267       patternRegPtrL[i++] = patternRegPtrL[1];
268    }
269
270    sisSETDSTADDR(dstaddr);
271    sisSETHEIGHTWIDTH(h-1, w*(pSiS->CurrentLayout.bitsPerPixel/8)-1);
272    sisSETCMD(op);
273}
274
275/* Line */
276static void
277SiSSetupForSolidLine(ScrnInfoPtr pScrn,
278			int color, int rop, unsigned int planemask)
279{
280    SISPtr pSiS = SISPTR(pScrn);
281
282    sisBLTSync;
283    sisSETBGROPCOL(SiSGetCopyROP(rop), 0);
284    sisSETFGROPCOL(SiSGetCopyROP(rop), color);
285}
286
287static void
288SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn,
289			int x1, int y1, int x2, int y2, int flags)
290
291{
292    SISPtr pSiS = SISPTR(pScrn);
293    int op, major, minor, err, K1, K2, tmp;
294
295    op = sisCMDLINE  | sisSRCFG;
296
297    if((flags & OMIT_LAST))
298       op |= sisLASTPIX;
299
300    if(pSiS->ClipEnabled)
301       op |= sisCLIPINTRN | sisCLIPENABL;
302
303    if((major = x2 - x1) <= 0)
304       major = -major;
305    else
306       op |= sisXINCREASE;
307
308    if((minor = y2 - y1) <= 0)
309       minor = -minor;
310    else
311       op |= sisYINCREASE;
312
313    if(minor >= major) {
314       tmp = minor;
315       minor = major;
316       major = tmp;
317    } else
318       op |= sisXMAJOR;
319
320    K1 = (minor - major) << 1;
321    K2 = minor << 1;
322    err = (minor << 1) - major;
323
324    sisBLTSync;
325    sisSETXStart(x1);
326    sisSETYStart(y1);
327    sisSETLineSteps((short)K1,(short)K2);
328    sisSETLineErrorTerm((short)err);
329    sisSETLineMajorCount((short)major);
330    sisSETCMD(op);
331}
332
333static void
334SiSSubsequentSolidHorVertLine(ScrnInfoPtr pScrn,
335				int x, int y, int len, int dir)
336{
337    SISPtr pSiS = SISPTR(pScrn);
338    int destaddr, op;
339
340    destaddr = y * pSiS->CurrentLayout.displayWidth + x;
341
342    op = sisCMDBLT | sisSRCFG | sisTOP2BOTTOM | sisLEFT2RIGHT;
343
344    if(pSiS->ClipEnabled)
345        op |= sisCLIPINTRN | sisCLIPENABL;
346
347    destaddr *= (pSiS->CurrentLayout.bitsPerPixel / 8);
348
349    sisBLTSync;
350
351    sisSETPITCH(pSiS->scrnOffset, pSiS->scrnOffset);
352
353    if(dir == DEGREES_0) {
354        sisSETHEIGHTWIDTH(0, len * (pSiS->CurrentLayout.bitsPerPixel >> 3) - 1);
355    } else {
356        sisSETHEIGHTWIDTH(len - 1, (pSiS->CurrentLayout.bitsPerPixel >> 3) - 1);
357    }
358
359    sisSETDSTADDR(destaddr);
360    sisSETCMD(op);
361}
362
363#ifdef CTSCE
364/* ----- CPU To Screen Color Expand (scanline-wise) ------ */
365static void
366SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
367				int fg, int bg, int rop, unsigned int planemask)
368{
369    SISPtr pSiS=SISPTR(pScrn);
370
371    pSiS->CommandReg = 0;
372
373    pSiS->CommandReg |= (sisCMDECOLEXP |
374			 sisLEFT2RIGHT |
375			 sisTOP2BOTTOM);
376
377    sisBLTSync;
378
379    /* The combination of flags in the following
380     * is not understandable. However, this is the
381     * only combination that seems to work.
382     */
383    if(bg == -1) {
384       sisSETROPBG(0xAA);             /* dst = dst (=noop) */
385       pSiS->CommandReg |= sisSRCFG;
386    } else {
387       sisSETBGROPCOL(SiSGetPatternROP(rop), bg);
388       pSiS->CommandReg |= sisSRCFG | sisPATBG;
389    }
390
391    sisSETFGROPCOL(SiSGetCopyROP(rop), fg);
392
393    sisSETDSTPITCH(pSiS->scrnOffset);
394}
395
396
397static void
398SiSSubsequentScanlineCPUToScreenColorExpandFill(
399			ScrnInfoPtr pScrn, int x, int y, int w,
400			int h, int skipleft)
401{
402    SISPtr pSiS = SISPTR(pScrn);
403    int _x0, _y0, _x1, _y1;
404    int op = pSiS->CommandReg;
405
406    if(skipleft > 0) {
407       _x0 = x + skipleft;
408       _y0 = y;
409       _x1 = x + w;
410       _y1 = y + h;
411       sisSETCLIPTOP(_x0, _y0);
412       sisSETCLIPBOTTOM(_x1, _y1);
413       op |= sisCLIPENABL;
414    } else {
415       op &= (~(sisCLIPINTRN | sisCLIPENABL));
416    }
417
418    sisSETSRCPITCH(((((w + 7) / 8) + 3) >> 2) * 4);
419
420    sisSETHEIGHTWIDTH(1-1, (w * (pSiS->CurrentLayout.bitsPerPixel/8)) - 1);
421
422    pSiS->xcurrent = x;
423    pSiS->ycurrent = y;
424
425    pSiS->CommandReg = op;
426}
427
428static void
429SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
430{
431    SISPtr pSiS = SISPTR(pScrn);
432    unsigned long cbo = pSiS->ColorExpandBufferScreenOffset[bufno];
433    int op = pSiS->CommandReg;
434    int destaddr;
435
436    destaddr = (pSiS->ycurrent * pSiS->CurrentLayout.displayWidth) + pSiS->xcurrent;
437    destaddr *= (pSiS->CurrentLayout.bitsPerPixel / 8);
438
439    /* Wait until there is no color expansion command in queue */
440    /* sisBLTSync; */
441
442    sisSETSRCADDR(cbo);
443
444    sisSETDSTADDR(destaddr);
445
446    sisSETCMD(op);
447
448    pSiS->ycurrent++;
449
450    /* Wait for eventual color expand commands to finish */
451    /* (needs to be done, otherwise the data in the buffer may
452     *  be overwritten while accessed by the hardware)
453     */
454    while((SIS_MMIO_IN32(pSiS->IOBase, 0x8284) & 0x80000000)) {}
455
456    sisBLTSync;
457}
458#endif  /* CTSCE */
459
460#endif /* XAA */
461
462#ifdef SIS_USE_EXA  /* ---------------------------- EXA -------------------------- */
463
464static void
465SiSEXASync(ScreenPtr pScreen, int marker)
466{
467	SISPtr pSiS = SISPTR(xf86ScreenToScrn(pScreen));
468
469	sisBLTSync;
470}
471
472static Bool
473SiSPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
474{
475	ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
476	SISPtr pSiS = SISPTR(pScrn);
477
478	/* Planemask not supported */
479	if((planemask & ((1 << pPixmap->drawable.depth) - 1)) !=
480				(1 << pPixmap->drawable.depth) - 1) {
481	   return FALSE;
482	}
483
484	/* Since these old engines have no "dest color depth" register, I assume
485	 * the 2D engine takes the bpp from the DAC... FIXME ? */
486	if(pPixmap->drawable.bitsPerPixel != pSiS->CurrentLayout.bitsPerPixel)
487	   return FALSE;
488
489	/* Check that the pitch matches the hardware's requirements. Should
490	 * never be a problem due to pixmapPitchAlign and fbScreenInit.
491	 */
492	if(exaGetPixmapPitch(pPixmap) & 7)
493	   return FALSE;
494
495	pSiS->fillPitch = exaGetPixmapPitch(pPixmap);
496	pSiS->fillBpp = pPixmap->drawable.bitsPerPixel >> 3;
497	pSiS->fillDstBase = (CARD32)exaGetPixmapOffset(pPixmap);
498
499	sisBLTSync;
500	sisSETBGROPCOL(SiSGetCopyROP(alu), fg);
501	sisSETFGROPCOL(SiSGetCopyROP(alu), fg);
502	sisSETPITCH(pSiS->fillPitch, pSiS->fillPitch);
503
504	return TRUE;
505}
506
507static void
508SiSSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
509{
510	ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
511	SISPtr pSiS = SISPTR(pScrn);
512
513	sisBLTSync;
514	sisSETHEIGHTWIDTH((y2 - y1) - 1, (x2 - x1) * pSiS->fillBpp - 1);
515	sisSETDSTADDR((pSiS->fillDstBase + ((y1 * (pSiS->fillPitch / pSiS->fillBpp) + x1) * pSiS->fillBpp)));
516	sisSETCMD((sisCMDBLT | sisSRCBG | sisTOP2BOTTOM | sisLEFT2RIGHT));
517}
518
519static void
520SiSDoneSolid(PixmapPtr pPixmap)
521{
522}
523
524static Bool
525SiSPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir,
526					int alu, Pixel planemask)
527{
528	ScrnInfoPtr pScrn = xf86ScreenToScrn(pSrcPixmap->drawable.pScreen);
529	SISPtr pSiS = SISPTR(pScrn);
530
531	/* Planemask not supported */
532	if((planemask & ((1 << pSrcPixmap->drawable.depth) - 1)) !=
533				(1 << pSrcPixmap->drawable.depth) - 1) {
534	   return FALSE;
535	}
536
537	/* Since these old engines have no "dest color depth" register, I assume
538	 * the 2D engine takes the bpp from the DAC... FIXME ? */
539	if(pDstPixmap->drawable.bitsPerPixel != pSiS->CurrentLayout.bitsPerPixel)
540	   return FALSE;
541
542	/* Check that the pitch matches the hardware's requirements. Should
543	 * never be a problem due to pixmapPitchAlign and fbScreenInit.
544	 */
545	if(exaGetPixmapPitch(pSrcPixmap) & 3)
546	   return FALSE;
547	if(exaGetPixmapPitch(pDstPixmap) & 7)
548	   return FALSE;
549
550	pSiS->copyXdir = xdir;
551	pSiS->copyYdir = ydir;
552	pSiS->copyBpp = pSrcPixmap->drawable.bitsPerPixel >> 3;
553	pSiS->copySPitch = exaGetPixmapPitch(pSrcPixmap);
554	pSiS->copyDPitch = exaGetPixmapPitch(pDstPixmap);
555	pSiS->copySrcBase = (CARD32)exaGetPixmapOffset(pSrcPixmap);
556	pSiS->copyDstBase = (CARD32)exaGetPixmapOffset(pDstPixmap);
557
558	sisBLTSync;
559	sisSETPITCH(pSiS->copySPitch, pSiS->copyDPitch);
560	sisSETROP(SiSGetCopyROP(alu));
561
562	return TRUE;
563}
564
565static void
566SiSCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
567{
568	ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
569	SISPtr pSiS = SISPTR(pScrn);
570	CARD32 srcbase, dstbase, cmd;
571	int bpp = pSiS->copyBpp;
572	int srcPixelPitch = pSiS->copySPitch / bpp;
573	int dstPixelPitch = pSiS->copyDPitch / bpp;
574
575	cmd = sisCMDBLT | sisSRCVIDEO;
576
577	if(pSiS->copyYdir < 0) {
578	   cmd |= sisBOTTOM2TOP;
579	   srcbase = (srcY + height - 1) * srcPixelPitch;
580	   dstbase = (dstY + height - 1) * dstPixelPitch;
581	} else {
582	   cmd |= sisTOP2BOTTOM;
583	   srcbase = srcY * srcPixelPitch;
584	   dstbase = dstY * dstPixelPitch;
585	}
586
587	if(pSiS->copyXdir < 0) {
588	   cmd |= sisRIGHT2LEFT;
589	   srcbase += srcX + width - 1;
590	   dstbase += dstX + width - 1;
591	} else {
592	   cmd |= sisLEFT2RIGHT;
593	   srcbase += srcX;
594	   dstbase += dstX;
595	}
596
597	srcbase *= bpp;
598	dstbase *= bpp;
599	if(pSiS->copyXdir < 0) {
600	   srcbase += bpp - 1;
601	   dstbase += bpp - 1;
602	}
603
604	srcbase += pSiS->copySrcBase;
605	dstbase += pSiS->copyDstBase;
606
607	sisBLTSync;
608	sisSETSRCADDR(srcbase);
609	sisSETDSTADDR(dstbase);
610	sisSETHEIGHTWIDTH(height - 1, width * bpp - 1);
611	sisSETCMD(cmd);
612}
613
614static void
615SiSDoneCopy(PixmapPtr pDstPixmap)
616{
617}
618
619#endif /* EXA */
620
621/* For DGA usage */
622
623static void
624SiSDGAFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, int color)
625{
626	SiSSetupForFillRectSolid(pScrn, color, GXcopy, ~0);
627	SiSSubsequentFillRectSolid(pScrn, x, y, w, h);
628}
629
630static void
631SiSDGABlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int dstx, int dsty, int w, int h, int color)
632{
633	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
634	int ydir = (srcy < dsty) ? -1 : 1;
635
636	SiSSetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, (CARD32)~0, color);
637	SiSSubsequentScreenToScreenCopy(pScrn, srcx, srcy, dstx, dsty, w, h);
638}
639
640/* Initialisation */
641
642Bool
643SiSAccelInit(ScreenPtr pScreen)
644{
645    ScrnInfoPtr    pScrn = xf86ScreenToScrn(pScreen);
646    SISPtr         pSiS = SISPTR(pScrn);
647#ifdef SIS_USE_XAA
648    XAAInfoRecPtr  infoPtr = NULL;
649    int            topFB, reservedFbSize, usableFbSize, i;
650    UChar          *AvailBufBase;
651    BoxRec         Avail;
652#endif
653
654    pSiS->ColorExpandBufferNumber = 0;
655    pSiS->PerColorExpandBufferSize = 0;
656    pSiS->RenderAccelArray = NULL;
657#ifdef SIS_USE_XAA
658    pSiS->AccelInfoPtr = NULL;
659#endif
660#ifdef SIS_USE_EXA
661    pSiS->EXADriverPtr = NULL;
662    pSiS->exa_scratch = NULL;
663#endif
664
665    if(!pSiS->NoAccel) {
666#ifdef SIS_USE_XAA
667       if(!pSiS->useEXA) {
668          pSiS->AccelInfoPtr = infoPtr = XAACreateInfoRec();
669          if(!infoPtr) pSiS->NoAccel = TRUE;
670       }
671#endif
672#ifdef SIS_USE_EXA
673       if(pSiS->useEXA) {
674	  if(!(pSiS->EXADriverPtr = exaDriverAlloc())) {
675	     pSiS->NoAccel = TRUE;
676	     pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */
677	  }
678       }
679#endif
680    }
681
682    if(!pSiS->NoAccel) {
683
684       SiSInitializeAccelerator(pScrn);
685
686       pSiS->InitAccel = SiSInitializeAccelerator;
687       pSiS->SyncAccel = SiSSyncAccel;
688       pSiS->FillRect  = SiSDGAFillRect;
689       pSiS->BlitRect  = SiSDGABlitRect;
690
691#ifdef SIS_USE_XAA	/* ----------------------- XAA ----------------------- */
692       if(!pSiS->useEXA) {
693
694	  infoPtr->Flags = LINEAR_FRAMEBUFFER |
695			   OFFSCREEN_PIXMAPS |
696			   PIXMAP_CACHE;
697
698	  /* Sync */
699	  infoPtr->Sync = SiSSync;
700
701	  /* Screen To Screen copy */
702	  infoPtr->SetupForScreenToScreenCopy =  SiSSetupForScreenToScreenCopy;
703	  infoPtr->SubsequentScreenToScreenCopy = SiSSubsequentScreenToScreenCopy;
704	  infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK;
705
706	  /* Solid fill */
707	  infoPtr->SetupForSolidFill = SiSSetupForFillRectSolid;
708	  infoPtr->SubsequentSolidFillRect = SiSSubsequentFillRectSolid;
709	  infoPtr->SolidFillFlags = NO_PLANEMASK;
710
711	  /* On 5597/5598 and 6326, clipping and lines only work
712	     for 1024, 2048, 4096 logical width */
713	  if(pSiS->ValidWidth) {
714	     /* Clipping */
715	     infoPtr->SetClippingRectangle = SiSSetClippingRectangle;
716	     infoPtr->DisableClipping = SiSDisableClipping;
717	     infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_LINE |
718				      HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY |
719				      HARDWARE_CLIP_MONO_8x8_FILL |
720				      HARDWARE_CLIP_SOLID_FILL  ;
721
722	     /* Solid Lines */
723	     infoPtr->SetupForSolidLine = SiSSetupForSolidLine;
724	     infoPtr->SubsequentSolidTwoPointLine = SiSSubsequentSolidTwoPointLine;
725	     infoPtr->SubsequentSolidHorVertLine = SiSSubsequentSolidHorVertLine;
726	     infoPtr->SolidLineFlags = NO_PLANEMASK;
727          }
728
729	  if(pScrn->bitsPerPixel != 24) {
730	     /* 8x8 mono pattern */
731	     infoPtr->SetupForMono8x8PatternFill = SiSSetupForMono8x8PatternFill;
732	     infoPtr->SubsequentMono8x8PatternFillRect = SiSSubsequentMono8x8PatternFillRect;
733	     infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK |
734						HARDWARE_PATTERN_PROGRAMMED_BITS |
735						HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
736						BIT_ORDER_IN_BYTE_MSBFIRST;
737	  }
738
739#ifdef CTSCE
740	  if(pScrn->bitsPerPixel != 24) {
741	     /* per-scanline color expansion (using indirect method) */
742	     pSiS->ColorExpandBufferNumber = 4;
743	     pSiS->ColorExpandBufferCountMask = 0x03;
744	     pSiS->PerColorExpandBufferSize = ((pScrn->virtualX + 31) / 32) * 4;
745
746	     infoPtr->NumScanlineColorExpandBuffers = pSiS->ColorExpandBufferNumber;
747	     infoPtr->ScanlineColorExpandBuffers = (UChar **)&pSiS->ColorExpandBufferAddr[0];
748
749	     infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
750				SiSSetupForScanlineCPUToScreenColorExpandFill;
751	     infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
752				SiSSubsequentScanlineCPUToScreenColorExpandFill;
753	     infoPtr->SubsequentColorExpandScanline =
754	                            SiSSubsequentColorExpandScanline;
755	     infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
756								CPU_TRANSFER_PAD_DWORD |
757								SCANLINE_PAD_DWORD |
758								BIT_ORDER_IN_BYTE_MSBFIRST |
759								LEFT_EDGE_CLIPPING;
760	  }
761#endif
762       } /* !exa */
763#endif /* XAA */
764
765#ifdef SIS_USE_EXA	/* ----------------------- EXA ----------------------- */
766       if(pSiS->useEXA) {
767	  pSiS->EXADriverPtr->exa_major = 2;
768	  pSiS->EXADriverPtr->exa_minor = 0;
769
770	  /* data */
771	  pSiS->EXADriverPtr->memoryBase = pSiS->FbBase;
772	  pSiS->EXADriverPtr->memorySize = pSiS->maxxfbmem;
773	  pSiS->EXADriverPtr->offScreenBase = pScrn->virtualX * pScrn->virtualY
774						* (pScrn->bitsPerPixel >> 3);
775	  if(pSiS->EXADriverPtr->memorySize > pSiS->EXADriverPtr->offScreenBase) {
776	     pSiS->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
777	  } else {
778	     pSiS->NoXvideo = TRUE;
779	     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
780		"Not enough video RAM for offscreen memory manager. Xv disabled\n");
781	  }
782	  pSiS->EXADriverPtr->pixmapOffsetAlign = 8;	/* src/dst: double quad word boundary */
783	  pSiS->EXADriverPtr->pixmapPitchAlign = 8;	/* could possibly be 1, but who knows for sure */
784	  pSiS->EXADriverPtr->maxX = 2047;
785	  pSiS->EXADriverPtr->maxY = 2047;
786
787	  /* Sync */
788	  pSiS->EXADriverPtr->WaitMarker = SiSEXASync;
789
790	  /* Solid fill */
791	  pSiS->EXADriverPtr->PrepareSolid = SiSPrepareSolid;
792	  pSiS->EXADriverPtr->Solid = SiSSolid;
793	  pSiS->EXADriverPtr->DoneSolid = SiSDoneSolid;
794
795	  /* Copy */
796	  pSiS->EXADriverPtr->PrepareCopy = SiSPrepareCopy;
797	  pSiS->EXADriverPtr->Copy = SiSCopy;
798	  pSiS->EXADriverPtr->DoneCopy = SiSDoneCopy;
799
800	  /* Composite not supported */
801
802       }
803#endif /* EXA */
804
805    }  /* NoAccel */
806
807    /* Offscreen memory manager
808     *
809     * Layout: (Sizes here do not reflect correct proportions)
810     * |--------------++++++++++++++++++++|  ====================~~~~~~~~~~~~|
811     *   UsableFbSize  ColorExpandBuffers |        TurboQueue     HWCursor
812     *                                  topFB
813     */
814
815#ifdef SIS_USE_XAA
816    if(!pSiS->useEXA) {
817
818       topFB = pSiS->maxxfbmem;
819
820       reservedFbSize = pSiS->ColorExpandBufferNumber * pSiS->PerColorExpandBufferSize;
821
822       usableFbSize = topFB - reservedFbSize;
823
824       if(pSiS->ColorExpandBufferNumber) {
825	  AvailBufBase = pSiS->FbBase + usableFbSize;
826	  for(i = 0; i < pSiS->ColorExpandBufferNumber; i++) {
827	     pSiS->ColorExpandBufferAddr[i] = AvailBufBase +
828				i * pSiS->PerColorExpandBufferSize;
829	     pSiS->ColorExpandBufferScreenOffset[i] = usableFbSize +
830				i * pSiS->PerColorExpandBufferSize;
831	  }
832       }
833
834       Avail.x1 = 0;
835       Avail.y1 = 0;
836       Avail.x2 = pScrn->displayWidth;
837       Avail.y2 = usableFbSize / (pScrn->displayWidth * pScrn->bitsPerPixel / 8) - 1;
838
839       if(Avail.y2 < 0) Avail.y2 = 32767;
840
841       if(Avail.y2 < pScrn->currentMode->VDisplay) {
842	  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
843		"Not enough video RAM for accelerator: %dKB needed, %dKB available\n",
844		((((pScrn->displayWidth * pScrn->bitsPerPixel/8)   /* +8 for make it sure */
845		     * pScrn->currentMode->VDisplay) + reservedFbSize) / 1024) + 8,
846		pSiS->maxxfbmem/1024);
847	  pSiS->NoAccel = TRUE;
848	  pSiS->NoXvideo = TRUE;
849	  XAADestroyInfoRec(pSiS->AccelInfoPtr);
850	  pSiS->AccelInfoPtr = NULL;
851	  return FALSE;
852       }
853
854       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
855		"Framebuffer from (%d,%d) to (%d,%d)\n",
856		Avail.x1, Avail.y1, Avail.x2 - 1, Avail.y2 - 1);
857
858       xf86InitFBManager(pScreen, &Avail);
859
860       if(!pSiS->NoAccel) {
861	  return XAAInit(pScreen, infoPtr);
862       }
863    } /* !exa */
864#endif
865
866#ifdef SIS_USE_EXA
867    if(pSiS->useEXA) {
868
869       if(!pSiS->NoAccel) {
870
871          if(!exaDriverInit(pScreen, pSiS->EXADriverPtr)) {
872	     pSiS->NoAccel = TRUE;
873	     pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */
874	     return FALSE;
875          }
876
877          /* Reserve locked offscreen scratch area of 64K for glyph data */
878	  pSiS->exa_scratch = exaOffscreenAlloc(pScreen, 64 * 1024, 16, TRUE,
879						SiSScratchSave, pSiS);
880	  if(pSiS->exa_scratch) {
881	     pSiS->exa_scratch_next = pSiS->exa_scratch->offset;
882	     pSiS->EXADriverPtr->UploadToScratch = SiSUploadToScratch;
883	  }
884
885       } else {
886
887          pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */
888
889       }
890
891    }
892#endif /* EXA */
893
894    return TRUE;
895}
896
897
898
899
900
901
902
903