/* * Copyright 1992-2003 by Alan Hourihane, North Wales, UK. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Alan Hourihane not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Alan Hourihane makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Authors: Alan Hourihane, * * Trident accelerated options. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "xf86.h" #include "xf86_OSproc.h" #include "xf86Pci.h" #include "miline.h" #include "trident.h" #include "trident_regs.h" #ifdef HAVE_XAA_H #include "xaalocal.h" #include "xaarop.h" static void TridentSync(ScrnInfoPtr pScrn); static void TridentSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask, int length, unsigned char *pattern); static void TridentSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn, int x, int y, int dmaj, int dmin, int e, int len, int octant, int phase); static void TridentSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask); static void TridentSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn, int x, int y, int dmaj, int dmin, int e, int len, int octant); static void TridentSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir); static void TridentSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask); static void TridentSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h); static void TridentSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h); static void TridentSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, unsigned int planemask, int transparency_color); static void TridentSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, int fg, int bg, int rop, unsigned int planemask); static void TridentSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patternx, int patterny, int x, int y, int w, int h); #if 0 static void TridentSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, int rop, unsigned int planemask, int trans_col); static void TridentSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patternx, int patterny, int x, int y, int w, int h); #endif #if 0 static void TridentSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask); static void TridentSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft); static void TridentSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); #endif static void TridentInitializeAccelerator(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); /* This forces updating the clipper */ pTrident->Clipping = TRUE; CHECKCLIPPING; if ( (pTrident->Chipset == PROVIDIA9682) || (pTrident->Chipset == CYBER9385) || (pTrident->Chipset == CYBER9382) ) pTrident->EngineOperation |= 0x100; /* Disable Clipping */ TGUI_OPERMODE(pTrident->EngineOperation); pTrident->PatternLocation = pScrn->displayWidth*pScrn->bitsPerPixel/8; } #endif Bool TridentAccelInit(ScreenPtr pScreen) { #ifdef HAVE_XAA_H XAAInfoRecPtr infoPtr; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); TRIDENTPtr pTrident = TRIDENTPTR(pScrn); if (pTrident->NoAccel) return FALSE; pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec(); if (!infoPtr) return FALSE; if (!(pTrident->Chipset == TGUI9440AGi && pScrn->bitsPerPixel > 8)) infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER; pTrident->InitializeAccelerator = TridentInitializeAccelerator; TridentInitializeAccelerator(pScrn); infoPtr->PixmapCacheFlags = DO_NOT_BLIT_STIPPLES; infoPtr->Sync = TridentSync; infoPtr->SolidLineFlags = NO_PLANEMASK; infoPtr->SetupForSolidLine = TridentSetupForSolidLine; infoPtr->SolidBresenhamLineErrorTermBits = 12; infoPtr->SubsequentSolidBresenhamLine = TridentSubsequentSolidBresenhamLine; infoPtr->SubsequentSolidHorVertLine = TridentSubsequentSolidHorVertLine; infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED | NO_PLANEMASK | LINE_PATTERN_POWER_OF_2_ONLY; infoPtr->SetupForDashedLine = TridentSetupForDashedLine; infoPtr->DashedBresenhamLineErrorTermBits = 12; infoPtr->SubsequentDashedBresenhamLine = TridentSubsequentDashedBresenhamLine; infoPtr->DashPatternMaxLength = 16; infoPtr->SolidFillFlags = NO_PLANEMASK; infoPtr->SetupForSolidFill = TridentSetupForFillRectSolid; infoPtr->SubsequentSolidFillRect = TridentSubsequentFillRectSolid; infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK; if (!HAS_DST_TRANS) infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY; infoPtr->SetupForScreenToScreenCopy = TridentSetupForScreenToScreenCopy; infoPtr->SubsequentScreenToScreenCopy = TridentSubsequentScreenToScreenCopy; if (!((pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) && pScrn->bitsPerPixel > 8)) { infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST; infoPtr->SetupForMono8x8PatternFill = TridentSetupForMono8x8PatternFill; infoPtr->SubsequentMono8x8PatternFillRect = TridentSubsequentMono8x8PatternFillRect; } #if 0 /* Not convinced this works 100% yet */ infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN | BIT_ORDER_IN_BYTE_MSBFIRST; if (!HAS_DST_TRANS) infoPtr->Color8x8PatternFillFlags |= NO_TRANSPARENCY; infoPtr->SetupForColor8x8PatternFill = TridentSetupForColor8x8PatternFill; infoPtr->SubsequentColor8x8PatternFillRect = TridentSubsequentColor8x8PatternFillRect; #endif #if 0 /* This is buggy, it only seems to work 95% of the time.... */ { infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK | NO_TRANSPARENCY | BIT_ORDER_IN_BYTE_MSBFIRST; pTrident->XAAScanlineColorExpandBuffers[0] = xnfalloc(((pScrn->virtualX + 63)) *4* (pScrn->bitsPerPixel / 8)); infoPtr->NumScanlineColorExpandBuffers = 1; infoPtr->ScanlineColorExpandBuffers = pTrident->XAAScanlineColorExpandBuffers; infoPtr->SetupForScanlineCPUToScreenColorExpandFill = TridentSetupForScanlineCPUToScreenColorExpandFill; infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = TridentSubsequentScanlineCPUToScreenColorExpandFill; infoPtr->SubsequentColorExpandScanline = TridentSubsequentColorExpandScanline; } #endif return(XAAInit(pScreen, infoPtr)); #else return FALSE; #endif } #ifdef HAVE_XAA_H static void TridentSync(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int count = 0, timeout = 0; int busy; TGUI_OPERMODE(pTrident->EngineOperation); for (;;) { BLTBUSY(busy); if (busy != GE_BUSY) { return; } count++; if (count == 10000000) { ErrorF("Trident: BitBLT engine time-out.\n"); count = 9990000; timeout++; if (timeout == 8) { /* Reset BitBLT Engine */ TGUI_STATUS(0x00); return; } } } } static void TridentClearSync(ScrnInfoPtr pScrn) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int count = 0, timeout = 0; int busy; for (;;) { BLTBUSY(busy); if (busy != GE_BUSY) { return; } count++; if (count == 10000000) { ErrorF("Trident: BitBLT engine time-out.\n"); count = 9990000; timeout++; if (timeout == 8) { /* Reset BitBLT Engine */ TGUI_STATUS(0x00); return; } } } } static void TridentSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, unsigned int planemask, int transparency_color) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int dst = 0; pTrident->BltScanDirection = 0; if (xdir < 0) pTrident->BltScanDirection |= XNEG; if (ydir < 0) pTrident->BltScanDirection |= YNEG; REPLICATE(transparency_color); if (transparency_color != -1) { if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) { dst |= 1<<16; } else { TGUI_OPERMODE(pTrident->EngineOperation | DST_ENABLE); } TGUI_CKEY(transparency_color); } TGUI_DRAWFLAG(pTrident->DrawFlag | pTrident->BltScanDirection | SCR2SCR | dst); TGUI_FMIX(XAAGetCopyROP(rop)); } static void TridentSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); if (pTrident->BltScanDirection & YNEG) { y1 = y1 + h - 1; y2 = y2 + h - 1; } if (pTrident->BltScanDirection & XNEG) { x1 = x1 + w - 1; x2 = x2 + w - 1; } TGUI_SRC_XY(x1,y1); TGUI_DEST_XY(x2,y2); TGUI_DIM_XY(w,h); TGUI_COMMAND(GE_BLT); TridentClearSync(pScrn); } static void TridentSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); pTrident->BltScanDirection = 0; REPLICATE(color); TGUI_FMIX(XAAGetPatternROP(rop)); if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) { TGUI_FPATCOL(color); } else { TGUI_FCOLOUR(color); } } static void TridentSubsequentSolidBresenhamLine( ScrnInfoPtr pScrn, int x, int y, int dmaj, int dmin, int e, int len, int octant) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int tmp = pTrident->BltScanDirection; if (octant & YMAJOR) tmp |= YMAJ; if (octant & XDECREASING) tmp |= XNEG; if (octant & YDECREASING) tmp |= YNEG; TGUI_DRAWFLAG(pTrident->DrawFlag | SOLIDFILL | STENCIL | tmp); TGUI_SRC_XY(dmin-dmaj,dmin); TGUI_DEST_XY(x,y); TGUI_DIM_XY(dmin+e,len); TGUI_COMMAND(GE_BRESLINE); TridentSync(pScrn); } static void TridentSubsequentSolidHorVertLine( ScrnInfoPtr pScrn, int x, int y, int len, int dir ){ TRIDENTPtr pTrident = TRIDENTPTR(pScrn); TGUI_DRAWFLAG(pTrident->DrawFlag | SOLIDFILL); if (dir == DEGREES_0) { TGUI_DIM_XY(len,1); TGUI_DEST_XY(x,y); } else { TGUI_DIM_XY(1,len); TGUI_DEST_XY(x,y); } TGUI_COMMAND(GE_BLT); TridentSync(pScrn); } void TridentSetupForDashedLine( ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask, int length, unsigned char *pattern ){ TRIDENTPtr pTrident = TRIDENTPTR(pScrn); CARD32 *DashPattern = (CARD32*)pattern; CARD32 NiceDashPattern = DashPattern[0]; NiceDashPattern = *((CARD16 *)pattern) & ((1<BltScanDirection = 0; REPLICATE(fg); if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) { TGUI_FPATCOL(fg); if (bg == -1) { pTrident->BltScanDirection |= 1<<12; TGUI_BPATCOL(~fg); } else { REPLICATE(bg); TGUI_BPATCOL(bg); } } else { TGUI_FCOLOUR(fg); if (bg == -1) { pTrident->BltScanDirection |= 1<<12; TGUI_BCOLOUR(~fg); } else { REPLICATE(bg); TGUI_BCOLOUR(bg); } } TGUI_FMIX(XAAGetPatternROP(rop)); pTrident->LinePattern = NiceDashPattern; } void TridentSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn, int x, int y, int dmaj, int dmin, int e, int len, int octant, int phase) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int tmp = pTrident->BltScanDirection; if (octant & YMAJOR) tmp |= YMAJ; if (octant & XDECREASING) tmp |= XNEG; if (octant & YDECREASING) tmp |= YNEG; TGUI_STYLE(((pTrident->LinePattern >> phase) | (pTrident->LinePattern << (16-phase))) & 0x0000FFFF); TGUI_DRAWFLAG(pTrident->DrawFlag | STENCIL | tmp); TGUI_SRC_XY(dmin-dmaj,dmin); TGUI_DEST_XY(x,y); TGUI_DIM_XY(e+dmin,len); TGUI_COMMAND(GE_BRESLINE); TridentSync(pScrn); } static void TridentSetupForFillRectSolid(ScrnInfoPtr pScrn, int color, int rop, unsigned int planemask) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int drawflag = 0; REPLICATE(color); TGUI_FMIX(XAAGetPatternROP(rop)); if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) { TGUI_FPATCOL(color); } else { drawflag |= PATMONO; TGUI_FCOLOUR(color); } TGUI_DRAWFLAG(pTrident->DrawFlag | SOLIDFILL | drawflag); } static void TridentSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); TGUI_DIM_XY(w,h); TGUI_DEST_XY(x,y); TGUI_COMMAND(GE_BLT); TridentSync(pScrn); } #if 0 static void MoveDWORDS( register CARD32* dest, register CARD32* src, register int dwords ) { while(dwords & ~0x03) { *dest = *src; *(dest + 1) = *(src + 1); *(dest + 2) = *(src + 2); *(dest + 3) = *(src + 3); src += 4; dest += 4; dwords -= 4; } if (!dwords) return; *dest = *src; dest += 1; src += 1; if (dwords == 1) return; *dest = *src; dest += 1; src += 1; if (dwords == 2) return; *dest = *src; dest += 1; src += 1; } #endif static void TridentSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, int fg, int bg, int rop, unsigned int planemask) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int drawflag = 0; REPLICATE(fg); if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) TGUI_FPATCOL(fg); else TGUI_FCOLOUR(fg); if (bg == -1) { drawflag |= 1<<12; if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) TGUI_BPATCOL(~fg); else TGUI_BCOLOUR(~fg); } else { REPLICATE(bg); if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) TGUI_BPATCOL(bg); else TGUI_BCOLOUR(bg); } if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) { drawflag |= 7<<18; } TGUI_DRAWFLAG(pTrident->DrawFlag | PAT2SCR | PATMONO | drawflag); TGUI_PATLOC(((patterny * pTrident->PatternLocation) + (patternx * pScrn->bitsPerPixel / 8)) >> 6); TGUI_FMIX(XAAGetPatternROP(rop)); } static void TridentSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patternx, int patterny, int x, int y, int w, int h) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); TGUI_DEST_XY(x,y); TGUI_DIM_XY(w,h); TGUI_COMMAND(GE_BLT); TridentSync(pScrn); } #if 0 static void TridentSetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny, int rop, unsigned int planemask, int transparency_color) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int drawflag = 0; REPLICATE(transparency_color); if (transparency_color != -1) { if (pTrident->Chipset == PROVIDIA9685 || pTrident->Chipset == CYBER9388) { drawflag |= 1<<16; } else { TGUI_OPERMODE(pTrident->EngineOperation | DST_ENABLE); } TGUI_CKEY(transparency_color); } TGUI_DRAWFLAG(pTrident->DrawFlag | PAT2SCR | drawflag); TGUI_PATLOC(((patterny * pTrident->PatternLocation) + (patternx * pScrn->bitsPerPixel / 8)) >> 6); TGUI_FMIX(XAAGetPatternROP(rop)); } static void TridentSubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patternx, int patterny, int x, int y, int w, int h) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); TGUI_DEST_XY(x,y); TGUI_DIM_XY(w,h); TGUI_COMMAND(GE_BLT); TridentClearSync(pScrn); } #endif #if 0 static void TridentSetupForScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, int fg, int bg, int rop, unsigned int planemask ){ TRIDENTPtr pTrident = TRIDENTPTR(pScrn); int drawflag = SRCMONO; REPLICATE(fg); TGUI_FCOLOUR(fg); if (bg == -1) { drawflag |= 1<<12; TGUI_BCOLOUR(~fg); } else { REPLICATE(bg); TGUI_BCOLOUR(bg); } TGUI_SRC_XY(0,0); TGUI_DRAWFLAG(drawflag); TGUI_FMIX(XAAGetCopyROP(rop)); } static void TridentSubsequentScanlineCPUToScreenColorExpandFill( ScrnInfoPtr pScrn, int x, int y, int w, int h, int skipleft ){ TRIDENTPtr pTrident = TRIDENTPTR(pScrn); pTrident->dwords = (w + 31) >> 5; pTrident->h = h; pTrident->y = y; pTrident->x = x; pTrident->w = w; TGUI_DEST_XY(x,pTrident->y++); TGUI_DIM_XY(w,1); TGUI_COMMAND(GE_BLT); } static void TridentSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) { TRIDENTPtr pTrident = TRIDENTPTR(pScrn); XAAInfoRecPtr infoRec; infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn); MoveDWORDS((CARD32 *)pTrident->FbBase, (CARD32 *)pTrident->XAAScanlineColorExpandBuffers[0], pTrident->dwords); pTrident->h--; TridentSync(pScrn); if (pTrident->h) { TGUI_DEST_XY(pTrident->x,pTrident->y++); TGUI_DIM_XY(pTrident->w,1); TGUI_COMMAND(GE_BLT); } } #endif #endif