172b676d7Smrg/*
272b676d7Smrg * 2D Acceleration for SiS 530, 620, 300, 540, 630, 730.
372b676d7Smrg *
472b676d7Smrg * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria
572b676d7Smrg *
672b676d7Smrg * Redistribution and use in source and binary forms, with or without
772b676d7Smrg * modification, are permitted provided that the following conditions
872b676d7Smrg * are met:
972b676d7Smrg * 1) Redistributions of source code must retain the above copyright
1072b676d7Smrg *    notice, this list of conditions and the following disclaimer.
1172b676d7Smrg * 2) Redistributions in binary form must reproduce the above copyright
1272b676d7Smrg *    notice, this list of conditions and the following disclaimer in the
1372b676d7Smrg *    documentation and/or other materials provided with the distribution.
1472b676d7Smrg * 3) The name of the author may not be used to endorse or promote products
1572b676d7Smrg *    derived from this software without specific prior written permission.
1672b676d7Smrg *
1772b676d7Smrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1872b676d7Smrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1972b676d7Smrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2072b676d7Smrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2172b676d7Smrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2272b676d7Smrg * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2372b676d7Smrg * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2472b676d7Smrg * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2572b676d7Smrg * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2672b676d7Smrg * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2772b676d7Smrg *
2872b676d7Smrg * Authors:   Thomas Winischhofer <thomas@winischhofer.net>
2972b676d7Smrg *	      Can-Ru Yeou, SiS Inc.
3072b676d7Smrg *
3172b676d7Smrg */
3272b676d7Smrg
3372b676d7Smrg#ifdef HAVE_CONFIG_H
3472b676d7Smrg#include "config.h"
3572b676d7Smrg#endif
3672b676d7Smrg
3772b676d7Smrg#if 0
3872b676d7Smrg#define DEBUG
3972b676d7Smrg#endif
4072b676d7Smrg
4172b676d7Smrg#include "sis.h"
4272b676d7Smrg#include "sis_regs.h"
4372b676d7Smrg
4472b676d7Smrg#include "sis300_accel.h"
4572b676d7Smrg
4672b676d7Smrg/* This is the offset to the memory for each head */
4772b676d7Smrg#define HEADOFFSET 	(pSiS->dhmOffset)
4872b676d7Smrg
4972b676d7Smrg#ifdef SIS_USE_XAA
5072b676d7Smrg
5172b676d7Smrg#undef STSCE    	/* Use/Don't use ScreenToScreenColorExpand - does not work */
5272b676d7Smrg
5372b676d7Smrg#undef TRAP     	/* Use/Don't use Trapezoid Fills - does not work - XAA provides
5472b676d7Smrg		         * illegal trapezoid data (left and right edges cross each other
5572b676d7Smrg			 * sometimes) which causes drawing errors. Further, I have not found
5672b676d7Smrg			 * out how to draw polygones with a height greater than 127...
5772b676d7Smrg                         */
5872b676d7Smrg#endif /* XAA */
5972b676d7Smrg
6072b676d7Smrg#ifdef SIS_USE_EXA
6172b676d7Smrgextern void SiSScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area);
6272b676d7Smrgextern Bool SiSUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst);
6372b676d7Smrg#endif /* EXA */
6472b676d7Smrg
6572b676d7Smrgextern UChar SiSGetCopyROP(int rop);
6672b676d7Smrgextern UChar SiSGetPatternROP(int rop);
6772b676d7Smrg
6872b676d7Smrgstatic void
6972b676d7SmrgSiSInitializeAccelerator(ScrnInfoPtr pScrn)
7072b676d7Smrg{
7172b676d7Smrg#ifdef SIS_USE_XAA
7272b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
7372b676d7Smrg
7472b676d7Smrg	pSiS->DoColorExpand = FALSE;
7572b676d7Smrg#endif
7672b676d7Smrg}
7772b676d7Smrg
7872b676d7Smrgstatic void
7972b676d7SmrgSiSSync(ScrnInfoPtr pScrn)
8072b676d7Smrg{
8172b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
8272b676d7Smrg
8372b676d7Smrg	SiSIdle
8472b676d7Smrg}
8572b676d7Smrg
8672b676d7Smrgstatic void
8772b676d7SmrgSiSSyncAccel(ScrnInfoPtr pScrn)
8872b676d7Smrg{
8972b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
9072b676d7Smrg
9172b676d7Smrg	if(!pSiS->NoAccel) SiSSync(pScrn);
9272b676d7Smrg}
9372b676d7Smrg
9472b676d7Smrgstatic void
9572b676d7SmrgSiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
9672b676d7Smrg			int xdir, int ydir, int rop,
9772b676d7Smrg			unsigned int planemask, int trans_color)
9872b676d7Smrg{
9972b676d7Smrg	SISPtr  pSiS = SISPTR(pScrn);
10072b676d7Smrg
10172b676d7Smrg	SiSSetupDSTColorDepth(pSiS->DstColor);
10272b676d7Smrg	SiSSetupSRCPitch(pSiS->scrnOffset)
10372b676d7Smrg	SiSSetupDSTRect(pSiS->scrnOffset, -1)
10472b676d7Smrg
10572b676d7Smrg	if(trans_color != -1) {
10672b676d7Smrg	   SiSSetupROP(0x0A)
10772b676d7Smrg	   SiSSetupSRCTrans(trans_color)
10872b676d7Smrg	   SiSSetupCMDFlag(TRANSPARENT_BITBLT)
10972b676d7Smrg	} else {
11072b676d7Smrg	   SiSSetupROP(SiSGetCopyROP(rop))
11172b676d7Smrg	}
11272b676d7Smrg	if(xdir > 0) {
11372b676d7Smrg	   SiSSetupCMDFlag(X_INC)
11472b676d7Smrg	}
11572b676d7Smrg	if(ydir > 0) {
11672b676d7Smrg	   SiSSetupCMDFlag(Y_INC)
11772b676d7Smrg	}
11872b676d7Smrg}
11972b676d7Smrg
12072b676d7Smrgstatic void
12172b676d7SmrgSiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
12272b676d7Smrg			int src_x, int src_y, int dst_x, int dst_y,
12372b676d7Smrg			int width, int height)
12472b676d7Smrg{
12572b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
12672b676d7Smrg	CARD32 srcbase, dstbase;
12772b676d7Smrg
12872b676d7Smrg	srcbase = dstbase = 0;
12972b676d7Smrg	if(src_y >= 2048) {
13072b676d7Smrg	   srcbase = pSiS->scrnOffset * src_y;
13172b676d7Smrg	   src_y = 0;
13272b676d7Smrg	}
13372b676d7Smrg	if((dst_y >= pScrn->virtualY) || (dst_y >= 2048)) {
13472b676d7Smrg	   dstbase = pSiS->scrnOffset * dst_y;
13572b676d7Smrg	   dst_y = 0;
13672b676d7Smrg	}
13772b676d7Smrg#ifdef SISDUALHEAD
13872b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
13972b676d7Smrg	   srcbase += HEADOFFSET;
14072b676d7Smrg	   dstbase += HEADOFFSET;
14172b676d7Smrg	}
14272b676d7Smrg#endif
14372b676d7Smrg	SiSSetupSRCBase(srcbase);
14472b676d7Smrg	SiSSetupDSTBase(dstbase);
14572b676d7Smrg
14672b676d7Smrg	if(!(pSiS->CommandReg & X_INC)) {
14772b676d7Smrg	   src_x += width-1;
14872b676d7Smrg	   dst_x += width-1;
14972b676d7Smrg	}
15072b676d7Smrg	if(!(pSiS->CommandReg & Y_INC)) {
15172b676d7Smrg	   src_y += height-1;
15272b676d7Smrg	   dst_y += height-1;
15372b676d7Smrg	}
15472b676d7Smrg	SiSSetupRect(width, height)
15572b676d7Smrg	SiSSetupSRCXY(src_x, src_y)
15672b676d7Smrg	SiSSetupDSTXY(dst_x, dst_y)
15772b676d7Smrg
15872b676d7Smrg	SiSDoCMD
15972b676d7Smrg}
16072b676d7Smrg
16172b676d7Smrgstatic void
16272b676d7SmrgSiSSetupForSolidFill(ScrnInfoPtr pScrn,
16372b676d7Smrg			int color, int rop, unsigned int planemask)
16472b676d7Smrg{
16572b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
16672b676d7Smrg
16772b676d7Smrg	if(pSiS->disablecolorkeycurrent) {
16872b676d7Smrg	   if((CARD32)color == pSiS->colorKey) {
16972b676d7Smrg	      rop = 5;  /* NOOP */
17072b676d7Smrg	   }
17172b676d7Smrg	}
17272b676d7Smrg	SiSSetupPATFG(color)
17372b676d7Smrg	SiSSetupDSTRect(pSiS->scrnOffset, -1)
17472b676d7Smrg	SiSSetupDSTColorDepth(pSiS->DstColor);
17572b676d7Smrg	SiSSetupROP(SiSGetPatternROP(rop))
17672b676d7Smrg	/* SiSSetupCMDFlag(PATFG) - is zero */
17772b676d7Smrg}
17872b676d7Smrg
17972b676d7Smrgstatic void
18072b676d7SmrgSiSSubsequentSolidFillRect(ScrnInfoPtr pScrn,
18172b676d7Smrg			int x, int y, int w, int h)
18272b676d7Smrg{
18372b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
18472b676d7Smrg	CARD32 dstbase = 0;
18572b676d7Smrg
18672b676d7Smrg	if(y >= 2048) {
18772b676d7Smrg	   dstbase = pSiS->scrnOffset * y;
18872b676d7Smrg	   y = 0;
18972b676d7Smrg	}
19072b676d7Smrg#ifdef SISDUALHEAD
19172b676d7Smrg        if(pSiS->VGAEngine != SIS_530_VGA) {
19272b676d7Smrg	   dstbase += HEADOFFSET;
19372b676d7Smrg        }
19472b676d7Smrg#endif
19572b676d7Smrg	SiSSetupDSTBase(dstbase)
19672b676d7Smrg	SiSSetupDSTXY(x,y)
19772b676d7Smrg	SiSSetupRect(w,h)
19872b676d7Smrg	/* Clear commandReg because Setup can be used for Rect and Trap */
19972b676d7Smrg	pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR |
20072b676d7Smrg			      T_L_X_INC | T_L_Y_INC |
20172b676d7Smrg			      T_R_X_INC | T_R_Y_INC |
20272b676d7Smrg			      TRAPAZOID_FILL);
20372b676d7Smrg	SiSSetupCMDFlag(X_INC | Y_INC | BITBLT)
20472b676d7Smrg
20572b676d7Smrg	SiSDoCMD
20672b676d7Smrg}
20772b676d7Smrg
20872b676d7Smrg#ifdef SIS_USE_XAA  /* ---------------------------- XAA -------------------------- */
20972b676d7Smrg
21072b676d7Smrg#ifdef SISDUALHEAD
21172b676d7Smrgstatic void
21272b676d7SmrgSiSRestoreAccelState(ScrnInfoPtr pScrn)
21372b676d7Smrg{
21472b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
21572b676d7Smrg
21672b676d7Smrg	/* We don't need to do anything special here; forcing the
21772b676d7Smrg	 * other head to re-read the CmdQueLen is not necessary:
21872b676d7Smrg	 * After the Sync in RestoreAccelState(), the real queue
21972b676d7Smrg	 * length is always larger than (or at least equal to)
22072b676d7Smrg	 * the amount stored in CmdQueueLen of the other head,
22172b676d7Smrg	 * so the only thing that might happen is one unnecessary
22272b676d7Smrg	 * Sync on the other head. I think we can live with that.
22372b676d7Smrg	 */
22472b676d7Smrg	pSiS->DoColorExpand = FALSE;
22572b676d7Smrg	SiSIdle
22672b676d7Smrg}
22772b676d7Smrg#endif
22872b676d7Smrg
22972b676d7Smrg/* Trapezoid */
23072b676d7Smrg/* This would work better if XAA would provide us with valid trapezoids.
23172b676d7Smrg * In fact, with small trapezoids the left and the right edge often cross
23272b676d7Smrg * each other or result in a line length of 0 which causes drawing errors
23372b676d7Smrg * (filling over whole scanline).
23472b676d7Smrg * Furthermore, I have not found out how to draw trapezoids with a height
23572b676d7Smrg * greater than 127.
23672b676d7Smrg */
23772b676d7Smrg#ifdef TRAP
23872b676d7Smrgstatic void
23972b676d7SmrgSiSSubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h,
24072b676d7Smrg			int left,  int dxL, int dyL, int eL,
24172b676d7Smrg			int right, int dxR, int dyR, int eR )
24272b676d7Smrg{
24372b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
24472b676d7Smrg	CARD32 dstbase;
24572b676d7Smrg#if 0
24672b676d7Smrg	float kL, kR;
24772b676d7Smrg#endif
24872b676d7Smrg
24972b676d7Smrg	dstbase = 0;
25072b676d7Smrg	if(y >= 2048) {
25172b676d7Smrg	   dstbase=pSiS->scrnOffset*y;
25272b676d7Smrg	   y = 0;
25372b676d7Smrg	}
25472b676d7Smrg#ifdef SISDUALHEAD
25572b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
25672b676d7Smrg	   dstbase += HEADOFFSET;
25772b676d7Smrg	}
25872b676d7Smrg#endif
25972b676d7Smrg	SiSSetupDSTBase(dstbase)
26072b676d7Smrg	/* SiSSetupRect(w,h) */
26172b676d7Smrg
26272b676d7Smrg#if 1
26372b676d7Smrg	SiSSetupPATFG(0xff0000) /* FOR TESTING */
26472b676d7Smrg#endif
26572b676d7Smrg
26672b676d7Smrg	/* Clear CommandReg because SetUp can be used for Rect and Trap */
26772b676d7Smrg	pSiS->CommandReg &= ~(T_L_X_INC | T_L_Y_INC |
26872b676d7Smrg	                      T_R_X_INC | T_R_Y_INC |
26972b676d7Smrg	                      T_XISMAJORL | T_XISMAJORR |
27072b676d7Smrg			      BITBLT);
27172b676d7Smrg
27272b676d7Smrg        xf86DrvMsg(0, X_INFO, "Trap (%d %d %d %d) dxL %d dyL %d eL %d   dxR %d dyR %d eR %d\n",
27372b676d7Smrg		left, right, y, h, dxL, dyL, eL, dxR, dyR, eR);
27472b676d7Smrg
27572b676d7Smrg	/* Unfortunately, we must check if the right and the left edge
27672b676d7Smrg	 * cross each other...  INCOMPLETE (line equation wrong)
27772b676d7Smrg	 */
27872b676d7Smrg#if 0
27972b676d7Smrg	if (dxL == 0) kL = 0;
28072b676d7Smrg	else kL = (float)dyL / (float)dxL;
28172b676d7Smrg	if (dxR == 0) kR = 0;
28272b676d7Smrg	else kR = (float)dyR / (float)dxR;
28372b676d7Smrg	xf86DrvMsg(0, X_INFO, "kL %f kR %f!\n", kL, kR);
28472b676d7Smrg	if ( (kR != kL) &&
28572b676d7Smrg	     (!(kR == 0 && kL == 0)) &&
28672b676d7Smrg	     (!(kR <  0 && kL >  0)) ) {
28772b676d7Smrg	   xf86DrvMsg(0, X_INFO, "Inside if (%f - %d)\n", ( kL * ( ( ((float)right - (float)left) / (kL - kR) ) - left) + y), h+y);
28872b676d7Smrg           if ( ( ( kL * ( ( ((float)right - (float)left) / (kL - kR) ) - (float)left) + (float)y) < (h + y) ) ) {
28972b676d7Smrg	     xf86DrvMsg(0, X_INFO, "Cross detected!\n");
29072b676d7Smrg	   }
29172b676d7Smrg	}
29272b676d7Smrg#endif
29372b676d7Smrg
29472b676d7Smrg	/* Determine egde angles */
29572b676d7Smrg	if(dxL < 0) { dxL = -dxL; }
29672b676d7Smrg	else { SiSSetupCMDFlag(T_L_X_INC) }
29772b676d7Smrg	if(dxR < 0) { dxR = -dxR; }
29872b676d7Smrg	else { SiSSetupCMDFlag(T_R_X_INC) }
29972b676d7Smrg
30072b676d7Smrg	/* (Y direction always positive - do this anyway) */
30172b676d7Smrg	if(dyL < 0) { dyL = -dyL; }
30272b676d7Smrg	else { SiSSetupCMDFlag(T_L_Y_INC) }
30372b676d7Smrg	if(dyR < 0) { dyR = -dyR; }
30472b676d7Smrg	else { SiSSetupCMDFlag(T_R_Y_INC) }
30572b676d7Smrg
30672b676d7Smrg	/* Determine major axis */
30772b676d7Smrg	if(dxL >= dyL) {      /* X is major axis */
30872b676d7Smrg	   SiSSetupCMDFlag(T_XISMAJORL)
30972b676d7Smrg	}
31072b676d7Smrg	if(dxR >= dyR) {      /* X is major axis */
31172b676d7Smrg	   SiSSetupCMDFlag(T_XISMAJORR)
31272b676d7Smrg	}
31372b676d7Smrg
31472b676d7Smrg	/* Set up deltas */
31572b676d7Smrg	SiSSetupdL(dxL, dyL)
31672b676d7Smrg	SiSSetupdR(dxR, dyR)
31772b676d7Smrg
31872b676d7Smrg#if 0   /* Could it be that this crappy engine can only draw trapezoids up to 127 pixels high? */
31972b676d7Smrg	h &= 0x7F;
32072b676d7Smrg	if (h == 0) h = 10;
32172b676d7Smrg#endif
32272b676d7Smrg
32372b676d7Smrg	/* Set up y, h, left, right */
32472b676d7Smrg	SiSSetupYH(y,h)
32572b676d7Smrg	SiSSetupLR(left,right)
32672b676d7Smrg
32772b676d7Smrg	/* Set up initial error term */
32872b676d7Smrg	SiSSetupEL(eL)
32972b676d7Smrg	SiSSetupER(eR)
33072b676d7Smrg
33172b676d7Smrg	SiSSetupCMDFlag(TRAPAZOID_FILL);
33272b676d7Smrg
33372b676d7Smrg	SiSDoCMD
33472b676d7Smrg}
33572b676d7Smrg#endif
33672b676d7Smrg
33772b676d7Smrgstatic void
33872b676d7SmrgSiSSetupForSolidLine(ScrnInfoPtr pScrn,
33972b676d7Smrg			int color, int rop, unsigned int planemask)
34072b676d7Smrg{
34172b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
34272b676d7Smrg
34372b676d7Smrg	SiSSetupLineCount(1)
34472b676d7Smrg	SiSSetupPATFG(color)
34572b676d7Smrg	SiSSetupDSTRect(pSiS->scrnOffset, -1)
34672b676d7Smrg	SiSSetupDSTColorDepth(pSiS->DstColor);
34772b676d7Smrg	SiSSetupROP(SiSGetPatternROP(rop))
34872b676d7Smrg	SiSSetupCMDFlag(PATFG | LINE)
34972b676d7Smrg}
35072b676d7Smrg
35172b676d7Smrgstatic void
35272b676d7SmrgSiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn,
35372b676d7Smrg			int x1, int y1, int x2, int y2, int flags)
35472b676d7Smrg{
35572b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
35672b676d7Smrg	int    miny, maxy;
35772b676d7Smrg	CARD32 dstbase = 0;
35872b676d7Smrg
35972b676d7Smrg	miny = (y1 > y2) ? y2 : y1;
36072b676d7Smrg	maxy = (y1 > y2) ? y1 : y2;
36172b676d7Smrg	if(maxy >= 2048) {
36272b676d7Smrg	   dstbase = pSiS->scrnOffset * miny;
36372b676d7Smrg	   y1 -= miny;
36472b676d7Smrg	   y2 -= miny;
36572b676d7Smrg	}
36672b676d7Smrg#ifdef SISDUALHEAD
36772b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
36872b676d7Smrg	   dstbase += HEADOFFSET;
36972b676d7Smrg	}
37072b676d7Smrg#endif
37172b676d7Smrg	SiSSetupDSTBase(dstbase)
37272b676d7Smrg
37372b676d7Smrg	SiSSetupX0Y0(x1,y1)
37472b676d7Smrg	SiSSetupX1Y1(x2,y2)
37572b676d7Smrg	if(flags & OMIT_LAST) {
37672b676d7Smrg	   SiSSetupCMDFlag(NO_LAST_PIXEL)
37772b676d7Smrg	} else {
37872b676d7Smrg	   pSiS->CommandReg &= ~(NO_LAST_PIXEL);
37972b676d7Smrg	}
38072b676d7Smrg
38172b676d7Smrg	SiSDoCMD
38272b676d7Smrg}
38372b676d7Smrg
38472b676d7Smrgstatic void
38572b676d7SmrgSiSSubsequentSolidHorzVertLine(ScrnInfoPtr pScrn,
38672b676d7Smrg			int x, int y, int len, int dir)
38772b676d7Smrg{
38872b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
38972b676d7Smrg	CARD32 dstbase = 0;
39072b676d7Smrg
39172b676d7Smrg	len--; /* starting point is included! */
39272b676d7Smrg
39372b676d7Smrg	if((y >= 2048) || ((dir != DEGREES_0) && ((y + len) >= 2048))) {
39472b676d7Smrg	   dstbase = pSiS->scrnOffset * y;
39572b676d7Smrg	   y = 0;
39672b676d7Smrg	}
39772b676d7Smrg#ifdef SISDUALHEAD
39872b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
39972b676d7Smrg	   dstbase += HEADOFFSET;
40072b676d7Smrg	}
40172b676d7Smrg#endif
40272b676d7Smrg	SiSSetupDSTBase(dstbase)
40372b676d7Smrg
40472b676d7Smrg	SiSSetupX0Y0(x,y)
40572b676d7Smrg	if(dir == DEGREES_0) {
40672b676d7Smrg	   SiSSetupX1Y1(x + len, y);
40772b676d7Smrg	} else {
40872b676d7Smrg	   SiSSetupX1Y1(x, y + len);
40972b676d7Smrg	}
41072b676d7Smrg
41172b676d7Smrg	SiSDoCMD
41272b676d7Smrg}
41372b676d7Smrg
41472b676d7Smrgstatic void
41572b676d7SmrgSiSSetupForDashedLine(ScrnInfoPtr pScrn,
41672b676d7Smrg			int fg, int bg, int rop, unsigned int planemask,
41772b676d7Smrg			int length, UChar *pattern)
41872b676d7Smrg{
41972b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
42072b676d7Smrg
42172b676d7Smrg	SiSSetupLineCount(1)
42272b676d7Smrg	SiSSetupDSTRect(pSiS->scrnOffset, -1)
42372b676d7Smrg	SiSSetupDSTColorDepth(pSiS->DstColor);
42472b676d7Smrg	SiSSetupStyleLow(*pattern)
42572b676d7Smrg	SiSSetupStyleHigh(*(pattern+4))
42672b676d7Smrg	SiSSetupStylePeriod(length-1);
42772b676d7Smrg	SiSSetupROP(SiSGetPatternROP(rop))
42872b676d7Smrg	SiSSetupPATFG(fg)
42972b676d7Smrg	SiSSetupCMDFlag(LINE | LINE_STYLE)
43072b676d7Smrg	if(bg != -1) {
43172b676d7Smrg	   SiSSetupPATBG(bg)
43272b676d7Smrg	} else {
43372b676d7Smrg	   SiSSetupCMDFlag(TRANSPARENT);
43472b676d7Smrg	}
43572b676d7Smrg}
43672b676d7Smrg
43772b676d7Smrgstatic void
43872b676d7SmrgSiSSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn,
43972b676d7Smrg			int x1, int y1, int x2, int y2,
44072b676d7Smrg			int flags, int phase)
44172b676d7Smrg{
44272b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
44372b676d7Smrg	int    miny, maxy;
44472b676d7Smrg	CARD32 dstbase = 0;
44572b676d7Smrg
44672b676d7Smrg	miny = (y1 > y2) ? y2 : y1;
44772b676d7Smrg	maxy = (y1 > y2) ? y1 : y2;
44872b676d7Smrg	if(maxy >= 2048) {
44972b676d7Smrg	   dstbase = pSiS->scrnOffset * miny;
45072b676d7Smrg	   y1 -= miny;
45172b676d7Smrg	   y2 -= miny;
45272b676d7Smrg	}
45372b676d7Smrg#ifdef SISDUALHEAD
45472b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
45572b676d7Smrg	   dstbase += HEADOFFSET;
45672b676d7Smrg	}
45772b676d7Smrg#endif
45872b676d7Smrg	SiSSetupDSTBase(dstbase)
45972b676d7Smrg
46072b676d7Smrg	SiSSetupX0Y0(x1,y1)
46172b676d7Smrg	SiSSetupX1Y1(x2,y2)
46272b676d7Smrg	if(flags & OMIT_LAST) {
46372b676d7Smrg	   SiSSetupCMDFlag(NO_LAST_PIXEL)
46472b676d7Smrg	} else {
46572b676d7Smrg	   pSiS->CommandReg &= ~(NO_LAST_PIXEL);
46672b676d7Smrg	}
46772b676d7Smrg
46872b676d7Smrg	SiSDoCMD
46972b676d7Smrg}
47072b676d7Smrg
47172b676d7Smrgstatic void
47272b676d7SmrgSiSSetupForMonoPatternFill(ScrnInfoPtr pScrn,
47372b676d7Smrg			int patx, int paty, int fg, int bg,
47472b676d7Smrg			int rop, unsigned int planemask)
47572b676d7Smrg{
47672b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
47772b676d7Smrg
47872b676d7Smrg	SiSSetupDSTRect(pSiS->scrnOffset, -1)
47972b676d7Smrg	SiSSetupDSTColorDepth(pSiS->DstColor);
48072b676d7Smrg	SiSSetupMONOPAT(patx,paty)
48172b676d7Smrg	SiSSetupPATFG(fg)
48272b676d7Smrg	SiSSetupROP(SiSGetPatternROP(rop))
48372b676d7Smrg	SiSSetupCMDFlag(PATMONO)
48472b676d7Smrg	if(bg != -1) {
48572b676d7Smrg	   SiSSetupPATBG(bg)
48672b676d7Smrg	} else {
48772b676d7Smrg	   SiSSetupCMDFlag(TRANSPARENT)
48872b676d7Smrg	}
48972b676d7Smrg}
49072b676d7Smrg
49172b676d7Smrgstatic void
49272b676d7SmrgSiSSubsequentMonoPatternFill(ScrnInfoPtr pScrn,
49372b676d7Smrg			int patx, int paty,
49472b676d7Smrg			int x, int y, int w, int h)
49572b676d7Smrg{
49672b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
49772b676d7Smrg	CARD32 dstbase = 0;
49872b676d7Smrg
49972b676d7Smrg	if(y >= 2048) {
50072b676d7Smrg	   dstbase = pSiS->scrnOffset * y;
50172b676d7Smrg	   y = 0;
50272b676d7Smrg	}
50372b676d7Smrg#ifdef SISDUALHEAD
50472b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
50572b676d7Smrg	   dstbase += HEADOFFSET;
50672b676d7Smrg	}
50772b676d7Smrg#endif
50872b676d7Smrg	SiSSetupDSTBase(dstbase)
50972b676d7Smrg	SiSSetupDSTXY(x, y)
51072b676d7Smrg	SiSSetupRect(w, h)
51172b676d7Smrg	/* Clear commandReg because Setup can be used for Rect and Trap */
51272b676d7Smrg	pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR |
51372b676d7Smrg	                      T_L_X_INC | T_L_Y_INC |
51472b676d7Smrg	                      T_R_X_INC | T_R_Y_INC |
51572b676d7Smrg	                      TRAPAZOID_FILL);
51672b676d7Smrg	SiSSetupCMDFlag(X_INC | Y_INC)
51772b676d7Smrg
51872b676d7Smrg	SiSDoCMD
51972b676d7Smrg}
52072b676d7Smrg
52172b676d7Smrg/* Trapezoid */
52272b676d7Smrg#ifdef TRAP
52372b676d7Smrgstatic void
52472b676d7SmrgSiSSubsequentMonoPatternFillTrap(ScrnInfoPtr pScrn,
52572b676d7Smrg			int patx, int paty,
52672b676d7Smrg			int y, int h,
52772b676d7Smrg			int left, int dxL, int dyL, int eL,
52872b676d7Smrg			int right, int dxR, int dyR, int eR )
52972b676d7Smrg{
53072b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
53172b676d7Smrg	CARD32 dstbase = 0;
53272b676d7Smrg
53372b676d7Smrg	if(y >= 2048) {
53472b676d7Smrg	   dstbase = pSiS->scrnOffset * y;
53572b676d7Smrg	   y = 0;
53672b676d7Smrg	}
53772b676d7Smrg#ifdef SISDUALHEAD
53872b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
53972b676d7Smrg	   dstbase += HEADOFFSET;
54072b676d7Smrg	}
54172b676d7Smrg#endif
54272b676d7Smrg	SiSSetupDSTBase(dstbase)
54372b676d7Smrg
54472b676d7Smrg	/* Clear CommandReg because SetUp can be used for Rect and Trap */
54572b676d7Smrg	pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR |
54672b676d7Smrg			      T_L_X_INC | T_L_Y_INC |
54772b676d7Smrg			      T_R_X_INC | T_R_Y_INC |
54872b676d7Smrg			      BITBLT);
54972b676d7Smrg
55072b676d7Smrg	if(dxL < 0) { dxL = -dxL;  }
55172b676d7Smrg	else { SiSSetupCMDFlag(T_L_X_INC) }
55272b676d7Smrg	if(dxR < 0) { dxR = -dxR; }
55372b676d7Smrg	else { SiSSetupCMDFlag(T_R_X_INC) }
55472b676d7Smrg
55572b676d7Smrg	if(dyL < 0) { dyL = -dyL; }
55672b676d7Smrg	else { SiSSetupCMDFlag(T_L_Y_INC) }
55772b676d7Smrg	if(dyR < 0) { dyR = -dyR; }
55872b676d7Smrg	else { SiSSetupCMDFlag(T_R_Y_INC) }
55972b676d7Smrg
56072b676d7Smrg	/* Determine major axis */
56172b676d7Smrg	if(dxL >= dyL) {      /* X is major axis */
56272b676d7Smrg	   SiSSetupCMDFlag(T_XISMAJORL)
56372b676d7Smrg	}
56472b676d7Smrg	if(dxR >= dyR) {      /* X is major axis */
56572b676d7Smrg	   SiSSetupCMDFlag(T_XISMAJORR)
56672b676d7Smrg	}
56772b676d7Smrg
56872b676d7Smrg	SiSSetupYH(y,h)
56972b676d7Smrg	SiSSetupLR(left,right)
57072b676d7Smrg
57172b676d7Smrg	SiSSetupdL(dxL, dyL)
57272b676d7Smrg	SiSSetupdR(dxR, dyR)
57372b676d7Smrg
57472b676d7Smrg	SiSSetupEL(eL)
57572b676d7Smrg	SiSSetupER(eR)
57672b676d7Smrg
57772b676d7Smrg	SiSSetupCMDFlag(TRAPAZOID_FILL);
57872b676d7Smrg
57972b676d7Smrg	SiSDoCMD
58072b676d7Smrg}
58172b676d7Smrg#endif
58272b676d7Smrg
58372b676d7Smrg/* ------ Screen To Screen Color Expand ------------------------------- */
58472b676d7Smrg
58572b676d7Smrg/* The hareware does not seem to support this the way we need it */
58672b676d7Smrg
58772b676d7Smrg#ifdef STSCE
58872b676d7Smrgstatic void
58972b676d7SmrgSiSSetupForScreenToScreenColorExpand(ScrnInfoPtr pScrn,
59072b676d7Smrg			int fg, int bg,
59172b676d7Smrg			int rop, unsigned int planemask)
59272b676d7Smrg{
59372b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
59472b676d7Smrg
59572b676d7Smrg	SiSSetupDSTColorDepth(pSiS->DstColor)
59672b676d7Smrg	SiSSetupDSTRect(pSiS->scrnOffset, -1)
59772b676d7Smrg	SiSSetupROP(SiSGetCopyROP(rop))
59872b676d7Smrg	SiSSetupSRCFG(fg)
59972b676d7Smrg	/* SiSSetupSRCXY(0,0) */
60072b676d7Smrg
60172b676d7Smrg	if(bg == -1) {
60272b676d7Smrg	   SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | X_INC |
60372b676d7Smrg				Y_INC | SRCVIDEO);
60472b676d7Smrg	} else {
60572b676d7Smrg	   SiSSetupSRCBG(bg);
60672b676d7Smrg	   SiSSetupCMDFlag(ENCOLOREXP | X_INC | Y_INC |
60772b676d7Smrg				SRCVIDEO);
60872b676d7Smrg	};
60972b676d7Smrg}
61072b676d7Smrg#endif
61172b676d7Smrg
61272b676d7Smrg/* This method blits in a single task; this does not seem to work
61372b676d7Smrg * because the hardware does not use the source pitch as scanline
61472b676d7Smrg * offset but only to calculate pattern address from source X and Y.
61572b676d7Smrg * XAA provides the pattern bitmap with scrnOffset (displayWidth * bpp/8)
61672b676d7Smrg * offset, but this does not seem to be supported by the hardware.
61772b676d7Smrg */
61872b676d7Smrg#ifdef STSCE
61972b676d7Smrg
62072b676d7Smrg/* For testing, these are the methods: (use only one at a time!) */
62172b676d7Smrg
62272b676d7Smrg#undef npitch		/* Normal: Use srcx/y as srcx/y, use scrnOffset as source pitch
62372b676d7Smrg			 * This would work if the hareware used the source pitch for
62472b676d7Smrg			 * incrementing the source address after each scanline - but
62572b676d7Smrg			 * it doesn't do this! The first line of the area is correctly
62672b676d7Smrg			 * color expanded, but since the source pitch is ignored and
62772b676d7Smrg			 * the source address not incremented correctly, the following
62872b676d7Smrg			 * lines are color expanded with any bit pattern that is left
62972b676d7Smrg			 * in the unused space of the source bitmap (which is organized
63072b676d7Smrg			 * with the depth of the screen framebuffer hence with a pitch
63172b676d7Smrg			 * of scrnOffset).
63272b676d7Smrg			 */
63372b676d7Smrg
63472b676d7Smrg#undef pitchdw		/* Use source pitch "displayWidth / 8" instead
63572b676d7Smrg			 * of scrnOffset (=displayWidth * bpp / 8)
63672b676d7Smrg			 * This can't work, because the pitch of the source
63772b676d7Smrg			 * bitmap is scrnoffset!
63872b676d7Smrg			 */
63972b676d7Smrg
64072b676d7Smrg#define nopitch		/* Calculate srcbase with srcx and srcy, set the
64172b676d7Smrg			 * pitch to scrnOffset (which IS the correct pitch
64272b676d7Smrg			 * for the source bitmap) and set srcx and srcy both
64372b676d7Smrg			 * to 0.
64472b676d7Smrg			 * This would work if the hareware used the source pitch for
64572b676d7Smrg			 * incrementing the source address after each scanline - but
64672b676d7Smrg			 * it doesn't do this! Again: The first line of the area is
64772b676d7Smrg			 * correctly color expanded, but since the source pitch is
64872b676d7Smrg			 * ignored for scanline address incremention, the following
64972b676d7Smrg			 * lines are not correctly color expanded.
65072b676d7Smrg			 * WHATEVER I write to source pitch is ignored!
65172b676d7Smrg			 */
65272b676d7Smrg
65372b676d7Smrgstatic void
65472b676d7SmrgSiSSubsequentScreenToScreenColorExpand(ScrnInfoPtr pScrn,
65572b676d7Smrg			int x, int y, int w, int h,
65672b676d7Smrg			int srcx, int srcy, int skipleft)
65772b676d7Smrg{
65872b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
65972b676d7Smrg        CARD32 srcbase, dstbase;
66072b676d7Smrg#if 0
66172b676d7Smrg	int _x0, _y0, _x1, _y1;
66272b676d7Smrg#endif
66372b676d7Smrg#ifdef pitchdw
66472b676d7Smrg	int newsrcx, newsrcy;
66572b676d7Smrg
66672b676d7Smrg	/* srcx and srcy are provided based on a scrnOffset pitch ( = displayWidth * bpp / 8 )
66772b676d7Smrg	 * We recalulate srcx and srcy based on pitch = displayWidth / 8
66872b676d7Smrg	 */
66972b676d7Smrg        newsrcy = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) /
67072b676d7Smrg					  (pScrn->displayWidth/8);
67172b676d7Smrg        newsrcx = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) %
67272b676d7Smrg					  (pScrn->displayWidth/8);
67372b676d7Smrg#endif
67472b676d7Smrg	xf86DrvMsg(0, X_INFO, "Sub ScreenToScreen ColorExp(%d,%d, %d,%d, %d,%d, %d)\n",
67572b676d7Smrg					x, y, w, h, srcx, srcy, skipleft);
67672b676d7Smrg
67772b676d7Smrg	srcbase = dstbase = 0;
67872b676d7Smrg
67972b676d7Smrg#ifdef pitchdw
68072b676d7Smrg	if(newsrcy >= 2048) {
68172b676d7Smrg	   srcbase = (pScrn->displayWidth / 8) * newsrcy;
68272b676d7Smrg	   newsrcy = 0;
68372b676d7Smrg	}
68472b676d7Smrg#endif
68572b676d7Smrg#ifdef nopitch
68672b676d7Smrg	srcbase = (pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8));
68772b676d7Smrg#endif
68872b676d7Smrg#ifdef npitch
68972b676d7Smrg	if(srcy >= 2048) {
69072b676d7Smrg	   srcbase = pSiS->scrnOffset * srcy;
69172b676d7Smrg	   srcy = 0;
69272b676d7Smrg	}
69372b676d7Smrg#endif
69472b676d7Smrg	if(y >= 2048) {
69572b676d7Smrg	   dstbase = pSiS->scrnOffset * y;
69672b676d7Smrg	   y = 0;
69772b676d7Smrg	}
69872b676d7Smrg#ifdef SISDUALHEAD
69972b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
70072b676d7Smrg	   srcbase += HEADOFFSET;
70172b676d7Smrg	   dstbase += HEADOFFSET;
70272b676d7Smrg	}
70372b676d7Smrg#endif
70472b676d7Smrg	SiSSetupSRCBase(srcbase)
70572b676d7Smrg	SiSSetupDSTBase(dstbase)
70672b676d7Smrg
70772b676d7Smrg#ifdef pitchdw
70872b676d7Smrg	SiSSetupSRCPitch(pScrn->displayWidth/8)
70972b676d7Smrg#endif
71072b676d7Smrg#ifdef nopitch
71172b676d7Smrg	SiSSetupSRCPitch(pSiS->scrnOffset)
71272b676d7Smrg	/* SiSSetupSRCPitch(100) */ /* For test - has NO effect WHATSOEVER */
71372b676d7Smrg#endif
71472b676d7Smrg#ifdef npitch
71572b676d7Smrg	SiSSetupSRCPitch(pSiS->scrnOffset)
71672b676d7Smrg#endif
71772b676d7Smrg
71872b676d7Smrg	SiSSetupRect(w,h)
71972b676d7Smrg
72072b676d7Smrg#if 0   /* How do I implement the offset? Not this way, that's for sure.. */
72172b676d7Smrg	if (skipleft > 0) {
72272b676d7Smrg		_x0 = x+skipleft;
72372b676d7Smrg		_y0 = y;
72472b676d7Smrg		_x1 = x+w;
72572b676d7Smrg		_y1 = y+h;
72672b676d7Smrg		SiSSetupClipLT(_x0, _y0);
72772b676d7Smrg		SiSSetupClipRB(_x1, _y1);
72872b676d7Smrg		SiSSetupCMDFlag(CLIPENABLE);
72972b676d7Smrg	}
73072b676d7Smrg#endif
73172b676d7Smrg#ifdef pitchdw
73272b676d7Smrg	SiSSetupSRCXY(newsrcx, newsrcy)
73372b676d7Smrg#endif
73472b676d7Smrg#ifdef nopitch
73572b676d7Smrg	SiSSetupSRCXY(0,0)
73672b676d7Smrg#endif
73772b676d7Smrg#ifdef npitch
73872b676d7Smrg	SiSSetupSRCXY(srcx, srcy)
73972b676d7Smrg#endif
74072b676d7Smrg
74172b676d7Smrg	SiSSetupDSTXY(x,y)
74272b676d7Smrg
74372b676d7Smrg	SiSDoCMD
74472b676d7Smrg}
74572b676d7Smrg#endif
74672b676d7Smrg
74772b676d7Smrg/* ----- CPU To Screen Color Expand (scanline-wise) ----------------- */
74872b676d7Smrg
74972b676d7Smrg/* We do it using the indirect method */
75072b676d7Smrg
75172b676d7Smrgstatic void
75272b676d7SmrgSiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
75372b676d7Smrg			int fg, int bg, int rop, unsigned int planemask)
75472b676d7Smrg{
75572b676d7Smrg	SISPtr pSiS=SISPTR(pScrn);
75672b676d7Smrg
75772b676d7Smrg        /* Make sure that current CPU-driven BitBlt buffer stage is 0
75872b676d7Smrg	 * This is required!!! (Otherwise -> drawing errors)
75972b676d7Smrg	 */
76072b676d7Smrg	while((SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0x1F00) != 0) {} /* WDR: == 0x10 */
76172b676d7Smrg
76272b676d7Smrg	SiSSetupSRCXY(0,0);
76372b676d7Smrg	SiSSetupROP(SiSGetCopyROP(rop));
76472b676d7Smrg	SiSSetupSRCFG(fg);
76572b676d7Smrg	SiSSetupDSTRect(pSiS->scrnOffset, -1);
76672b676d7Smrg	SiSSetupDSTColorDepth(pSiS->DstColor);
76772b676d7Smrg	if(bg == -1) {
76872b676d7Smrg	   SiSSetupCMDFlag(TRANSPARENT |
76972b676d7Smrg			   ENCOLOREXP |
77072b676d7Smrg			   X_INC | Y_INC |
77172b676d7Smrg			   SRCCPUBLITBUF);
77272b676d7Smrg	} else {
77372b676d7Smrg	   SiSSetupSRCBG(bg);
77472b676d7Smrg	   SiSSetupCMDFlag(ENCOLOREXP |
77572b676d7Smrg			   X_INC | Y_INC |
77672b676d7Smrg			   SRCCPUBLITBUF);
77772b676d7Smrg	}
77872b676d7Smrg}
77972b676d7Smrg
78072b676d7Smrg
78172b676d7Smrgstatic void
78272b676d7SmrgSiSSubsequentScanlineCPUToScreenColorExpandFill(
78372b676d7Smrg			ScrnInfoPtr pScrn, int x, int y, int w,
78472b676d7Smrg			int h, int skipleft)
78572b676d7Smrg{
78672b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
78772b676d7Smrg	int    _x0, _y0, _x1, _y1;
78872b676d7Smrg	CARD32 dstbase = 0;
78972b676d7Smrg
79072b676d7Smrg	if((y >= 2048) || ((y + h) >= 2048)) {
79172b676d7Smrg	   dstbase = pSiS->scrnOffset * y;
79272b676d7Smrg	   y = 0;
79372b676d7Smrg	}
79472b676d7Smrg#ifdef SISDUALHEAD
79572b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
79672b676d7Smrg	   dstbase += HEADOFFSET;
79772b676d7Smrg	}
79872b676d7Smrg#endif
79972b676d7Smrg
80072b676d7Smrg	/* Wait until there is no color expansion command in queue
80172b676d7Smrg	 * (This solves the OpenOffice.org window-move bug)
80272b676d7Smrg	 * Added Idle-check - bit 23 is set sometimes, although
80372b676d7Smrg	 * engine is actually idle!
80472b676d7Smrg	 * Update: Bit 23 is not reliable. After heavy 3D engine
80572b676d7Smrg	 * action, this bit never gets cleared again. So do
80672b676d7Smrg	 * SiSIdle instead.
80772b676d7Smrg	 */
80872b676d7Smrg	if((SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0xe000) != 0xe000) {
80972b676d7Smrg           /* while ((SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0x0080) != 0) {} */
81072b676d7Smrg	   SiSIdle
81172b676d7Smrg	}
81272b676d7Smrg
81372b676d7Smrg	SiSSetupDSTBase(dstbase)
81472b676d7Smrg
81572b676d7Smrg	if(skipleft > 0) {
81672b676d7Smrg	   _x0 = x + skipleft;
81772b676d7Smrg	   _y0 = y;
81872b676d7Smrg	   _x1 = x + w;
81972b676d7Smrg	   _y1 = y + h;
82072b676d7Smrg	   SiSSetupClipLT(_x0, _y0);
82172b676d7Smrg	   SiSSetupClipRB(_x1, _y1);
82272b676d7Smrg	   SiSSetupCMDFlag(CLIPENABLE);
82372b676d7Smrg	} else {
82472b676d7Smrg	   pSiS->CommandReg &= (~CLIPENABLE);
82572b676d7Smrg	}
82672b676d7Smrg
82772b676d7Smrg	SiSSetupRect(w, 1);
82872b676d7Smrg        SiSSetupSRCPitch(((((w + 7) / 8) + 3) >> 2) * 4);
82972b676d7Smrg	pSiS->xcurrent = x;
83072b676d7Smrg	pSiS->ycurrent = y;
83172b676d7Smrg}
83272b676d7Smrg
83372b676d7Smrgstatic void
83472b676d7SmrgSiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
83572b676d7Smrg{
83672b676d7Smrg	SISPtr pSiS=SISPTR(pScrn);
83772b676d7Smrg#if 0
83872b676d7Smrg	int newhead,bltbufstage,newtail;
83972b676d7Smrg#endif
84072b676d7Smrg	CARD32 cbo;
84172b676d7Smrg
84272b676d7Smrg	cbo = pSiS->ColorExpandBufferScreenOffset[bufno];
84372b676d7Smrg#ifdef SISDUALHEAD
84472b676d7Smrg	if(pSiS->VGAEngine != SIS_530_VGA) {
84572b676d7Smrg	   cbo += HEADOFFSET;
84672b676d7Smrg	}
84772b676d7Smrg#endif
84872b676d7Smrg
84972b676d7Smrg	/* Wait until there is no color expansion command in queue
85072b676d7Smrg	 * (This solves the GTK-big-font bug)
85172b676d7Smrg	 * Added Idle-check - bit 23 is set sometimes, although
85272b676d7Smrg	 * engine is actually idle!
85372b676d7Smrg	 * Update: Bit 23 is not reliable. After heavy 3D engine
85472b676d7Smrg	 * action, this bit never gets cleared again. So do
85572b676d7Smrg	 * SiSIdle instead.
85672b676d7Smrg	 */
85772b676d7Smrg	if((SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0xe000) != 0xe000) {
85872b676d7Smrg	   /* while ((SIS_MMIO_IN16(pSiS->IOBase, 0x8242) & 0x0080) != 0) {} */
85972b676d7Smrg	   SiSIdle
86072b676d7Smrg	}
86172b676d7Smrg
86272b676d7Smrg	SiSSetupSRCBase(cbo);
86372b676d7Smrg
86472b676d7Smrg	SiSSetupDSTXY(pSiS->xcurrent, pSiS->ycurrent);
86572b676d7Smrg
86672b676d7Smrg	SiSDoCMD
86772b676d7Smrg
86872b676d7Smrg	pSiS->ycurrent++;
86972b676d7Smrg
87072b676d7Smrg	if(pSiS->VGAEngine == SIS_530_VGA) {
87172b676d7Smrg	   while(SIS_MMIO_IN8(pSiS->IOBase, 0x8242) & 0x80) {}
87272b676d7Smrg	}
87372b676d7Smrg}
87472b676d7Smrg
87572b676d7Smrg#endif /* XAA */
87672b676d7Smrg
87772b676d7Smrg#ifdef SIS_USE_EXA  /* ---------------------------- EXA -------------------------- */
87872b676d7Smrg
87972b676d7Smrgstatic const unsigned short dstcol[] = { 0x0000, 0x8000, 0xc000 };
88072b676d7Smrg
88172b676d7Smrgstatic void
88272b676d7SmrgSiSEXASync(ScreenPtr pScreen, int marker)
88372b676d7Smrg{
88474c14cd6Smrg	SISPtr pSiS = SISPTR(xf86ScreenToScrn(pScreen));
88572b676d7Smrg
88672b676d7Smrg	SiSIdle
88772b676d7Smrg}
88872b676d7Smrg
88972b676d7Smrgstatic Bool
89072b676d7SmrgSiSPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
89172b676d7Smrg{
89274c14cd6Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
89372b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
89472b676d7Smrg	CARD32 dstbase;
89572b676d7Smrg
89672b676d7Smrg	/* Planemask not supported */
89772b676d7Smrg	if((planemask & ((1 << pPixmap->drawable.depth) - 1)) !=
89872b676d7Smrg				(1 << pPixmap->drawable.depth) - 1) {
89972b676d7Smrg	   return FALSE;
90072b676d7Smrg	}
90172b676d7Smrg
90272b676d7Smrg	/* Since the 530/620 have no "dest color depth" register, I
90372b676d7Smrg	 * assume that the 2D engine reads the current color depth
90472b676d7Smrg	 * from the DAC.... FIXME ? */
90572b676d7Smrg	if(pSiS->VGAEngine == SIS_530_VGA) {
90672b676d7Smrg	   if(pPixmap->drawable.bitsPerPixel != pSiS->CurrentLayout.bitsPerPixel)
90772b676d7Smrg	      return FALSE;
90872b676d7Smrg	} else if((pPixmap->drawable.bitsPerPixel != 8)  &&
90972b676d7Smrg		  (pPixmap->drawable.bitsPerPixel != 16) &&
91072b676d7Smrg		  (pPixmap->drawable.bitsPerPixel != 32))
91172b676d7Smrg	   return FALSE;
91272b676d7Smrg
91372b676d7Smrg	if(pSiS->disablecolorkeycurrent) {
91472b676d7Smrg	   if((CARD32)fg == pSiS->colorKey) {
91572b676d7Smrg	      alu = 5;  /* NOOP */
91672b676d7Smrg	   }
91772b676d7Smrg	}
91872b676d7Smrg
91972b676d7Smrg	/* Check that the pitch matches the hardware's requirements. Should
92072b676d7Smrg	 * never be a problem due to pixmapPitchAlign and fbScreenInit.
92172b676d7Smrg	 */
92272b676d7Smrg	if(exaGetPixmapPitch(pPixmap) & 3)
92372b676d7Smrg	   return FALSE;
92472b676d7Smrg
92572b676d7Smrg	dstbase = (CARD32)exaGetPixmapOffset(pPixmap) + HEADOFFSET;
92672b676d7Smrg
92772b676d7Smrg	SiSSetupPATFG(fg)
92872b676d7Smrg	SiSSetupDSTRect(exaGetPixmapPitch(pPixmap), -1)
92972b676d7Smrg	SiSSetupDSTColorDepth(dstcol[pPixmap->drawable.bitsPerPixel >> 4]);
93072b676d7Smrg	SiSSetupROP(SiSGetPatternROP(alu))
93172b676d7Smrg	SiSSetupDSTBase(dstbase)
93272b676d7Smrg	/* SiSSetupCMDFlag(PATFG) - is zero */
93372b676d7Smrg
93472b676d7Smrg	return TRUE;
93572b676d7Smrg}
93672b676d7Smrg
93772b676d7Smrgstatic void
93872b676d7SmrgSiSSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
93972b676d7Smrg{
94074c14cd6Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen);
94172b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
94272b676d7Smrg
94372b676d7Smrg	SiSSetupDSTXY(x1, y1)
94472b676d7Smrg	SiSSetupRect(x2-x1, y2-y1)
94572b676d7Smrg
94672b676d7Smrg	SiSSetupCMDFlag(X_INC | Y_INC | BITBLT)
94772b676d7Smrg
94872b676d7Smrg	SiSDoCMD
94972b676d7Smrg}
95072b676d7Smrg
95172b676d7Smrgstatic void
95272b676d7SmrgSiSDoneSolid(PixmapPtr pPixmap)
95372b676d7Smrg{
95472b676d7Smrg}
95572b676d7Smrg
95672b676d7Smrgstatic Bool
95772b676d7SmrgSiSPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir,
95872b676d7Smrg					int alu, Pixel planemask)
95972b676d7Smrg{
96074c14cd6Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
96172b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
96272b676d7Smrg	CARD32 srcbase, dstbase;
96372b676d7Smrg
96472b676d7Smrg	/* Planemask not supported */
96572b676d7Smrg	if((planemask & ((1 << pSrcPixmap->drawable.depth) - 1)) !=
96672b676d7Smrg				(1 << pSrcPixmap->drawable.depth) - 1) {
96772b676d7Smrg	   return FALSE;
96872b676d7Smrg	}
96972b676d7Smrg
97072b676d7Smrg	/* Since the 530/620 have no "dest color depth" register, I
97172b676d7Smrg	 * assume that the 2D engine reads the current color depth
97272b676d7Smrg	 * from the DAC.... FIXME ? */
97372b676d7Smrg	if(pSiS->VGAEngine == SIS_530_VGA) {
97472b676d7Smrg	   if(pDstPixmap->drawable.bitsPerPixel != pSiS->CurrentLayout.bitsPerPixel)
97572b676d7Smrg	      return FALSE;
97672b676d7Smrg	} else if((pDstPixmap->drawable.bitsPerPixel != 8)  &&
97772b676d7Smrg		  (pDstPixmap->drawable.bitsPerPixel != 16) &&
97872b676d7Smrg		  (pDstPixmap->drawable.bitsPerPixel != 32))
97972b676d7Smrg	   return FALSE;
98072b676d7Smrg
98172b676d7Smrg	/* Check that the pitch matches the hardware's requirements. Should
98272b676d7Smrg	 * never be a problem due to pixmapPitchAlign and fbScreenInit.
98372b676d7Smrg	 */
98472b676d7Smrg	if(exaGetPixmapPitch(pSrcPixmap) & 3)
98572b676d7Smrg	   return FALSE;
98672b676d7Smrg	if(exaGetPixmapPitch(pDstPixmap) & 3)
98772b676d7Smrg	   return FALSE;
98872b676d7Smrg
98972b676d7Smrg	SiSSetupDSTColorDepth(dstcol[pDstPixmap->drawable.bitsPerPixel >> 4]);
99072b676d7Smrg	SiSSetupSRCPitch(exaGetPixmapPitch(pSrcPixmap))
99172b676d7Smrg	SiSSetupDSTRect(exaGetPixmapPitch(pDstPixmap), -1)
99272b676d7Smrg
99372b676d7Smrg	SiSSetupROP(SiSGetCopyROP(alu))
99472b676d7Smrg
99572b676d7Smrg	if(xdir >= 0) {
99672b676d7Smrg	   SiSSetupCMDFlag(X_INC)
99772b676d7Smrg	}
99872b676d7Smrg	if(ydir >= 0) {
99972b676d7Smrg	   SiSSetupCMDFlag(Y_INC)
100072b676d7Smrg	}
100172b676d7Smrg
100272b676d7Smrg	srcbase = (CARD32)exaGetPixmapOffset(pSrcPixmap) + HEADOFFSET;
100372b676d7Smrg
100472b676d7Smrg	dstbase = (CARD32)exaGetPixmapOffset(pDstPixmap) + HEADOFFSET;
100572b676d7Smrg
100672b676d7Smrg	SiSSetupSRCBase(srcbase);
100772b676d7Smrg	SiSSetupDSTBase(dstbase);
100872b676d7Smrg
100972b676d7Smrg	return TRUE;
101072b676d7Smrg}
101172b676d7Smrg
101272b676d7Smrgstatic void
101372b676d7SmrgSiSCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height)
101472b676d7Smrg{
101574c14cd6Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pDstPixmap->drawable.pScreen);
101672b676d7Smrg	SISPtr pSiS = SISPTR(pScrn);
101772b676d7Smrg
101872b676d7Smrg	if(!(pSiS->CommandReg & X_INC))  {
101972b676d7Smrg	   srcX += width-1;
102072b676d7Smrg	   dstX += width-1;
102172b676d7Smrg	}
102272b676d7Smrg	if(!(pSiS->CommandReg & Y_INC))  {
102372b676d7Smrg	   srcY += height-1;
102472b676d7Smrg	   dstY += height-1;
102572b676d7Smrg	}
102672b676d7Smrg	SiSSetupRect(width, height)
102772b676d7Smrg	SiSSetupSRCXY(srcX, srcY)
102872b676d7Smrg	SiSSetupDSTXY(dstX, dstY)
102972b676d7Smrg
103072b676d7Smrg	SiSDoCMD
103172b676d7Smrg}
103272b676d7Smrg
103372b676d7Smrgstatic void
103472b676d7SmrgSiSDoneCopy(PixmapPtr pDstPixmap)
103572b676d7Smrg{
103672b676d7Smrg}
103772b676d7Smrg
103872b676d7Smrg#endif /* EXA */
103972b676d7Smrg
104072b676d7Smrg/* For DGA usage */
104172b676d7Smrg
104272b676d7Smrgstatic void
104372b676d7SmrgSiSDGAFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, int color)
104472b676d7Smrg{
104572b676d7Smrg	SiSSetupForSolidFill(pScrn, color, GXcopy, ~0);
104672b676d7Smrg	SiSSubsequentSolidFillRect(pScrn, x, y, w, h);
104772b676d7Smrg}
104872b676d7Smrg
104972b676d7Smrgstatic void
105072b676d7SmrgSiSDGABlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int dstx, int dsty, int w, int h, int color)
105172b676d7Smrg{
105272b676d7Smrg	int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
105372b676d7Smrg	int ydir = (srcy < dsty) ? -1 : 1;
105472b676d7Smrg
105572b676d7Smrg	SiSSetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, (CARD32)~0, color);
105672b676d7Smrg	SiSSubsequentScreenToScreenCopy(pScrn, srcx, srcy, dstx, dsty, w, h);
105772b676d7Smrg}
105872b676d7Smrg
105972b676d7Smrg/* Initialisation */
106072b676d7Smrg
106172b676d7SmrgBool
106272b676d7SmrgSiS300AccelInit(ScreenPtr pScreen)
106372b676d7Smrg{
106474c14cd6Smrg	ScrnInfoPtr     pScrn = xf86ScreenToScrn(pScreen);
106572b676d7Smrg	SISPtr          pSiS = SISPTR(pScrn);
106672b676d7Smrg#ifdef SIS_USE_XAA
106772b676d7Smrg	XAAInfoRecPtr   infoPtr = NULL;
106872b676d7Smrg	UChar           *AvailBufBase;
106972b676d7Smrg	int		topFB, reservedFbSize, usableFbSize, i;
107072b676d7Smrg	BoxRec          Avail;
107172b676d7Smrg#endif /* XAA */
107272b676d7Smrg
107372b676d7Smrg	pSiS->ColorExpandBufferNumber = 0;
107472b676d7Smrg	pSiS->PerColorExpandBufferSize = 0;
107572b676d7Smrg	pSiS->RenderAccelArray = NULL;
107672b676d7Smrg#ifdef SIS_USE_XAA
107772b676d7Smrg	pSiS->AccelInfoPtr = NULL;
107872b676d7Smrg#endif
107972b676d7Smrg#ifdef SIS_USE_EXA
108072b676d7Smrg	pSiS->EXADriverPtr = NULL;
108172b676d7Smrg	pSiS->exa_scratch = NULL;
108272b676d7Smrg#endif
108372b676d7Smrg
108472b676d7Smrg	if((pScrn->bitsPerPixel != 8)  &&
108572b676d7Smrg	   (pScrn->bitsPerPixel != 16) &&
108672b676d7Smrg	   (pScrn->bitsPerPixel != 32)) {
108772b676d7Smrg	   pSiS->NoAccel = TRUE;
108872b676d7Smrg	}
108972b676d7Smrg
109072b676d7Smrg	if(!pSiS->NoAccel) {
109172b676d7Smrg#ifdef SIS_USE_XAA
109272b676d7Smrg	   if(!pSiS->useEXA) {
109372b676d7Smrg	      pSiS->AccelInfoPtr = infoPtr = XAACreateInfoRec();
109472b676d7Smrg	      if(!infoPtr) pSiS->NoAccel = TRUE;
109572b676d7Smrg	   }
109672b676d7Smrg#endif
109772b676d7Smrg#ifdef SIS_USE_EXA
109872b676d7Smrg	   if(pSiS->useEXA) {
109972b676d7Smrg	      if(!(pSiS->EXADriverPtr = exaDriverAlloc())) {
110072b676d7Smrg		 pSiS->NoAccel = TRUE;
110172b676d7Smrg		 pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */
110272b676d7Smrg	      }
110372b676d7Smrg	   }
110472b676d7Smrg#endif
110572b676d7Smrg	}
110672b676d7Smrg
110772b676d7Smrg	if(!pSiS->NoAccel) {
110872b676d7Smrg
110972b676d7Smrg	   SiSInitializeAccelerator(pScrn);
111072b676d7Smrg
111172b676d7Smrg	   pSiS->InitAccel = SiSInitializeAccelerator;
111272b676d7Smrg	   pSiS->SyncAccel = SiSSyncAccel;
111372b676d7Smrg	   pSiS->FillRect  = SiSDGAFillRect;
111472b676d7Smrg	   pSiS->BlitRect  = SiSDGABlitRect;
111572b676d7Smrg
111672b676d7Smrg#ifdef SIS_USE_XAA	/* ----------------------- XAA ----------------------- */
111772b676d7Smrg	   if(!pSiS->useEXA) {
111872b676d7Smrg
111972b676d7Smrg	      infoPtr->Flags = LINEAR_FRAMEBUFFER |
112072b676d7Smrg			       OFFSCREEN_PIXMAPS |
112172b676d7Smrg			       PIXMAP_CACHE;
112272b676d7Smrg
112372b676d7Smrg	      /* sync */
112472b676d7Smrg	      infoPtr->Sync = SiSSync;
112572b676d7Smrg
112672b676d7Smrg	      /* Although SiS states that the 300 series supports a
112772b676d7Smrg	       * virtual screen of 4096x4096, the 2D accelerator
112872b676d7Smrg	       * does not seem to know that. If the destination bitmap
112972b676d7Smrg	       * pitch is > 8192 (which easily happens in 32bpp mode),
113072b676d7Smrg	       * the accelerator engine collapses.
113172b676d7Smrg	       * TODO: Find out about the 530 and 620
113272b676d7Smrg	       */
113372b676d7Smrg
113472b676d7Smrg	      if(pSiS->scrnOffset < 8192) {
113572b676d7Smrg
113672b676d7Smrg		 /* screen to screen copy */
113772b676d7Smrg		 infoPtr->SetupForScreenToScreenCopy = SiSSetupForScreenToScreenCopy;
113872b676d7Smrg		 infoPtr->SubsequentScreenToScreenCopy = SiSSubsequentScreenToScreenCopy;
113972b676d7Smrg		 infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK |
114072b676d7Smrg						    TRANSPARENCY_GXCOPY_ONLY;
114172b676d7Smrg
114272b676d7Smrg		 /* solid fills */
114372b676d7Smrg		 infoPtr->SetupForSolidFill = SiSSetupForSolidFill;
114472b676d7Smrg		 infoPtr->SubsequentSolidFillRect = SiSSubsequentSolidFillRect;
114572b676d7Smrg#ifdef TRAP
114672b676d7Smrg		 infoPtr->SubsequentSolidFillTrap = SiSSubsequentSolidFillTrap;
114772b676d7Smrg#endif
114872b676d7Smrg		 infoPtr->SolidFillFlags = NO_PLANEMASK;
114972b676d7Smrg
115072b676d7Smrg		 /* solid line */
115172b676d7Smrg	         infoPtr->SetupForSolidLine = SiSSetupForSolidLine;
115272b676d7Smrg		 infoPtr->SubsequentSolidTwoPointLine = SiSSubsequentSolidTwoPointLine;
115372b676d7Smrg		 infoPtr->SubsequentSolidHorVertLine = SiSSubsequentSolidHorzVertLine;
115472b676d7Smrg		 infoPtr->SolidLineFlags = NO_PLANEMASK;
115572b676d7Smrg
115672b676d7Smrg		 /* dashed line */
115772b676d7Smrg		 infoPtr->SetupForDashedLine = SiSSetupForDashedLine;
115872b676d7Smrg		 infoPtr->SubsequentDashedTwoPointLine = SiSSubsequentDashedTwoPointLine;
115972b676d7Smrg		 infoPtr->DashPatternMaxLength = 64;
116072b676d7Smrg		 infoPtr->DashedLineFlags = NO_PLANEMASK |
116172b676d7Smrg					    LINE_PATTERN_MSBFIRST_LSBJUSTIFIED;
116272b676d7Smrg
116372b676d7Smrg		 /* 8x8 mono pattern fill */
116472b676d7Smrg		 infoPtr->SetupForMono8x8PatternFill = SiSSetupForMonoPatternFill;
116572b676d7Smrg		 infoPtr->SubsequentMono8x8PatternFillRect = SiSSubsequentMonoPatternFill;
116672b676d7Smrg#ifdef TRAP
116772b676d7Smrg		 infoPtr->SubsequentMono8x8PatternFillTrap = SiSSubsequentMonoPatternFillTrap;
116872b676d7Smrg#endif
116972b676d7Smrg		 infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK |
117072b676d7Smrg						    HARDWARE_PATTERN_SCREEN_ORIGIN |
117172b676d7Smrg						    HARDWARE_PATTERN_PROGRAMMED_BITS |
117272b676d7Smrg						    /* NO_TRANSPARENCY | */
117372b676d7Smrg						    BIT_ORDER_IN_BYTE_MSBFIRST ;
117472b676d7Smrg
117572b676d7Smrg#ifdef STSCE
117672b676d7Smrg		 /* Screen To Screen Color Expand */
117772b676d7Smrg		 /* The hardware does support this the way we need it */
117872b676d7Smrg		 infoPtr->SetupForScreenToScreenColorExpandFill =
117972b676d7Smrg				SiSSetupForScreenToScreenColorExpand;
118072b676d7Smrg		 infoPtr->SubsequentScreenToScreenColorExpandFill =
118172b676d7Smrg				SiSSubsequentScreenToScreenColorExpand;
118272b676d7Smrg		 infoPtr->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK |
118372b676d7Smrg							       BIT_ORDER_IN_BYTE_MSBFIRST ;
118472b676d7Smrg#endif
118572b676d7Smrg
118672b676d7Smrg		 /* per-scanline color expansion (using indirect method) */
118772b676d7Smrg		 if(pSiS->VGAEngine == SIS_530_VGA) {
118872b676d7Smrg		    pSiS->ColorExpandBufferNumber = 4;
118972b676d7Smrg		    pSiS->ColorExpandBufferCountMask = 0x03;
119072b676d7Smrg		 } else {
119172b676d7Smrg		    pSiS->ColorExpandBufferNumber = 16;
119272b676d7Smrg		    pSiS->ColorExpandBufferCountMask = 0x0F;
119372b676d7Smrg		 }
119472b676d7Smrg
119572b676d7Smrg		 pSiS->PerColorExpandBufferSize = ((pScrn->virtualX + 31)/32) * 4;
119672b676d7Smrg		 infoPtr->NumScanlineColorExpandBuffers = pSiS->ColorExpandBufferNumber;
119772b676d7Smrg		 infoPtr->ScanlineColorExpandBuffers = (UChar **)&pSiS->ColorExpandBufferAddr[0];
119872b676d7Smrg
119972b676d7Smrg		 infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
120072b676d7Smrg					SiSSetupForScanlineCPUToScreenColorExpandFill;
120172b676d7Smrg		 infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
120272b676d7Smrg					SiSSubsequentScanlineCPUToScreenColorExpandFill;
120372b676d7Smrg		 infoPtr->SubsequentColorExpandScanline =
120472b676d7Smrg					SiSSubsequentColorExpandScanline;
120572b676d7Smrg		 infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
120672b676d7Smrg								    CPU_TRANSFER_PAD_DWORD |
120772b676d7Smrg								    SCANLINE_PAD_DWORD |
120872b676d7Smrg								    BIT_ORDER_IN_BYTE_MSBFIRST |
120972b676d7Smrg								    LEFT_EDGE_CLIPPING;
121072b676d7Smrg	      } else {
121172b676d7Smrg
121272b676d7Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
121372b676d7Smrg			"Virtual screen width too large for accelerator engine\n");
121472b676d7Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
121572b676d7Smrg			"\t2D acceleration and Xv disabled\n");
121672b676d7Smrg		 pSiS->NoXvideo = TRUE;
121772b676d7Smrg
121872b676d7Smrg	      }
121972b676d7Smrg
122072b676d7Smrg#ifdef SISDUALHEAD
122172b676d7Smrg	      if(pSiS->DualHeadMode) {
122272b676d7Smrg		 infoPtr->RestoreAccelState = SiSRestoreAccelState;
122372b676d7Smrg	      }
122472b676d7Smrg#endif
122572b676d7Smrg	   } /* !exa */
122672b676d7Smrg#endif /* XAA */
122772b676d7Smrg
122872b676d7Smrg#ifdef SIS_USE_EXA	/* ----------------------- EXA ----------------------- */
122972b676d7Smrg	   if(pSiS->useEXA) {
123072b676d7Smrg
123172b676d7Smrg	      pSiS->EXADriverPtr->exa_major = 2;
123272b676d7Smrg	      pSiS->EXADriverPtr->exa_minor = 0;
123372b676d7Smrg
123472b676d7Smrg	      if(pSiS->scrnOffset < 8192) {
123572b676d7Smrg
123672b676d7Smrg		 /* data */
123772b676d7Smrg		 pSiS->EXADriverPtr->memoryBase = pSiS->FbBase;
123872b676d7Smrg		 pSiS->EXADriverPtr->memorySize = pSiS->maxxfbmem;
123972b676d7Smrg		 pSiS->EXADriverPtr->offScreenBase = pScrn->virtualX * pScrn->virtualY
124072b676d7Smrg						* ((pScrn->bitsPerPixel + 7) / 8);
124172b676d7Smrg		 if(pSiS->EXADriverPtr->memorySize > pSiS->EXADriverPtr->offScreenBase) {
124272b676d7Smrg		    pSiS->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
124372b676d7Smrg		 } else {
124472b676d7Smrg		    pSiS->NoXvideo = TRUE;
124572b676d7Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
124672b676d7Smrg			"Not enough video RAM for offscreen memory manager. Xv disabled\n");
124772b676d7Smrg		 }
124872b676d7Smrg		 pSiS->EXADriverPtr->pixmapOffsetAlign = 16;	/* src/dst: double quad word boundary */
124972b676d7Smrg		 pSiS->EXADriverPtr->pixmapPitchAlign = 4;		/* pitch:   double word boundary      */
125072b676d7Smrg		 if(pSiS->VGAEngine == SIS_300_VGA) {
125172b676d7Smrg		    pSiS->EXADriverPtr->maxX = 4095;
125272b676d7Smrg		    pSiS->EXADriverPtr->maxY = 4095;
125372b676d7Smrg		 } else {
125472b676d7Smrg		    pSiS->EXADriverPtr->maxX = 2047;
125572b676d7Smrg		    pSiS->EXADriverPtr->maxY = 2047;
125672b676d7Smrg		 }
125772b676d7Smrg
125872b676d7Smrg		 /* Sync */
125972b676d7Smrg		 pSiS->EXADriverPtr->WaitMarker = SiSEXASync;
126072b676d7Smrg
126172b676d7Smrg		 /* Solid fill */
126272b676d7Smrg		 pSiS->EXADriverPtr->PrepareSolid = SiSPrepareSolid;
126372b676d7Smrg		 pSiS->EXADriverPtr->Solid = SiSSolid;
126472b676d7Smrg		 pSiS->EXADriverPtr->DoneSolid = SiSDoneSolid;
126572b676d7Smrg
126672b676d7Smrg		 /* Copy */
126772b676d7Smrg		 pSiS->EXADriverPtr->PrepareCopy = SiSPrepareCopy;
126872b676d7Smrg		 pSiS->EXADriverPtr->Copy = SiSCopy;
126972b676d7Smrg		 pSiS->EXADriverPtr->DoneCopy = SiSDoneCopy;
127072b676d7Smrg
127172b676d7Smrg		 /* Composite not supported */
127272b676d7Smrg
127372b676d7Smrg	      } else {
127472b676d7Smrg
127572b676d7Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
127672b676d7Smrg			"Virtual screen width too large for accelerator engine\n");
127772b676d7Smrg		 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
127872b676d7Smrg			"\t2D acceleration and Xv disabled\n");
127972b676d7Smrg		 pSiS->NoAccel = TRUE;
128072b676d7Smrg		 pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */
128172b676d7Smrg
128272b676d7Smrg	      }
128372b676d7Smrg
128472b676d7Smrg	   }
128572b676d7Smrg#endif /* EXA */
128672b676d7Smrg
128772b676d7Smrg
128872b676d7Smrg	}  /* NoAccel */
128972b676d7Smrg
129072b676d7Smrg	/* Init framebuffer memory manager */
129172b676d7Smrg
129272b676d7Smrg	/* Layout: (Sizes do not reflect correct proportions)
129372b676d7Smrg	 * |--------------++++++++++++++++++++^************==========~~~~~~~~~~~~|
129472b676d7Smrg	 *   UsableFbSize  ColorExpandBuffers | DRI-Heap  |  HWCursor  TurboQueue   300/310/325 series
129572b676d7Smrg	 * |--------------++++++++++++++++++++|  ====================~~~~~~~~~~~~|
129672b676d7Smrg	 *   UsableFbSize  ColorExpandBuffers |        TurboQueue     HWCursor      530/620
129772b676d7Smrg	 *                                  topFB
129872b676d7Smrg	 */
129972b676d7Smrg
130072b676d7Smrg#ifdef SIS_USE_XAA
130172b676d7Smrg	if(!pSiS->useEXA) {
130272b676d7Smrg
130372b676d7Smrg	   topFB = pSiS->maxxfbmem;
130472b676d7Smrg
130572b676d7Smrg	   reservedFbSize = pSiS->ColorExpandBufferNumber * pSiS->PerColorExpandBufferSize;
130672b676d7Smrg
130772b676d7Smrg	   usableFbSize = topFB - reservedFbSize;
130872b676d7Smrg
130972b676d7Smrg	   AvailBufBase = pSiS->FbBase + usableFbSize;
131072b676d7Smrg	   for(i = 0; i < pSiS->ColorExpandBufferNumber; i++) {
131172b676d7Smrg	      pSiS->ColorExpandBufferAddr[i] = AvailBufBase +
131272b676d7Smrg				i * pSiS->PerColorExpandBufferSize;
131372b676d7Smrg	      pSiS->ColorExpandBufferScreenOffset[i] = usableFbSize +
131472b676d7Smrg				i * pSiS->PerColorExpandBufferSize;
131572b676d7Smrg	   }
131672b676d7Smrg
131772b676d7Smrg	   Avail.x1 = 0;
131872b676d7Smrg	   Avail.y1 = 0;
131972b676d7Smrg	   Avail.x2 = pScrn->displayWidth;
132072b676d7Smrg	   Avail.y2 = (usableFbSize / (pScrn->displayWidth * pScrn->bitsPerPixel/8)) - 1;
132172b676d7Smrg
132272b676d7Smrg	   if(Avail.y2 < 0)  Avail.y2 = 32767;
132372b676d7Smrg
132472b676d7Smrg	   if(Avail.y2 < pScrn->currentMode->VDisplay) {
132572b676d7Smrg	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
132672b676d7Smrg			"Not enough video RAM for accelerator. At least "
132772b676d7Smrg			"%dKB needed, %dKB available\n",
132872b676d7Smrg			((((pScrn->displayWidth * pScrn->bitsPerPixel/8)   /* +8 for make it sure */
132972b676d7Smrg		     		* pScrn->currentMode->VDisplay) + reservedFbSize) / 1024) + 8,
133072b676d7Smrg			pSiS->maxxfbmem/1024);
133172b676d7Smrg	      pSiS->NoAccel = TRUE;
133272b676d7Smrg	      pSiS->NoXvideo = TRUE;
133372b676d7Smrg	      XAADestroyInfoRec(pSiS->AccelInfoPtr);
133472b676d7Smrg	      pSiS->AccelInfoPtr = NULL;
133572b676d7Smrg	      return FALSE;
133672b676d7Smrg	   }
133772b676d7Smrg
133872b676d7Smrg	   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
133972b676d7Smrg			"Framebuffer from (%d,%d) to (%d,%d)\n",
134072b676d7Smrg			Avail.x1, Avail.y1, Avail.x2 - 1, Avail.y2 - 1);
134172b676d7Smrg
134272b676d7Smrg	   xf86InitFBManager(pScreen, &Avail);
134372b676d7Smrg
134472b676d7Smrg	   if(!pSiS->NoAccel) {
134572b676d7Smrg	      return XAAInit(pScreen, infoPtr);
134672b676d7Smrg	   }
134772b676d7Smrg	} /* !exa */
134872b676d7Smrg#endif /* XAA */
134972b676d7Smrg
135072b676d7Smrg#ifdef SIS_USE_EXA
135172b676d7Smrg        if(pSiS->useEXA) {
135272b676d7Smrg
135372b676d7Smrg	   if(!pSiS->NoAccel) {
135472b676d7Smrg
135572b676d7Smrg	      if(!exaDriverInit(pScreen, pSiS->EXADriverPtr)) {
135672b676d7Smrg		 pSiS->NoAccel = TRUE;
135772b676d7Smrg		 pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */
135872b676d7Smrg		 return FALSE;
135972b676d7Smrg	      }
136072b676d7Smrg
136172b676d7Smrg	      /* Reserve locked offscreen scratch area of 128K for glyph data */
136272b676d7Smrg	      pSiS->exa_scratch = exaOffscreenAlloc(pScreen, 128 * 1024, 16, TRUE,
136372b676d7Smrg						SiSScratchSave, pSiS);
136472b676d7Smrg	      if(pSiS->exa_scratch) {
136572b676d7Smrg		 pSiS->exa_scratch_next = pSiS->exa_scratch->offset;
136672b676d7Smrg		 pSiS->EXADriverPtr->UploadToScratch = SiSUploadToScratch;
136772b676d7Smrg	      }
136872b676d7Smrg
136972b676d7Smrg	   } else {
137072b676d7Smrg
137172b676d7Smrg	      pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */
137272b676d7Smrg
137372b676d7Smrg	   }
137472b676d7Smrg
137572b676d7Smrg	}
137672b676d7Smrg#endif /* EXA */
137772b676d7Smrg
137872b676d7Smrg	return TRUE;
137972b676d7Smrg}
138072b676d7Smrg
138172b676d7Smrg
138272b676d7Smrg
138372b676d7Smrg
138472b676d7Smrg
138572b676d7Smrg
138672b676d7Smrg
1387