/* $XFree86$ */ /* $XdotOrg: driver/xf86-video-sis/src/sis310_accel.c,v 1.31 2006-03-09 06:06:25 anholt Exp $ */ /* * 2D Acceleration for SiS 315, 330 and 340 series * * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1) Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3) The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * Author: Thomas Winischhofer * * 2003/08/18: Rewritten for using VRAM command queue * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "sis.h" #define SIS_NEED_MYMMIO #define SIS_NEED_ACCELBUF #include "sis_regs.h" #include "sis310_accel.h" #if 0 #define ACCELDEBUG #endif #define FBOFFSET (pSiS->dhmOffset) #define DEV_HEIGHT 0xfff /* "Device height of destination bitmap" */ #undef SIS_NEED_ARRAY /* For XAA */ #ifdef SIS_USE_XAA #undef TRAP /* Use/Don't use Trapezoid Fills * DOES NOT WORK. XAA sometimes provides illegal * trapezoid data (left and right edges cross each * other) which causes drawing errors. Since * checking the trapezoid for such a case is very * time-intensive, it is faster to let it be done * by the generic polygon functions. * Does not work on 330 series at all, hangs the engine. * Even with correct trapezoids, this is slower than * doing it by the CPU. */ #undef CTSCE /* Use/Don't use CPUToScreenColorExpand. Disabled * because it is slower than doing it by the CPU. * Indirect mode does not work in VRAM queue mode. * Does not work on 330 series (even in MMIO mode). */ #undef CTSCE_DIRECT /* Use direct method - This works (on both 315 and 330 at * least in VRAM queue mode) but we don't use this either, * because it's slower than doing it by the CPU. (Using it * would require defining CTSCE) */ #undef STSCE /* Use/Don't use ScreenToScreenColorExpand - does not work, * see comments below. */ #define INCL_RENDER /* Use/Don't use RENDER extension acceleration */ #ifdef INCL_RENDER # ifdef RENDER # include "mipict.h" # include "dixstruct.h" # define SIS_NEED_ARRAY # undef SISNEWRENDER # ifdef XORG_VERSION_CURRENT # if XORG_VERSION_CURRENT > XORG_VERSION_NUMERIC(6,7,0,0,0) # define SISNEWRENDER # endif # endif # endif #endif #endif /* XAA */ /* For EXA */ #ifdef SIS_USE_EXA #if 0 #define SIS_HAVE_COMPOSITE /* Have our own EXA composite */ #endif #ifdef SIS_HAVE_COMPOSITE #ifndef SIS_NEED_ARRAY #define SIS_NEED_ARRAY #endif #endif #endif #ifdef SIS_USE_XAA /* XAA */ #ifdef INCL_RENDER #ifdef RENDER static CARD32 SiSAlphaTextureFormats[2] = { PICT_a8 , 0 }; static CARD32 SiSTextureFormats[2] = { PICT_a8r8g8b8, 0 }; #ifdef SISNEWRENDER static CARD32 SiSDstTextureFormats16[2] = { PICT_r5g6b5 , 0 }; static CARD32 SiSDstTextureFormats32[3] = { PICT_x8r8g8b8, PICT_a8r8g8b8, 0 }; #endif #endif /* RENDER */ #endif /* INCL_RENDER */ #endif /* XAA */ #ifdef SIS_USE_EXA /* EXA */ void SiSScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area); Bool SiSUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch); Bool SiSUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst); Bool SiSDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch); #endif /* EXA */ #ifdef INCL_YUV_BLIT_ADAPTOR void SISWriteBlitPacket(SISPtr pSiS, CARD32 *packet); #endif extern unsigned char SiSGetCopyROP(int rop); extern unsigned char SiSGetPatternROP(int rop); CARD32 dummybuf; #ifdef SIS_NEED_ARRAY #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,0,0,0) #define SiSRenderOpsMAX 0x2b #else #define SiSRenderOpsMAX 0x0f #endif static const CARD8 SiSRenderOps[] = { /* PictOpXXX 1 = supported, 0 = unsupported */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #endif /* NEED ARRAY */ #ifdef SIS_NEED_ARRAY static void SiSCalcRenderAccelArray(ScrnInfoPtr pScrn) { SISPtr pSiS = SISPTR(pScrn); #ifdef SISDUALHEAD SISEntPtr pSiSEnt = pSiS->entityPrivate;; #endif if(((pScrn->bitsPerPixel == 16) || (pScrn->bitsPerPixel == 32)) && pSiS->doRender) { int i, j; #ifdef SISDUALHEAD if(pSiSEnt) pSiS->RenderAccelArray = pSiSEnt->RenderAccelArray; #endif if(!pSiS->RenderAccelArray) { if((pSiS->RenderAccelArray = xnfcalloc(65536, 1))) { #ifdef SISDUALHEAD if(pSiSEnt) pSiSEnt->RenderAccelArray = pSiS->RenderAccelArray; #endif for(i = 0; i < 256; i++) { for(j = 0; j < 256; j++) { pSiS->RenderAccelArray[(i << 8) + j] = (i * j) / 255; } } } } } } #endif #ifdef SIS_USE_EXA void SiSScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area) { SISPtr pSiS = SISPTR(xf86Screens[pScreen->myNum]); pSiS->exa_scratch = NULL; } #endif static void SiSSync(ScrnInfoPtr pScrn) { SISPtr pSiS = SISPTR(pScrn); #ifdef SIS_USE_XAA if(!pSiS->useEXA) { #ifdef CTSCE #ifdef CTSCE_DIRECT if(pSiS->DoColorExpand) { SiSDoCMD pSiS->ColorExpandBusy = TRUE; } #endif #endif pSiS->DoColorExpand = FALSE; } #endif pSiS->alphaBlitBusy = FALSE; SiSIdle } static void SiSSyncAccel(ScrnInfoPtr pScrn) { SISPtr pSiS = SISPTR(pScrn); if(!pSiS->NoAccel) SiSSync(pScrn); } static void SiSInitializeAccelerator(ScrnInfoPtr pScrn) { SISPtr pSiS = SISPTR(pScrn); #ifdef SIS_USE_XAA pSiS->DoColorExpand = FALSE; #endif pSiS->alphaBlitBusy = FALSE; if(!pSiS->NoAccel) { #ifndef SISVRAMQ if(pSiS->ChipFlags & SiSCF_Integrated) { CmdQueLen = 0; } else { CmdQueLen = ((128 * 1024) / 4) - 64; } #endif #ifdef SISVRAMQ if(pSiS->ChipType == XGI_40) { SiSSync(pScrn); SiSDualPipe(1); /* 1 = disable, 0 = enable */ SiSSync(pScrn); } #endif } } static void SiSSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, unsigned int planemask, int trans_color) { SISPtr pSiS = SISPTR(pScrn); #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); SiSCheckQueue(16 * 2); SiSSetupSRCPitchDSTRect(pSiS->scrnOffset, pSiS->scrnOffset, DEV_HEIGHT) #else SiSSetupDSTColorDepth(pSiS->DstColor); SiSSetupSRCPitch(pSiS->scrnOffset) SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) #endif if(trans_color != -1) { SiSSetupROP(0x0A) SiSSetupSRCTrans(trans_color) SiSSetupCMDFlag(TRANSPARENT_BITBLT) } else { SiSSetupROP(SiSGetCopyROP(rop)) /* Set command - not needed, both 0 */ /* SiSSetupCMDFlag(BITBLT | SRCVIDEO) */ } #ifndef SISVRAMQ SiSSetupCMDFlag(pSiS->SiS310_AccelDepth) #endif #ifdef SISVRAMQ SiSSyncWP #endif /* The chip is smart enough to know the direction */ } static void SiSSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int src_x, int src_y, int dst_x, int dst_y, int width, int height) { SISPtr pSiS = SISPTR(pScrn); CARD32 srcbase, dstbase; int mymin, mymax; srcbase = dstbase = 0; mymin = min(src_y, dst_y); mymax = max(src_y, dst_y); /* Libxaa.a has a bug: The tilecache cannot operate * correctly if there are 512x512 slots, but no 256x256 * slots. This leads to catastrophic data fed to us. * Filter this out here and warn the user. * Fixed in 4.3.99.10 (?) and Debian's 4.3.0.1 */ #if (XF86_VERSION_CURRENT < XF86_VERSION_NUMERIC(4,3,99,10,0)) && (XF86_VERSION_CURRENT != XF86_VERSION_NUMERIC(4,3,0,1,0)) if((src_x < 0) || (dst_x < 0) || (src_y < 0) || (dst_y < 0) || (width <= 0) || (height <= 0)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "BitBlit fatal error: Illegal coordinates:\n"); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Source x %d y %d, dest x %d y %d, width %d height %d\n", src_x, src_y, dst_x, dst_y, width, height); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "This is very probably caused by a known bug in libxaa.a.\n"); xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Please update libxaa.a to avoid this error.\n"); return; } #endif /* Although the chip knows the direction to use * if the source and destination areas overlap, * that logic fails if we fiddle with the bitmap * addresses. Therefore, we check if the source * and destination blitting areas overlap and * adapt the bitmap addresses synchronously * if the coordinates exceed the valid range. * The the areas do not overlap, we do our * normal check. */ if((mymax - mymin) < height) { if((src_y >= 2048) || (dst_y >= 2048)) { srcbase = pSiS->scrnOffset * mymin; dstbase = pSiS->scrnOffset * mymin; src_y -= mymin; dst_y -= mymin; } } else { if(src_y >= 2048) { srcbase = pSiS->scrnOffset * src_y; src_y = 0; } if((dst_y >= pScrn->virtualY) || (dst_y >= 2048)) { dstbase = pSiS->scrnOffset * dst_y; dst_y = 0; } } srcbase += FBOFFSET; dstbase += FBOFFSET; #ifdef SISVRAMQ SiSCheckQueue(16 * 3); SiSSetupSRCDSTBase(srcbase, dstbase) SiSSetupSRCDSTXY(src_x, src_y, dst_x, dst_y) SiSSetRectDoCMD(width,height) #else SiSSetupSRCBase(srcbase); SiSSetupDSTBase(dstbase); SiSSetupRect(width, height) SiSSetupSRCXY(src_x, src_y) SiSSetupDSTXY(dst_x, dst_y) SiSDoCMD #endif } static void SiSSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask) { SISPtr pSiS = SISPTR(pScrn); if(pSiS->disablecolorkeycurrent) { if((CARD32)color == pSiS->colorKey) { rop = 5; /* NOOP */ } } #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); SiSCheckQueue(16 * 1); SiSSetupPATFGDSTRect(color, pSiS->scrnOffset, DEV_HEIGHT) SiSSetupROP(SiSGetPatternROP(rop)) SiSSetupCMDFlag(PATFG) SiSSyncWP #else SiSSetupPATFG(color) SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) SiSSetupDSTColorDepth(pSiS->DstColor); SiSSetupROP(SiSGetPatternROP(rop)) SiSSetupCMDFlag(PATFG | pSiS->SiS310_AccelDepth) #endif } static void SiSSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) { SISPtr pSiS = SISPTR(pScrn); CARD32 dstbase = 0; if(y >= 2048) { dstbase = pSiS->scrnOffset * y; y = 0; } dstbase += FBOFFSET; pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | T_L_X_INC | T_L_Y_INC | T_R_X_INC | T_R_Y_INC | TRAPAZOID_FILL); /* SiSSetupCMDFlag(BITBLT) - BITBLT = 0 */ #ifdef SISVRAMQ SiSCheckQueue(16 * 2) SiSSetupDSTXYRect(x, y, w, h) SiSSetupDSTBaseDoCMD(dstbase) #else SiSSetupDSTBase(dstbase) SiSSetupDSTXY(x, y) SiSSetupRect(w, h) SiSDoCMD #endif } #ifdef SIS_USE_XAA /* ---------------------------- XAA -------------------------- */ /* Trapezoid */ /* This would work better if XAA would provide us with valid trapezoids. * In fact, with small trapezoids the left and the right edge often cross * each other which causes drawing errors (filling over whole scanline). * DOES NOT WORK ON 330 SERIES, HANGS THE ENGINE. */ #ifdef TRAP static void SiSSubsequentSolidFillTrap(ScrnInfoPtr pScrn, int y, int h, int left, int dxL, int dyL, int eL, int right, int dxR, int dyR, int eR ) { SISPtr pSiS = SISPTR(pScrn); CARD32 dstbase = 0; if(y >= 2048) { dstbase = pSiS->scrnOffset * y; y = 0; } dstbase += FBOFFSET; #ifdef SISVRAMQ /* Not optimized yet */ SiSCheckQueue(16 * 10) #else SiSSetupDSTBase(dstbase) #endif #if 1 SiSSetupPATFG(0xff0000) /* FOR TESTING */ #endif /* Clear CommandReg because SetUp can be used for Rect and Trap */ pSiS->CommandReg &= ~(T_L_X_INC | T_L_Y_INC | T_R_X_INC | T_R_Y_INC | T_XISMAJORL | T_XISMAJORR | BITBLT); xf86DrvMsg(0, X_INFO, "Trap (%d %d %d %d) dxL %d dyL %d eL %d dxR %d dyR %d eR %d\n", left, right, y, h, dxL, dyL, eL, dxR, dyR, eR); /* Determine egde angles */ if(dxL < 0) { dxL = -dxL; } else { SiSSetupCMDFlag(T_L_X_INC) } if(dxR < 0) { dxR = -dxR; } else { SiSSetupCMDFlag(T_R_X_INC) } /* (Y direction always positive - do this anyway) */ if(dyL < 0) { dyL = -dyL; } else { SiSSetupCMDFlag(T_L_Y_INC) } if(dyR < 0) { dyR = -dyR; } else { SiSSetupCMDFlag(T_R_Y_INC) } /* Determine major axis */ if(dxL >= dyL) { SiSSetupCMDFlag(T_XISMAJORL) } if(dxR >= dyR) { SiSSetupCMDFlag(T_XISMAJORR) } SiSSetupCMDFlag(TRAPAZOID_FILL); #ifdef SISVRAMQ SiSSetupYHLR(y, h, left, right) SiSSetupdLdR(dxL, dyL, dxR, dyR) SiSSetupELER(eL, eR) SiSSetupDSTBaseDoCMD(dstbase) #else /* Set up deltas */ SiSSetupdL(dxL, dyL) SiSSetupdR(dxR, dyR) /* Set up y, h, left, right */ SiSSetupYH(y, h) SiSSetupLR(left, right) /* Set up initial error term */ SiSSetupEL(eL) SiSSetupER(eR) SiSDoCMD #endif } #endif static void SiSSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask) { SISPtr pSiS = SISPTR(pScrn); #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); SiSCheckQueue(16 * 3); SiSSetupLineCountPeriod(1, 1) SiSSetupPATFGDSTRect(color, pSiS->scrnOffset, DEV_HEIGHT) SiSSetupROP(SiSGetPatternROP(rop)) SiSSetupCMDFlag(PATFG | LINE) SiSSyncWP #else SiSSetupLineCount(1) SiSSetupPATFG(color) SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) SiSSetupDSTColorDepth(pSiS->DstColor) SiSSetupROP(SiSGetPatternROP(rop)) SiSSetupCMDFlag(PATFG | LINE | pSiS->SiS310_AccelDepth) #endif } static void SiSSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int flags) { SISPtr pSiS = SISPTR(pScrn); int miny, maxy; CARD32 dstbase = 0; miny = (y1 > y2) ? y2 : y1; maxy = (y1 > y2) ? y1 : y2; if(maxy >= 2048) { dstbase = pSiS->scrnOffset*miny; y1 -= miny; y2 -= miny; } dstbase += FBOFFSET; if(flags & OMIT_LAST) { SiSSetupCMDFlag(NO_LAST_PIXEL) } else { pSiS->CommandReg &= ~(NO_LAST_PIXEL); } #ifdef SISVRAMQ SiSCheckQueue(16 * 2); SiSSetupX0Y0X1Y1(x1, y1, x2, y2) SiSSetupDSTBaseDoCMD(dstbase) #else SiSSetupDSTBase(dstbase) SiSSetupX0Y0(x1, y1) SiSSetupX1Y1(x2, y2) SiSDoCMD #endif } static void SiSSubsequentSolidHorzVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir) { SISPtr pSiS = SISPTR(pScrn); CARD32 dstbase = 0; len--; /* starting point is included! */ if((y >= 2048) || ((y + len) >= 2048)) { dstbase = pSiS->scrnOffset * y; y = 0; } dstbase += FBOFFSET; #ifdef SISVRAMQ SiSCheckQueue(16 * 2); if(dir == DEGREES_0) { SiSSetupX0Y0X1Y1(x, y, (x + len), y) } else { SiSSetupX0Y0X1Y1(x, y, x, (y + len)) } SiSSetupDSTBaseDoCMD(dstbase) #else SiSSetupDSTBase(dstbase) SiSSetupX0Y0(x,y) if(dir == DEGREES_0) { SiSSetupX1Y1(x + len, y); } else { SiSSetupX1Y1(x, y + len); } SiSDoCMD #endif } static void SiSSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask, int length, unsigned char *pattern) { SISPtr pSiS = SISPTR(pScrn); #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); SiSCheckQueue(16 * 3); SiSSetupLineCountPeriod(1, (length - 1)) SiSSetupStyle(*pattern,*(pattern + 4)) SiSSetupPATFGDSTRect(fg, pSiS->scrnOffset, DEV_HEIGHT) #else SiSSetupLineCount(1) SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) SiSSetupDSTColorDepth(pSiS->DstColor); SiSSetupStyleLow(*pattern) SiSSetupStyleHigh(*(pattern + 4)) SiSSetupStylePeriod(length - 1); SiSSetupPATFG(fg) #endif SiSSetupROP(SiSGetPatternROP(rop)) SiSSetupCMDFlag(LINE | LINE_STYLE) if(bg != -1) { SiSSetupPATBG(bg) } else { SiSSetupCMDFlag(TRANSPARENT) } #ifndef SISVRAMQ SiSSetupCMDFlag(pSiS->SiS310_AccelDepth) #endif #ifdef SISVRAMQ SiSSyncWP #endif } static void SiSSubsequentDashedTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int flags, int phase) { SISPtr pSiS = SISPTR(pScrn); CARD32 dstbase, miny, maxy; dstbase = 0; miny = (y1 > y2) ? y2 : y1; maxy = (y1 > y2) ? y1 : y2; if(maxy >= 2048) { dstbase = pSiS->scrnOffset * miny; y1 -= miny; y2 -= miny; } dstbase += FBOFFSET; if(flags & OMIT_LAST) { SiSSetupCMDFlag(NO_LAST_PIXEL) } else { pSiS->CommandReg &= ~(NO_LAST_PIXEL); } #ifdef SISVRAMQ SiSCheckQueue(16 * 2); SiSSetupX0Y0X1Y1(x1, y1, x2, y2) SiSSetupDSTBaseDoCMD(dstbase) #else SiSSetupDSTBase(dstbase) SiSSetupX0Y0(x1, y1) SiSSetupX1Y1(x2, y2) SiSDoCMD #endif } static void SiSSetupForMonoPatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg, int bg, int rop, unsigned int planemask) { SISPtr pSiS = SISPTR(pScrn); #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); SiSCheckQueue(16 * 3); SiSSetupPATFGDSTRect(fg, pSiS->scrnOffset, DEV_HEIGHT) #else SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) SiSSetupDSTColorDepth(pSiS->DstColor); #endif SiSSetupMONOPAT(patx,paty) SiSSetupROP(SiSGetPatternROP(rop)) #ifdef SISVRAMQ SiSSetupCMDFlag(PATMONO) #else SiSSetupPATFG(fg) SiSSetupCMDFlag(PATMONO | pSiS->SiS310_AccelDepth) #endif if(bg != -1) { SiSSetupPATBG(bg) } else { SiSSetupCMDFlag(TRANSPARENT) } #ifdef SISVRAMQ SiSSyncWP #endif } static void SiSSubsequentMonoPatternFill(ScrnInfoPtr pScrn, int patx, int paty, int x, int y, int w, int h) { SISPtr pSiS = SISPTR(pScrn); CARD32 dstbase = 0; if(y >= 2048) { dstbase = pSiS->scrnOffset * y; y = 0; } dstbase += FBOFFSET; /* Clear commandReg because Setup can be used for Rect and Trap */ pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | T_L_X_INC | T_L_Y_INC | T_R_X_INC | T_R_Y_INC | TRAPAZOID_FILL); #ifdef SISVRAMQ SiSCheckQueue(16 * 2); SiSSetupDSTXYRect(x,y,w,h) SiSSetupDSTBaseDoCMD(dstbase) #else SiSSetupDSTBase(dstbase) SiSSetupDSTXY(x,y) SiSSetupRect(w,h) SiSDoCMD #endif } /* --- Trapezoid --- */ /* Does not work at all on 330 series */ #ifdef TRAP static void SiSSubsequentMonoPatternFillTrap(ScrnInfoPtr pScrn, int patx, int paty, int y, int h, int left, int dxL, int dyL, int eL, int right, int dxR, int dyR, int eR) { SISPtr pSiS = SISPTR(pScrn); CARD32 dstbase = 0; if(y >= 2048) { dstbase=pSiS->scrnOffset*y; y = 0; } dstbase += FBOFFSET; #ifdef SISVRAMQ SiSCheckQueue(16 * 4); #else SiSSetupDSTBase(dstbase) #endif /* Clear CommandReg because SetUp can be used for Rect and Trap */ pSiS->CommandReg &= ~(T_XISMAJORL | T_XISMAJORR | T_L_X_INC | T_L_Y_INC | T_R_X_INC | T_R_Y_INC | BITBLT); if(dxL < 0) { dxL = -dxL; } else { SiSSetupCMDFlag(T_L_X_INC) } if(dxR < 0) { dxR = -dxR; } else { SiSSetupCMDFlag(T_R_X_INC) } if(dyL < 0) { dyL = -dyL; } else { SiSSetupCMDFlag(T_L_Y_INC) } if(dyR < 0) { dyR = -dyR; } else { SiSSetupCMDFlag(T_R_Y_INC) } /* Determine major axis */ if(dxL >= dyL) { SiSSetupCMDFlag(T_XISMAJORL) } if(dxR >= dyR) { SiSSetupCMDFlag(T_XISMAJORR) } SiSSetupCMDFlag(TRAPAZOID_FILL); #ifdef SISVRAMQ SiSSetupYHLR(y, h, left, right) SiSSetupdLdR(dxL, dyL, dxR, dyR) SiSSetupELER(eL, eR) SiSSetupDSTBaseDoCMD(dstbase) #else SiSSetupYH(y, h) SiSSetupLR(left, right) SiSSetupdL(dxL, dyL) SiSSetupdR(dxR, dyR) SiSSetupEL(eL) SiSSetupER(eR) SiSDoCMD #endif } #endif /* Color 8x8 pattern */ #ifdef SISVRAMQ static void SiSSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, int rop, unsigned int planemask, int trans_col) { SISPtr pSiS = SISPTR(pScrn); int j = pScrn->bitsPerPixel >> 3; CARD32 *patadr = (CARD32 *)(pSiS->FbBase + (patterny * pSiS->scrnOffset) + (patternx * j)); SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); SiSCheckQueue(16 * 3); SiSSetupDSTRectBurstHeader(pSiS->scrnOffset, DEV_HEIGHT, PATTERN_REG, (pScrn->bitsPerPixel << 1)) while(j--) { SiSSetupPatternRegBurst(patadr[0], patadr[1], patadr[2], patadr[3]); SiSSetupPatternRegBurst(patadr[4], patadr[5], patadr[6], patadr[7]); SiSSetupPatternRegBurst(patadr[8], patadr[9], patadr[10], patadr[11]); SiSSetupPatternRegBurst(patadr[12], patadr[13], patadr[14], patadr[15]); patadr += 16; /* = 64 due to (CARD32 *) */ } SiSSetupROP(SiSGetPatternROP(rop)) SiSSetupCMDFlag(PATPATREG) SiSSyncWP } static void SiSSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patternx, int patterny, int x, int y, int w, int h) { SISPtr pSiS = SISPTR(pScrn); CARD32 dstbase = 0; if(y >= 2048) { dstbase = pSiS->scrnOffset * y; y = 0; } dstbase += FBOFFSET; /* SiSSetupCMDFlag(BITBLT) - BITBLT = 0 */ SiSCheckQueue(16 * 2) SiSSetupDSTXYRect(x, y, w, h) SiSSetupDSTBaseDoCMD(dstbase) } #endif /* ---- CPUToScreen Color Expand --- */ #ifdef CTSCE #ifdef CTSCE_DIRECT /* Direct method */ /* This is somewhat a fake. We let XAA copy its data not to an * aperture, but to video RAM, and then do a ScreenToScreen * color expansion. * Since the data is sent AFTER the call to Subsequent, we * don't execute the command here, but set a flag and do * that in the (subsequent) call to Sync() */ static void SiSSetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask) { SISPtr pSiS=SISPTR(pScrn); #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); SiSSetupROP(SiSGetCopyROP(rop)); SiSSetupSRCFGDSTRect(fg, pSiS->scrnOffset, DEV_HEIGHT) if(bg == -1) { SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | SRCVIDEO); } else { SiSSetupSRCBG(bg); SiSSetupCMDFlag(ENCOLOREXP | SRCVIDEO); } SiSSyncWP #else SiSSetupSRCXY(0,0); SiSSetupROP(SiSGetCopyROP(rop)); SiSSetupSRCFG(fg); SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT); SiSSetupDSTColorDepth(pSiS->DstColor); if(bg == -1) { SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | SRCVIDEO | pSiS->SiS310_AccelDepth); } else { SiSSetupSRCBG(bg); SiSSetupCMDFlag(ENCOLOREXP | SRCVIDEO | pSiS->SiS310_AccelDepth); } #endif } static void SiSSubsequentCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft) { SISPtr pSiS = SISPTR(pScrn); int _x0, _y0, _x1, _y1; CARD32 srcbase, dstbase; srcbase = pSiS->ColorExpandBase; dstbase = 0; if(y >= 2048) { dstbase = pSiS->scrnOffset*y; y = 0; } srcbase += FBOFFSET; dstbase += FBOFFSET; #ifdef SISVRAMQ SiSSetupSRCDSTBase(srcbase,dstbase); #else SiSSetupSRCBase(srcbase); SiSSetupDSTBase(dstbase) #endif if(skipleft > 0) { _x0 = x + skipleft; _y0 = y; _x1 = x + w; _y1 = y + h; #ifdef SISVRAMQ SiSSetupClip(_x0, _y0, _x1, _y1); #else SiSSetupClipLT(_x0, _y0); SiSSetupClipRB(_x1, _y1); #endif SiSSetupCMDFlag(CLIPENABLE); } else { pSiS->CommandReg &= (~CLIPENABLE); } #ifdef SISVRAMQ SiSSetupRectSRCPitch(w, h, ((((w + 7) >> 3) + 3) >> 2) << 2); SiSSetupSRCDSTXY(0, 0, x, y); #else SiSSetupRect(w, h); SiSSetupSRCPitch(((((w+7)/8)+3) >> 2) * 4); SiSSetupDSTXY(x, y); #endif if(pSiS->ColorExpandBusy) { pSiS->ColorExpandBusy = FALSE; SiSIdle } pSiS->DoColorExpand = TRUE; } #else /* Indirect method */ /* This is SLOW, slower than the CPU on most chipsets */ /* Does not work in VRAM queue mode. */ static void SiSSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask) { SISPtr pSiS=SISPTR(pScrn); #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); #endif /* !!! DOES NOT WORK IN VRAM QUEUE MODE !!! */ /* (hence this is not optimized for VRAM mode) */ #ifndef SISVRAMQ SiSIdle #endif SiSSetupSRCXY(0,0); SiSSetupROP(SiSGetCopyROP(rop)); SiSSetupSRCFG(fg); SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT); #ifndef SISVRAMQ SiSSetupDSTColorDepth(pSiS->DstColor); #endif if(bg == -1) { #ifdef SISVRAMQ SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | SRCVIDEO); #else SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | SRCCPUBLITBUF | pSiS->SiS310_AccelDepth); #endif } else { SiSSetupSRCBG(bg); #ifdef SISVRAMQ SiSSetupCMDFlag(ENCOLOREXP | SRCCPUBLITBUF); #else SiSSetupCMDFlag(ENCOLOREXP | SRCCPUBLITBUF | pSiS->SiS310_AccelDepth); #endif }; } static void SiSSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft) { SISPtr pSiS = SISPTR(pScrn); int _x0, _y0, _x1, _y1; CARD32 dstbase = 0; if(y >= 2048) { dstbase = pSiS->scrnOffset*y; y = 0; } dstbase += FBOFFSET; #ifndef SISVRAMQ if((SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { SiSIdle; } #endif SiSSetupDSTBase(dstbase) if(skipleft > 0) { _x0 = x+skipleft; _y0 = y; _x1 = x+w; _y1 = y+h; #ifdef SISVRAMQ SiSSetupClip(_x0, _y0, _x1, _y1); #else SiSSetupClipLT(_x0, _y0); SiSSetupClipRB(_x1, _y1); #endif SiSSetupCMDFlag(CLIPENABLE); } else { pSiS->CommandReg &= (~CLIPENABLE); } SiSSetupRect(w, 1); SiSSetupSRCPitch(((((w+7)/8)+3) >> 2) * 4); pSiS->ycurrent = y; pSiS->xcurrent = x; } static void SiSSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) { SISPtr pSiS = SISPTR(pScrn); CARD32 cbo; cbo = pSiS->ColorExpandBufferScreenOffset[bufno]; cbo += FBOFFSET; #ifndef SISVRAMQ if((SIS_MMIO_IN16(pSiS->IOBase, Q_STATUS+2) & 0x8000) != 0x8000) { SiSIdle; } #endif SiSSetupSRCBase(cbo); SiSSetupDSTXY(pSiS->xcurrent, pSiS->ycurrent); SiSDoCMD pSiS->ycurrent++; #ifndef SISVRAMQ SiSIdle #endif } #endif #endif /* --- Screen To Screen Color Expand --- */ /* This method blits in a single task; this does not work because * the hardware does not use the source pitch as scanline offset * but to calculate pattern address from source X and Y and to * limit the drawing width (similar to width set by SetupRect). * XAA provides the pattern bitmap with scrnOffset (displayWidth * bpp/8) * offset, but this is not supported by the hardware. * DOES NOT WORK ON 330 SERIES, HANGS ENGINE. */ #ifdef STSCE static void SiSSetupForScreenToScreenColorExpand(ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask) { SISPtr pSiS = SISPTR(pScrn); #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); #else SiSSetupDSTColorDepth(pSiS->DstColor) #endif SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) SiSSetupROP(SiSGetCopyROP(rop)) SiSSetupSRCFG(fg) /* SiSSetupSRCXY(0,0) */ if(bg == -1) { SiSSetupCMDFlag(TRANSPARENT | ENCOLOREXP | SRCVIDEO); } else { SiSSetupSRCBG(bg); SiSSetupCMDFlag(ENCOLOREXP | SRCVIDEO); }; #ifdef SISVRAMQ SiSSyncWP #endif } /* For testing, these are the methods: (use only one at a time!) */ #undef npitch /* Normal: Use srcx/y as srcx/y, use scrnOffset as source pitch * Does not work on 315 series, because the hardware does not * regard the src x and y. Apart from this problem: * This would work if the hareware used the source pitch for * incrementing the source address after each scanline - but * it doesn't do this! The first line of the area is correctly * color expanded, but since the source pitch is ignored and * the source address not incremented correctly, the following * lines are color expanded with any bit pattern that is left * in the unused space of the source bitmap (which is organized * with the depth of the screen framebuffer hence with a pitch * of scrnOffset). */ #undef pitchdw /* Use source pitch "displayWidth / 8" instead * of scrnOffset (=displayWidth * bpp / 8) * This can't work, because the pitch of the source * bitmap is scrnoffset! */ #define nopitch /* Calculate srcbase with srcx and srcy, set the * pitch to scrnOffset (which IS the correct pitch * for the source bitmap) and set srcx and srcy both * to 0. * This would work if the hareware used the source pitch for * incrementing the source address after each scanline - but * it doesn't do this! Again: The first line of the area is * correctly color expanded, but since the source pitch is * ignored for scanline address incremention, the following * lines are not correctly color expanded. * This is the only way it works (apart from the problem * described above). The hardware does not regard the src * x and y values in any way. */ static void SiSSubsequentScreenToScreenColorExpand(ScrnInfoPtr pScrn, int x, int y, int w, int h, int srcx, int srcy, int skipleft) { SISPtr pSiS = SISPTR(pScrn); CARD32 srcbase, dstbase; #if 0 int _x0, _y0, _x1, _y1; #endif #ifdef pitchdw int newsrcx, newsrcy; /* srcx and srcy are provided based on a scrnOffset pitch ( = displayWidth * bpp / 8 ) * We recalulate srcx and srcy based on pitch = displayWidth / 8 */ newsrcy = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) / (pScrn->displayWidth/8); newsrcx = ((pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8))) % (pScrn->displayWidth/8); #endif xf86DrvMsg(0, X_INFO, "Sub ScreenToScreen ColorExp(%d,%d, %d,%d, %d,%d, %d)\n", x, y, w, h, srcx, srcy, skipleft); srcbase = dstbase = 0; #ifdef pitchdw if(newsrcy >= 2048) { srcbase = (pScrn->displayWidth / 8) * newsrcy; newsrcy = 0; } #endif #ifdef nopitch srcbase = (pSiS->scrnOffset * srcy) + (srcx * ((pScrn->bitsPerPixel+7)/8)); #endif #ifdef npitch if(srcy >= 2048) { srcbase = pSiS->scrnOffset * srcy; srcy = 0; } #endif if(y >= 2048) { dstbase = pSiS->scrnOffset * y; y = 0; } srcbase += FBOFFSET; dstbase += FBOFFSET; SiSSetupSRCBase(srcbase) SiSSetupDSTBase(dstbase) /* 315 series seem to treat the src pitch as * a "drawing limit", but still (as 300 series) * does not use it for incrementing the * address pointer for the next scanline. ARGH! */ #ifdef pitchdw SiSSetupSRCPitch(pScrn->displayWidth/8) #endif #ifdef nopitch SiSSetupSRCPitch(pScrn->displayWidth/8) /* SiSSetupSRCPitch(1024/8) */ /* For test */ #endif #ifdef npitch SiSSetupSRCPitch(pScrn->displayWidth/8) /* SiSSetupSRCPitch(pSiS->scrnOffset) */ #endif SiSSetupRect(w,h) #if 0 /* How do I implement the offset? Not this way, that's for sure.. */ if (skipleft > 0) { _x0 = x+skipleft; _y0 = y; _x1 = x+w; _y1 = y+h; SiSSetupClipLT(_x0, _y0); SiSSetupClipRB(_x1, _y1); SiSSetupCMDFlag(CLIPENABLE); } #endif #ifdef pitchdw SiSSetupSRCXY(newsrcx, newsrcy) #endif #ifdef nopitch SiSSetupSRCXY(0,0) #endif #ifdef npitch SiSSetupSRCXY(srcx, srcy) #endif SiSSetupDSTXY(x,y) SiSDoCMD #ifdef SISVRAMQ /* We MUST sync here, there must not be 2 or more color expansion commands in the queue */ SiSIdle #endif } #endif #ifdef SISDUALHEAD static void SiSRestoreAccelState(ScrnInfoPtr pScrn) { SISPtr pSiS = SISPTR(pScrn); pSiS->ColorExpandBusy = FALSE; pSiS->alphaBlitBusy = FALSE; SiSIdle } #endif /* ---- RENDER ---- */ #ifdef INCL_RENDER #ifdef RENDER static void SiSRenderCallback(ScrnInfoPtr pScrn) { SISPtr pSiS = SISPTR(pScrn); if((currentTime.milliseconds > pSiS->RenderTime) && pSiS->AccelLinearScratch) { xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); pSiS->AccelLinearScratch = NULL; } if(!pSiS->AccelLinearScratch) { pSiS->RenderCallback = NULL; } } #define RENDER_DELAY 15000 static Bool SiSAllocateLinear(ScrnInfoPtr pScrn, int sizeNeeded) { SISPtr pSiS = SISPTR(pScrn); pSiS->RenderTime = currentTime.milliseconds + RENDER_DELAY; pSiS->RenderCallback = SiSRenderCallback; if(pSiS->AccelLinearScratch) { if(pSiS->AccelLinearScratch->size >= sizeNeeded) { return TRUE; } else { if(pSiS->alphaBlitBusy) { pSiS->alphaBlitBusy = FALSE; SiSIdle } if(xf86ResizeOffscreenLinear(pSiS->AccelLinearScratch, sizeNeeded)) { return TRUE; } xf86FreeOffscreenLinear(pSiS->AccelLinearScratch); pSiS->AccelLinearScratch = NULL; } } pSiS->AccelLinearScratch = xf86AllocateOffscreenLinear( pScrn->pScreen, sizeNeeded, 32, NULL, NULL, NULL); return(pSiS->AccelLinearScratch != NULL); } static Bool SiSSetupForCPUToScreenAlphaTexture(ScrnInfoPtr pScrn, int op, CARD16 red, CARD16 green, CARD16 blue, CARD16 alpha, #ifdef SISNEWRENDER CARD32 alphaType, CARD32 dstType, #else int alphaType, #endif CARD8 *alphaPtr, int alphaPitch, int width, int height, int flags) { SISPtr pSiS = SISPTR(pScrn); unsigned char *renderaccelarray; CARD32 *dstPtr; int x, pitch, sizeNeeded; int sbpp = pSiS->CurrentLayout.bitsPerPixel >> 3; int sbppshift = sbpp >> 1; /* 8->0, 16->1, 32->2 */ CARD8 myalpha; Bool docopy = TRUE; #ifdef ACCELDEBUG xf86DrvMsg(0, X_INFO, "AT(1): op %d t %x ARGB %x %x %x %x, w %d h %d pch %d\n", op, alphaType, /*dstType, */alpha, red, green, blue, width, height, alphaPitch); #endif if((width > 2048) || (height > 2048)) return FALSE; #ifdef SISVRAMQ if(op > SiSRenderOpsMAX) return FALSE; if(!SiSRenderOps[op]) return FALSE; #else if(op != PictOpOver) return FALSE; #endif if(!((renderaccelarray = pSiS->RenderAccelArray))) return FALSE; #ifdef ACCELDEBUG xf86DrvMsg(0, X_INFO, "AT(2): op %d t %x ARGB %x %x %x %x, w %d h %d pch %d\n", op, alphaType, alpha, red, green, blue, width, height, alphaPitch); #endif pitch = (width + 31) & ~31; sizeNeeded = (pitch << 2) * height; /* Source a8 (=8bit), expand to A8R8G8B8 (=32bit) */ if(!SiSAllocateLinear(pScrn, (sizeNeeded + sbpp - 1) >> sbppshift)) return FALSE; red &= 0xff00; green &= 0xff00; blue &= 0xff00; #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); switch(op) { case PictOpClear: #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,0,0,0) case PictOpDisjointClear: case PictOpConjointClear: #endif SiSSetupPATFGDSTRect(0, pSiS->scrnOffset, DEV_HEIGHT) /* SiSSetupROP(0x00) - is already 0 */ SiSSetupCMDFlag(PATFG) docopy = FALSE; break; case PictOpSrc: #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,0,0,0) case PictOpDisjointSrc: case PictOpConjointSrc: #endif SiSSetupSRCPitchDSTRect((pitch << 2), pSiS->scrnOffset, DEV_HEIGHT); SiSSetupAlpha(0xff) SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_NODESTALPHA) break; case PictOpDst: #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,0,0,0) case PictOpDisjointDst: case PictOpConjointDst: #endif SiSSetupSRCPitchDSTRect((pitch << 2), pSiS->scrnOffset, DEV_HEIGHT); SiSSetupAlpha(0x00) SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_CONSTANTALPHA) docopy = FALSE; break; case PictOpOver: SiSSetupSRCPitchDSTRect((pitch << 2), pSiS->scrnOffset, DEV_HEIGHT); SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_PERPIXELALPHA) break; } SiSSyncWP #else SiSSetupDSTColorDepth(pSiS->DstColor); SiSSetupSRCPitch((pitch << 2)); SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) SiSSetupROP(0) SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_PERPIXELALPHA | pSiS->SiS310_AccelDepth) #endif /* Don't need source for clear and dest */ if(!docopy) return TRUE; dstPtr = (CARD32*)(pSiS->FbBase + (pSiS->AccelLinearScratch->offset << sbppshift)); if(pSiS->alphaBlitBusy) { pSiS->alphaBlitBusy = FALSE; SiSIdle } if(alpha == 0xffff) { while(height--) { for(x = 0; x < width; x++) { myalpha = alphaPtr[x]; dstPtr[x] = (renderaccelarray[red + myalpha] << 16) | (renderaccelarray[green + myalpha] << 8) | renderaccelarray[blue + myalpha] | myalpha << 24; } dstPtr += pitch; alphaPtr += alphaPitch; } } else { alpha &= 0xff00; while(height--) { for(x = 0; x < width; x++) { myalpha = alphaPtr[x]; dstPtr[x] = (renderaccelarray[alpha + myalpha] << 24) | (renderaccelarray[red + myalpha] << 16) | (renderaccelarray[green + myalpha] << 8) | renderaccelarray[blue + myalpha]; } dstPtr += pitch; alphaPtr += alphaPitch; } } return TRUE; } static Bool SiSSetupForCPUToScreenTexture(ScrnInfoPtr pScrn, int op, #ifdef SISNEWRENDER CARD32 texType, CARD32 dstType, #else int texType, #endif CARD8 *texPtr, int texPitch, int width, int height, int flags) { SISPtr pSiS = SISPTR(pScrn); CARD8 *dst; int pitch, sizeNeeded; int sbpp = pSiS->CurrentLayout.bitsPerPixel >> 3; int sbppshift = sbpp >> 1; /* 8->0, 16->1, 32->2 */ int bppshift = PICT_FORMAT_BPP(texType) >> 4; /* 8->0, 16->1, 32->2 */ Bool docopy = TRUE; #ifdef ACCELDEBUG xf86DrvMsg(0, X_INFO, "T: type %x op %d w %d h %d T-pitch %d\n", texType, op, width, height, texPitch); #endif #ifdef SISVRAMQ if(op > SiSRenderOpsMAX) return FALSE; if(!SiSRenderOps[op]) return FALSE; #else if(op != PictOpOver) return FALSE; #endif if((width > 2048) || (height > 2048)) return FALSE; pitch = (width + 31) & ~31; sizeNeeded = (pitch << bppshift) * height; #ifdef ACCELDEBUG xf86DrvMsg(0, X_INFO, "T: %x op %x w %d h %d T-pitch %d size %d (%d %d %d)\n", texType, op, width, height, texPitch, sizeNeeded, sbpp, sbppshift, bppshift); #endif if(!SiSAllocateLinear(pScrn, (sizeNeeded + sbpp - 1) >> sbppshift)) return FALSE; width <<= bppshift; /* -> bytes (for engine and memcpy) */ pitch <<= bppshift; /* -> bytes */ #ifdef SISVRAMQ SiSSetupDSTColorDepth(pSiS->SiS310_AccelDepth); switch(op) { case PictOpClear: #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,0,0,0) case PictOpDisjointClear: case PictOpConjointClear: #endif SiSSetupPATFGDSTRect(0, pSiS->scrnOffset, DEV_HEIGHT) /* SiSSetupROP(0x00) - is already zero */ SiSSetupCMDFlag(PATFG) docopy = FALSE; break; case PictOpSrc: #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,0,0,0) case PictOpDisjointSrc: case PictOpConjointSrc: #endif SiSSetupSRCPitchDSTRect(pitch, pSiS->scrnOffset, DEV_HEIGHT); SiSSetupAlpha(0xff) SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_NODESTALPHA) break; case PictOpDst: #if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(4,2,0,0,0) case PictOpDisjointDst: case PictOpConjointDst: #endif SiSSetupSRCPitchDSTRect(pitch, pSiS->scrnOffset, DEV_HEIGHT); SiSSetupAlpha(0x00) SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_CONSTANTALPHA) docopy = FALSE; break; case PictOpOver: SiSSetupSRCPitchDSTRect(pitch, pSiS->scrnOffset, DEV_HEIGHT); SiSSetupAlpha(0x00) SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_PERPIXELALPHA) break; default: return FALSE; } SiSSyncWP #else SiSSetupDSTColorDepth(pSiS->DstColor); SiSSetupSRCPitch(pitch); SiSSetupDSTRect(pSiS->scrnOffset, DEV_HEIGHT) SiSSetupAlpha(0x00) SiSSetupCMDFlag(ALPHA_BLEND | SRCVIDEO | A_PERPIXELALPHA | pSiS->SiS310_AccelDepth) #endif /* Don't need source for clear and dest */ if(!docopy) return TRUE; dst = (CARD8*)(pSiS->FbBase + (pSiS->AccelLinearScratch->offset << sbppshift)); if(pSiS->alphaBlitBusy) { pSiS->alphaBlitBusy = FALSE; SiSIdle } while(height--) { memcpy(dst, texPtr, width); texPtr += texPitch; dst += pitch; } return TRUE; } static void SiSSubsequentCPUToScreenTexture(ScrnInfoPtr pScrn, int dst_x, int dst_y, int src_x, int src_y, int width, int height) { SISPtr pSiS = SISPTR(pScrn); CARD32 srcbase, dstbase; srcbase = pSiS->AccelLinearScratch->offset << 1; if(pScrn->bitsPerPixel == 32) srcbase <<= 1; #ifdef ACCELDEBUG xf86DrvMsg(0, X_INFO, "FIRE: scrbase %x dx %d dy %d w %d h %d\n", srcbase, dst_x, dst_y, width, height); #endif dstbase = 0; if((dst_y >= pScrn->virtualY) || (dst_y >= 2048)) { dstbase = pSiS->scrnOffset * dst_y; dst_y = 0; } srcbase += FBOFFSET; dstbase += FBOFFSET; #ifdef SISVRAMQ SiSCheckQueue(16 * 3) SiSSetupSRCDSTBase(srcbase,dstbase); SiSSetupSRCDSTXY(src_x, src_y, dst_x, dst_y) SiSSetRectDoCMD(width,height) #else SiSSetupSRCBase(srcbase); SiSSetupDSTBase(dstbase); SiSSetupRect(width, height) SiSSetupSRCXY(src_x, src_y) SiSSetupDSTXY(dst_x, dst_y) SiSDoCMD #endif pSiS->alphaBlitBusy = TRUE; } #endif #endif #endif /* XAA */ #ifdef SIS_USE_EXA /* ---------------------------- EXA -------------------------- */ static void SiSEXASync(ScreenPtr pScreen, int marker) { SISPtr pSiS = SISPTR(xf86Screens[pScreen->myNum]); SiSIdle } static Bool SiSPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); /* Planemask not supported */ if((planemask & ((1 << pPixmap->drawable.depth) - 1)) != (1 << pPixmap->drawable.depth) - 1) { return FALSE; } if((pPixmap->drawable.bitsPerPixel != 8) && (pPixmap->drawable.bitsPerPixel != 16) && (pPixmap->drawable.bitsPerPixel != 32)) return FALSE; if(pSiS->disablecolorkeycurrent) { if((CARD32)fg == pSiS->colorKey) { alu = 5; /* NOOP */ } } /* Check that the pitch matches the hardware's requirements. Should * never be a problem due to pixmapPitchAlign and fbScreenInit. */ if(exaGetPixmapPitch(pPixmap) & 3) return FALSE; SiSSetupDSTColorDepth((pPixmap->drawable.bitsPerPixel >> 4) << 16); SiSCheckQueue(16 * 1); SiSSetupPATFGDSTRect(fg, exaGetPixmapPitch(pPixmap), DEV_HEIGHT) SiSSetupROP(SiSGetPatternROP(alu)) SiSSetupCMDFlag(PATFG) SiSSyncWP pSiS->fillDstBase = (CARD32)exaGetPixmapOffset(pPixmap) + FBOFFSET; return TRUE; } static void SiSSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); /* SiSSetupCMDFlag(BITBLT) - BITBLT = 0 */ SiSCheckQueue(16 * 2) SiSSetupDSTXYRect(x1, y1, x2-x1, y2-y1) SiSSetupDSTBaseDoCMD(pSiS->fillDstBase) } static void SiSDoneSolid(PixmapPtr pPixmap) { } static Bool SiSPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, int ydir, int alu, Pixel planemask) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); CARD32 srcbase, dstbase; /* Planemask not supported */ if((planemask & ((1 << pSrcPixmap->drawable.depth) - 1)) != (1 << pSrcPixmap->drawable.depth) - 1) { return FALSE; } if((pDstPixmap->drawable.bitsPerPixel != 8) && (pDstPixmap->drawable.bitsPerPixel != 16) && (pDstPixmap->drawable.bitsPerPixel != 32)) return FALSE; /* Check that the pitch matches the hardware's requirements. Should * never be a problem due to pixmapPitchAlign and fbScreenInit. */ if(exaGetPixmapPitch(pSrcPixmap) & 3) return FALSE; if(exaGetPixmapPitch(pDstPixmap) & 3) return FALSE; srcbase = (CARD32)exaGetPixmapOffset(pSrcPixmap) + FBOFFSET; dstbase = (CARD32)exaGetPixmapOffset(pDstPixmap) + FBOFFSET; /* TODO: Will there eventually be overlapping blits? * If so, good night. Then we must calculate new base addresses * which are identical for source and dest, otherwise * the chips direction-logic will fail. Certainly funny * to re-calculate x and y then... */ SiSSetupDSTColorDepth((pDstPixmap->drawable.bitsPerPixel >> 4) << 16); SiSCheckQueue(16 * 3); SiSSetupSRCPitchDSTRect(exaGetPixmapPitch(pSrcPixmap), exaGetPixmapPitch(pDstPixmap), DEV_HEIGHT) SiSSetupROP(SiSGetCopyROP(alu)) SiSSetupSRCDSTBase(srcbase, dstbase) SiSSyncWP return TRUE; } static void SiSCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); SiSCheckQueue(16 * 2); SiSSetupSRCDSTXY(srcX, srcY, dstX, dstY) SiSSetRectDoCMD(width, height) } static void SiSDoneCopy(PixmapPtr pDstPixmap) { } #ifdef SIS_HAVE_COMPOSITE static Bool SiSCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) { ScrnInfoPtr pScrn = xf86Screens[pDstPicture->pDrawable->pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); xf86DrvMsg(0, 0, "CC: %d Src %x (fi %d ca %d) Msk %x (%d %d) Dst %x (%d %d)\n", op, pSrcPicture->format, pSrcPicture->filter, pSrcPicture->componentAlpha, pMaskPicture ? pMaskPicture->format : 0x2011, pMaskPicture ? pMaskPicture->filter : -1, pMaskPicture ? pMaskPicture->componentAlpha : -1, pDstPicture->format, pDstPicture->filter, pDstPicture->componentAlpha); if(pSrcPicture->transform || (pMaskPicture && pMaskPicture->transform) || pDstPicture->transform) { xf86DrvMsg(0, 0, "CC: src tr %p msk %p dst %p !!!!!!!!!!!!!!!\n", pSrcPicture->transform, pMaskPicture ? pMaskPicture->transform : 0, pDstPicture->transform); } return FALSE; } static Bool SiSPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) { #if 0 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); #endif return FALSE; } static void SiSComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int width, int height) { #if 0 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); #endif } static void SiSDoneComposite(PixmapPtr pDst) { } #endif Bool SiSUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src, int src_pitch) { ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); unsigned char *dst = pDst->devPrivate.ptr; int dst_pitch = exaGetPixmapPitch(pDst); (pSiS->SyncAccel)(pScrn); if(pDst->drawable.bitsPerPixel < 8) return FALSE; dst += (x * pDst->drawable.bitsPerPixel / 8) + (y * src_pitch); while(h--) { SiSMemCopyToVideoRam(pSiS, dst, (unsigned char *)src, (w * pDst->drawable.bitsPerPixel / 8)); src += src_pitch; dst += dst_pitch; } return TRUE; } Bool SiSUploadToScratch(PixmapPtr pSrc, PixmapPtr pDst) { ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); unsigned char *src, *dst; int src_pitch = exaGetPixmapPitch(pSrc); int dst_pitch, size, w, h, bytes; w = pSrc->drawable.width; dst_pitch = ((w * (pSrc->drawable.bitsPerPixel >> 3)) + pSiS->EXADriverPtr->pixmapPitchAlign - 1) & ~(pSiS->EXADriverPtr->pixmapPitchAlign - 1); size = dst_pitch * pSrc->drawable.height; if(size > pSiS->exa_scratch->size) return FALSE; pSiS->exa_scratch_next = (pSiS->exa_scratch_next + pSiS->EXADriverPtr->pixmapOffsetAlign - 1) & ~(pSiS->EXADriverPtr->pixmapOffsetAlign - 1); if(pSiS->exa_scratch_next + size > pSiS->exa_scratch->offset + pSiS->exa_scratch->size) { (pSiS->EXADriverPtr->WaitMarker)(pSrc->drawable.pScreen, 0); pSiS->exa_scratch_next = pSiS->exa_scratch->offset; } memcpy(pDst, pSrc, sizeof(*pDst)); pDst->devKind = dst_pitch; pDst->devPrivate.ptr = pSiS->EXADriverPtr->memoryBase + pSiS->exa_scratch_next; pSiS->exa_scratch_next += size; src = pSrc->devPrivate.ptr; src_pitch = exaGetPixmapPitch(pSrc); dst = pDst->devPrivate.ptr; bytes = (src_pitch < dst_pitch) ? src_pitch : dst_pitch; h = pSrc->drawable.height; (pSiS->SyncAccel)(pScrn); while(h--) { SiSMemCopyToVideoRam(pSiS, dst, src, size); src += src_pitch; dst += dst_pitch; } return TRUE; } Bool SiSDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst, int dst_pitch) { ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); unsigned char *src = pSrc->devPrivate.ptr; int src_pitch = exaGetPixmapPitch(pSrc); int size = src_pitch < dst_pitch ? src_pitch : dst_pitch; (pSiS->SyncAccel)(pScrn); if(pSrc->drawable.bitsPerPixel < 8) return FALSE; src += (x * pSrc->drawable.bitsPerPixel / 8) + (y * src_pitch); while(h--) { SiSMemCopyFromVideoRam(pSiS, (unsigned char *)dst, src, size); src += src_pitch; dst += dst_pitch; } return TRUE; } #endif /* EXA */ /* Helper for xv video blitter */ #ifdef INCL_YUV_BLIT_ADAPTOR void SISWriteBlitPacket(SISPtr pSiS, CARD32 *packet) { CARD32 dummybuf; SiSWritePacketPart(packet[0], packet[1], packet[2], packet[3]); SiSWritePacketPart(packet[4], packet[5], packet[6], packet[7]); SiSWritePacketPart(packet[8], packet[9], packet[10], packet[11]); SiSWritePacketPart(packet[12], packet[13], packet[14], packet[15]); SiSWritePacketPart(packet[16], packet[17], packet[18], packet[19]); SiSSyncWP; (void)dummybuf; /* Suppress compiler warning */ } #endif /* For DGA usage */ static void SiSDGAFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h, int color) { SiSSetupForSolidFill(pScrn, color, GXcopy, ~0); SiSSubsequentSolidFillRect(pScrn, x, y, w, h); } static void SiSDGABlitRect(ScrnInfoPtr pScrn, int srcx, int srcy, int dstx, int dsty, int w, int h, int color) { /* Don't need xdir, ydir */ SiSSetupForScreenToScreenCopy(pScrn, 0, 0, GXcopy, (CARD32)~0, color); SiSSubsequentScreenToScreenCopy(pScrn, srcx, srcy, dstx, dsty, w, h); } /* Initialisation */ Bool SiS315AccelInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; SISPtr pSiS = SISPTR(pScrn); #ifdef SIS_USE_XAA XAAInfoRecPtr infoPtr = NULL; int topFB, reservedFbSize, usableFbSize; BoxRec Avail; #ifdef CTSCE unsigned char *AvailBufBase; #ifndef CTSCE_DIRECT int i; #endif #endif #endif /* XAA */ pSiS->ColorExpandBufferNumber = 0; pSiS->PerColorExpandBufferSize = 0; pSiS->RenderAccelArray = NULL; #ifdef SIS_USE_XAA pSiS->AccelInfoPtr = NULL; #endif #ifdef SIS_USE_EXA pSiS->EXADriverPtr = NULL; pSiS->exa_scratch = NULL; #endif if((pScrn->bitsPerPixel != 8) && (pScrn->bitsPerPixel != 16) && (pScrn->bitsPerPixel != 32)) { pSiS->NoAccel = TRUE; } if(!pSiS->NoAccel) { #ifdef SIS_USE_XAA if(!pSiS->useEXA) { pSiS->AccelInfoPtr = infoPtr = XAACreateInfoRec(); if(!infoPtr) pSiS->NoAccel = TRUE; } #endif #ifdef SIS_USE_EXA if(pSiS->useEXA) { if(!(pSiS->EXADriverPtr = exaDriverAlloc())) { pSiS->NoAccel = TRUE; pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */ } } #endif } if(!pSiS->NoAccel) { SiSInitializeAccelerator(pScrn); pSiS->InitAccel = SiSInitializeAccelerator; pSiS->SyncAccel = SiSSyncAccel; pSiS->FillRect = SiSDGAFillRect; pSiS->BlitRect = SiSDGABlitRect; #ifdef SIS_USE_XAA /* ----------------------- XAA ----------------------- */ if(!pSiS->useEXA) { infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS | PIXMAP_CACHE; /* sync */ infoPtr->Sync = SiSSync; /* BitBlt */ infoPtr->SetupForScreenToScreenCopy = SiSSetupForScreenToScreenCopy; infoPtr->SubsequentScreenToScreenCopy = SiSSubsequentScreenToScreenCopy; infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK | TRANSPARENCY_GXCOPY_ONLY; /* solid fills */ infoPtr->SetupForSolidFill = SiSSetupForSolidFill; infoPtr->SubsequentSolidFillRect = SiSSubsequentSolidFillRect; #ifdef TRAP if((pSiS->Chipset != PCI_CHIP_SIS660) && (pSiS->Chipset != PCI_CHIP_SIS330) && (pSiS->Chipset != PCI_CHIP_SIS340) && (pSiS->Chipset != PCI_CHIP_XGIXG20) && (pSiS->Chipset != PCI_CHIP_XGIXG40)) { infoPtr->SubsequentSolidFillTrap = SiSSubsequentSolidFillTrap; } #endif infoPtr->SolidFillFlags = NO_PLANEMASK; /* solid line */ infoPtr->SetupForSolidLine = SiSSetupForSolidLine; infoPtr->SubsequentSolidTwoPointLine = SiSSubsequentSolidTwoPointLine; infoPtr->SubsequentSolidHorVertLine = SiSSubsequentSolidHorzVertLine; infoPtr->SolidLineFlags = NO_PLANEMASK; /* dashed line */ infoPtr->SetupForDashedLine = SiSSetupForDashedLine; infoPtr->SubsequentDashedTwoPointLine = SiSSubsequentDashedTwoPointLine; infoPtr->DashPatternMaxLength = 64; infoPtr->DashedLineFlags = NO_PLANEMASK | LINE_PATTERN_MSBFIRST_LSBJUSTIFIED; /* 8x8 mono pattern fill */ infoPtr->SetupForMono8x8PatternFill = SiSSetupForMonoPatternFill; infoPtr->SubsequentMono8x8PatternFillRect = SiSSubsequentMonoPatternFill; #ifdef TRAP if((pSiS->Chipset != PCI_CHIP_SIS660) && (pSiS->Chipset != PCI_CHIP_SIS330) && (pSiS->Chipset != PCI_CHIP_SIS340) && (pSiS->Chipset != PCI_CHIP_XGIXG20) && (pSiS->Chipset != PCI_CHIP_XGIXG40)) { infoPtr->SubsequentMono8x8PatternFillTrap = SiSSubsequentMonoPatternFillTrap; } #endif infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN | HARDWARE_PATTERN_PROGRAMMED_BITS | BIT_ORDER_IN_BYTE_MSBFIRST; #ifdef SISVRAMQ /* 8x8 color pattern fill (MMIO support not implemented) */ infoPtr->SetupForColor8x8PatternFill = SiSSetupForColor8x8PatternFill; infoPtr->SubsequentColor8x8PatternFillRect = SiSSubsequentColor8x8PatternFillRect; infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN | NO_TRANSPARENCY; #endif #ifdef STSCE /* Screen To Screen Color Expand */ /* The hardware does not support this the way we need it, because * the mono-bitmap is not provided with a pitch of (width), but * with a pitch of scrnOffset (= width * bpp / 8). */ infoPtr->SetupForScreenToScreenColorExpandFill = SiSSetupForScreenToScreenColorExpand; infoPtr->SubsequentScreenToScreenColorExpandFill = SiSSubsequentScreenToScreenColorExpand; infoPtr->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK | BIT_ORDER_IN_BYTE_MSBFIRST ; #endif #ifdef CTSCE #ifdef CTSCE_DIRECT /* CPU color expansion - direct method * * We somewhat fake this function here in the following way: * XAA copies its mono-bitmap data not into an aperture, but * into our video RAM buffer. We then do a ScreenToScreen * color expand. * Unfortunately, XAA sends the data to the aperture AFTER * the call to Subsequent(), therefore we do not execute the * command in Subsequent, but in the following call to Sync(). * (Hence, the SYNC_AFTER_COLOR_EXPAND flag MUST BE SET) * * This is slower than doing it by the CPU. */ pSiS->ColorExpandBufferNumber = 48; pSiS->PerColorExpandBufferSize = ((pScrn->virtualX + 31)/32) * 4; infoPtr->SetupForCPUToScreenColorExpandFill = SiSSetupForCPUToScreenColorExpandFill; infoPtr->SubsequentCPUToScreenColorExpandFill = SiSSubsequentCPUToScreenColorExpandFill; infoPtr->ColorExpandRange = pSiS->ColorExpandBufferNumber * pSiS->PerColorExpandBufferSize; infoPtr->CPUToScreenColorExpandFillFlags = NO_PLANEMASK | CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING | SYNC_AFTER_COLOR_EXPAND; #else /* CPU color expansion - per-scanline / indirect method * * SLOW! SLOWER! SLOWEST! * * Does not work on 330 series, hangs the engine (both VRAM and MMIO). * Does not work in VRAM queue mode. */ #ifndef SISVRAMQ if((pSiS->Chipset != PCI_CHIP_SIS650) && (pSiS->Chipset != PCI_CHIP_SIS660) && (pSiS->Chipset != PCI_CHIP_SIS330) && (pSiS->Chipset != PCI_CHIP_SIS340) && (pSiS->Chipset != PCI_CHIP_XGIXG20) && (pSiS->Chipset != PCI_CHIP_XGIXG40)) { pSiS->ColorExpandBufferNumber = 16; pSiS->ColorExpandBufferCountMask = 0x0F; pSiS->PerColorExpandBufferSize = ((pScrn->virtualX + 31)/32) * 4; infoPtr->NumScanlineColorExpandBuffers = pSiS->ColorExpandBufferNumber; infoPtr->ScanlineColorExpandBuffers = (unsigned char **)&pSiS->ColorExpandBufferAddr[0]; infoPtr->SetupForScanlineCPUToScreenColorExpandFill = SiSSetupForScanlineCPUToScreenColorExpandFill; infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = SiSSubsequentScanlineCPUToScreenColorExpandFill; infoPtr->SubsequentColorExpandScanline = SiSSubsequentColorExpandScanline; infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK | CPU_TRANSFER_PAD_DWORD | SCANLINE_PAD_DWORD | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING; } #endif #endif #endif #ifdef INCL_RENDER #ifdef RENDER /* Render */ SiSCalcRenderAccelArray(pScrn); if(pSiS->RenderAccelArray) { pSiS->AccelLinearScratch = NULL; #ifdef SISNEWRENDER infoPtr->SetupForCPUToScreenAlphaTexture2 = SiSSetupForCPUToScreenAlphaTexture; infoPtr->CPUToScreenAlphaTextureDstFormats = (pScrn->bitsPerPixel == 16) ? SiSDstTextureFormats16 : SiSDstTextureFormats32; #else infoPtr->SetupForCPUToScreenAlphaTexture = SiSSetupForCPUToScreenAlphaTexture; #endif infoPtr->SubsequentCPUToScreenAlphaTexture = SiSSubsequentCPUToScreenTexture; infoPtr->CPUToScreenAlphaTextureFormats = SiSAlphaTextureFormats; infoPtr->CPUToScreenAlphaTextureFlags = XAA_RENDER_NO_TILE; #ifdef SISNEWRENDER infoPtr->SetupForCPUToScreenTexture2 = SiSSetupForCPUToScreenTexture; infoPtr->CPUToScreenTextureDstFormats = (pScrn->bitsPerPixel == 16) ? SiSDstTextureFormats16 : SiSDstTextureFormats32; #else infoPtr->SetupForCPUToScreenTexture = SiSSetupForCPUToScreenTexture; #endif infoPtr->SubsequentCPUToScreenTexture = SiSSubsequentCPUToScreenTexture; infoPtr->CPUToScreenTextureFormats = SiSTextureFormats; infoPtr->CPUToScreenTextureFlags = XAA_RENDER_NO_TILE; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "RENDER acceleration enabled\n"); } #endif #endif #ifdef SISDUALHEAD if(pSiS->DualHeadMode) { infoPtr->RestoreAccelState = SiSRestoreAccelState; } #endif } /* !EXA */ #endif /* XAA */ #ifdef SIS_USE_EXA /* ----------------------- EXA ----------------------- */ if(pSiS->useEXA) { pSiS->EXADriverPtr->exa_major = 2; pSiS->EXADriverPtr->exa_minor = 0; /* data */ pSiS->EXADriverPtr->memoryBase = pSiS->FbBase; pSiS->EXADriverPtr->memorySize = pSiS->maxxfbmem; pSiS->EXADriverPtr->offScreenBase = pScrn->virtualX * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) / 8); if(pSiS->EXADriverPtr->memorySize > pSiS->EXADriverPtr->offScreenBase) { pSiS->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS; } else { pSiS->NoXvideo = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for offscreen memory manager. Xv disabled\n"); } pSiS->EXADriverPtr->pixmapOffsetAlign = 16; /* src/dst: double quad word boundary */ pSiS->EXADriverPtr->pixmapPitchAlign = 4; /* pitch: double word boundary */ pSiS->EXADriverPtr->maxX = 4095; pSiS->EXADriverPtr->maxY = 4095; /* Sync */ pSiS->EXADriverPtr->WaitMarker = SiSEXASync; /* Solid fill */ pSiS->EXADriverPtr->PrepareSolid = SiSPrepareSolid; pSiS->EXADriverPtr->Solid = SiSSolid; pSiS->EXADriverPtr->DoneSolid = SiSDoneSolid; /* Copy */ pSiS->EXADriverPtr->PrepareCopy = SiSPrepareCopy; pSiS->EXADriverPtr->Copy = SiSCopy; pSiS->EXADriverPtr->DoneCopy = SiSDoneCopy; /* Composite */ #ifdef SIS_HAVE_COMPOSITE SiSCalcRenderAccelArray(pScrn); if(pSiS->RenderAccelArray) { pSiS->EXADriverPtr->CheckComposite = SiSCheckComposite; pSiS->EXADriverPtr->PrepareComposite = SiSPrepareComposite; pSiS->EXADriverPtr->Composite = SiSComposite; pSiS->EXADriverPtr->DoneComposite = SiSDoneComposite; } #endif /* Upload, download to/from Screen */ pSiS->EXADriverPtr->UploadToScreen = SiSUploadToScreen; pSiS->EXADriverPtr->DownloadFromScreen = SiSDownloadFromScreen; } #endif } /* NoAccel */ /* Init framebuffer memory manager */ /* Traditional layout: * |-----------------++++++++++++++++++++^************==========~~~~~~~~~~~~| * | UsableFbSize ColorExpandBuffers | DRI-Heap HWCursor CommandQueue * FbBase topFB * +-------------maxxfbmem---------------+ * * On SiS76x with UMA+LFB: * |UUUUUUUUUUUUUUU--------------++++++++++++++++++++^==========~~~~~~~~~~~~| * DRI heap |UsableFbSize ColorExpandBuffers | HWCursor CommandQueue * (in UMA and FbBase topFB * eventually +---------- maxxfbmem ------------+ * beginning of * LFB) */ #ifdef SIS_USE_XAA if(!pSiS->useEXA) { topFB = pSiS->maxxfbmem; /* relative to FbBase */ reservedFbSize = pSiS->ColorExpandBufferNumber * pSiS->PerColorExpandBufferSize; usableFbSize = topFB - reservedFbSize; #ifdef CTSCE AvailBufBase = pSiS->FbBase + usableFbSize; if(pSiS->ColorExpandBufferNumber) { #ifdef CTSCE_DIRECT infoPtr->ColorExpandBase = (unsigned char *)AvailBufBase; pSiS->ColorExpandBase = usableFbSize; #else for(i = 0; i < pSiS->ColorExpandBufferNumber; i++) { pSiS->ColorExpandBufferAddr[i] = AvailBufBase + i * pSiS->PerColorExpandBufferSize; pSiS->ColorExpandBufferScreenOffset[i] = usableFbSize + i * pSiS->PerColorExpandBufferSize; } #endif } #endif Avail.x1 = 0; Avail.y1 = 0; Avail.x2 = pScrn->displayWidth; Avail.y2 = (usableFbSize / (pScrn->displayWidth * pScrn->bitsPerPixel/8)) - 1; if(Avail.y2 < 0) Avail.y2 = 32767; if(Avail.y2 < pScrn->currentMode->VDisplay) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for accelerator. At least " "%dKB needed, %dKB available\n", ((((pScrn->displayWidth * pScrn->bitsPerPixel/8) /* +8 for make it sure */ * pScrn->currentMode->VDisplay) + reservedFbSize) / 1024) + 8, pSiS->maxxfbmem/1024); pSiS->NoAccel = TRUE; pSiS->NoXvideo = TRUE; XAADestroyInfoRec(pSiS->AccelInfoPtr); pSiS->AccelInfoPtr = NULL; return FALSE; /* Don't even init fb manager */ } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Framebuffer from (%d,%d) to (%d,%d)\n", Avail.x1, Avail.y1, Avail.x2 - 1, Avail.y2 - 1); xf86InitFBManager(pScreen, &Avail); if(!pSiS->NoAccel) { return XAAInit(pScreen, infoPtr); } } /* !EXA */ #endif /* XAA */ #ifdef SIS_USE_EXA if(pSiS->useEXA) { if(!pSiS->NoAccel) { if(!exaDriverInit(pScreen, pSiS->EXADriverPtr)) { pSiS->NoAccel = TRUE; pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */ return FALSE; } /* Reserve locked offscreen scratch area of 128K for glyph data */ pSiS->exa_scratch = exaOffscreenAlloc(pScreen, 128 * 1024, 16, TRUE, SiSScratchSave, pSiS); if(pSiS->exa_scratch) { pSiS->exa_scratch_next = pSiS->exa_scratch->offset; pSiS->EXADriverPtr->UploadToScratch = SiSUploadToScratch; } } else { pSiS->NoXvideo = TRUE; /* No fbmem manager -> no xv */ } } #endif /* EXA */ return TRUE; }