/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i128/i128accel.c,v 1.7 2000/12/06 01:07:34 robin Exp $ */ /* * Copyright 1997-2000 by Robin Cutshaw * * 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 Robin Cutshaw not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Robin Cutshaw makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * ROBIN CUTSHAW DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL ROBIN CUTSHAW 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. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "xaa.h" #include "xaalocal.h" #include "xf86fbman.h" #include "miline.h" #include "servermd.h" #include "xf86.h" #include "xf86_OSproc.h" #include "xf86_ansic.h" #include "xf86Pci.h" #include "xf86PciInfo.h" #include "i128.h" #include "i128reg.h" static void I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h); static void I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, unsigned planemask, int transparency_color); static void I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h); static void I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask); static void I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h); static void I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int flags); static void I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2); static void I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask, int nBox, register BoxPtr pBoxI); static void I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir, int alu, unsigned planemask); #define ENG_PIPELINE_READY() { while (pI128->mem.rbase_a[BUSY] & BUSY_BUSY) ; } #define ENG_DONE() { while (pI128->mem.rbase_a[FLOW] & (FLOW_DEB | FLOW_MCB | FLOW_PRV)) ;} /* pre-shift rops and just or in as needed */ static const CARD32 i128alu[16] = { CR_CLEAR<<8, CR_AND<<8, CR_AND_REV<<8, CR_COPY<<8, CR_AND_INV<<8, CR_NOOP<<8, CR_XOR<<8, CR_OR<<8, CR_NOR<<8, CR_EQUIV<<8, CR_INVERT<<8, CR_OR_REV<<8, CR_COPY_INV<<8, CR_OR_INV<<8, CR_NAND<<8, CR_SET<<8 }; /* 8bpp 16bpp 32bpp unused */ static const int min_size[] = { 0x62, 0x32, 0x1A, 0x00 }; static const int max_size[] = { 0x80, 0x40, 0x20, 0x00 }; static const int split_size[] = { 0x20, 0x10, 0x08, 0x00 }; void I128EngineDone(ScrnInfoPtr pScrn) { I128Ptr pI128 = I128PTR(pScrn); ENG_DONE(); } static void I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h) { I128Ptr pI128 = I128PTR(pScrn); #if 0 if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BB %d,%d %d,%d %d,%d 0x%x/0x%x\n", x1, y1, x2, y2, w, h, pI128->cmd); #endif ENG_PIPELINE_READY(); pI128->mem.rbase_a[CMD] = pI128->cmd; /*pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir;*/ if (pI128->blitdir & DIR_RL_TB) { x1 += w; x1--; x2 += w; x2--; } if (pI128->blitdir & DIR_LR_BT) { y1 += h; y1--; y2 += h; y2--; } if (pI128->Chipset == PCI_CHIP_I128) { int bppi; static int first_time_through = 1; /* The I128-1 has a nasty bitblit bug * that occurs when dest is exactly 8 pages wide */ bppi = (pI128->mem.rbase_a[BUF_CTRL] & BC_PSIZ_MSK) >> 24; if ((w >= min_size[bppi]) && (w <= max_size[bppi])) { if (first_time_through) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using I128-1 workarounds.\n"); first_time_through = 0; } bppi = split_size[bppi]; #if 1 /* split method */ pI128->mem.rbase_a[XY2_WH] = (bppi<<16) | h; pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB; pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB; ENG_PIPELINE_READY(); w -= bppi; if (pI128->blitdir & DIR_RL_TB) { /* right to left blit */ x1 -= bppi; x2 -= bppi; } else { /* left to right blit */ x1 += bppi; x2 += bppi; } #else /* clip method */ pI128->mem.rbase_a[CLPTL] = (x2<<16) | y2; pI128->mem.rbase_a[CLPBR] = ((x2+w)<<16) | (y2+h); w += bppi; #endif } } pI128->mem.rbase_a[XY2_WH] = (w<<16) | h; pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB; pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB; } static void I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, unsigned planemask, int transparency_color) { I128Ptr pI128 = I128PTR(pScrn); #if 0 if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSSC %d,%d %d 0x%x %d\n", xdir, ydir, rop, planemask, transparency_color); #endif ENG_PIPELINE_READY(); if (planemask == -1) pI128->mem.rbase_a[MASK] = -1; else switch (pI128->bitsPerPixel) { case 8: pI128->mem.rbase_a[MASK] = planemask | (planemask<<8) | (planemask<<16) | (planemask<<24); break; case 16: pI128->mem.rbase_a[MASK] = planemask | (planemask<<16); break; case 24: case 32: default: pI128->mem.rbase_a[MASK] = planemask; break; } pI128->mem.rbase_a[CLPTL] = 0x00000000; pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047; if (transparency_color != -1) pI128->mem.rbase_a[BACK] = transparency_color; if (xdir == -1) { if (ydir == -1) pI128->blitdir = DIR_RL_BT; else pI128->blitdir = DIR_RL_TB; } else { if (ydir == -1) pI128->blitdir = DIR_LR_BT; else pI128->blitdir = DIR_LR_TB; } pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir; pI128->rop = i128alu[rop]; pI128->cmd = (transparency_color != -1 ? (CS_TRNSP<<16) : 0) | pI128->rop | CO_BITBLT; pI128->mem.rbase_a[CMD] = pI128->cmd; } static void I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h) { I128BitBlit(pScrn, x1, y1, x2, y2, w, h); } static void I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask) { I128Ptr pI128 = I128PTR(pScrn); #if 0 if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSF color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", color, rop, i128alu[rop]>>8, planemask); #endif ENG_PIPELINE_READY(); if (planemask == -1) pI128->mem.rbase_a[MASK] = -1; else switch (pI128->bitsPerPixel) { case 8: pI128->mem.rbase_a[MASK] = planemask | (planemask<<8) | (planemask<<16) | (planemask<<24); break; case 16: pI128->mem.rbase_a[MASK] = planemask | (planemask<<16); break; case 24: case 32: default: pI128->mem.rbase_a[MASK] = planemask; break; } pI128->mem.rbase_a[FORE] = color; pI128->clptl = pI128->mem.rbase_a[CLPTL] = 0x00000000; pI128->clpbr = pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ; pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir = DIR_LR_TB; pI128->rop = i128alu[rop]; pI128->cmd = (CS_SOLID<<16) | pI128->rop | CO_BITBLT; pI128->mem.rbase_a[CMD] = pI128->cmd; } static void I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) { #if 0 I128Ptr pI128 = I128PTR(pScrn); if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SSFR %d,%d %d,%d\n", x, y, w, h); #endif I128BitBlit(pScrn, 0, 0, x, y, w, h); } static void I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int flags) { I128Ptr pI128 = I128PTR(pScrn); #if 0 if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STPL I128rop 0x%x %d,%d %d,%d clip %d,%d %d,%d\n", pI128->rop, x1, y1, x2, y2, pI128->clptl>>16, pI128->clptl&0xffff, (pI128->clpbr>>16)&0xffff, pI128->clpbr&0xffff); #endif ENG_PIPELINE_READY(); pI128->mem.rbase_a[CMD] = ((flags&0x0100) ? (CP_NLST<<24) : 0) | (CC_CLPRECI<<21) | (CS_SOLID<<16) | pI128->rop | CO_LINE; pI128->mem.rbase_a[CLPTL] = pI128->clptl; pI128->mem.rbase_a[CLPBR] = pI128->clpbr; pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB; pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB; } static void I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) { I128Ptr pI128 = I128PTR(pScrn); int tmp; #if 0 if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SCR %d,%d %d,%d\n", x1, y1, x2, y2); #endif if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } pI128->clptl = (x1<<16) | y1; pI128->clpbr = (x2<<16) | y2; } static void I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask, int nBox, register BoxPtr pBoxI) { I128Ptr pI128 = I128PTR(pScrn); register int w, h; #if 0 if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", fg, rop, i128alu[rop]>>8, planemask); #endif ENG_PIPELINE_READY(); if (planemask != -1) { if (pI128->bitsPerPixel == 8) { planemask |= (planemask<<8) | (planemask<<16) | (planemask<<24); } else if (pI128->bitsPerPixel == 16) planemask |= planemask<<16; } pI128->mem.rbase_a[MASK] = planemask; pI128->mem.rbase_a[FORE] = fg; pI128->mem.rbase_a[CMD] = (CS_SOLID<<16) | i128alu[rop] | CO_BITBLT; pI128->mem.rbase_a[CLPTL] = 0x00000000; pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047; pI128->mem.rbase_a[XY3_DIR] = DIR_LR_TB; pI128->mem.rbase_a[XY0_SRC] = 0x00000000; while (nBox > 0) { w = pBoxI->x2 - pBoxI->x1; h = pBoxI->y2 - pBoxI->y1; if (w > 0 && h > 0) { pI128->mem.rbase_a[XY2_WH] = (w<<16) | h; MB; pI128->mem.rbase_a[XY1_DST] = (pBoxI->x1<<16) | pBoxI->y1; MB; ENG_PIPELINE_READY(); #if 0 if (pI128->Debug) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR x,y %d,%d w,h %d,%d\n", pBoxI->x1, pBoxI->y1, w, h); #endif } pBoxI++; nBox--; } ENG_DONE(); } static void I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir, int alu, unsigned planemask) { I128Ptr pI128 = I128PTR(pScrn); I128SetupForScreenToScreenCopy(pScrn, xdir, ydir, alu, planemask, -1); for (; nbox; pbox++, pptSrc++, nbox--) I128SubsequentScreenToScreenCopy(pScrn, pptSrc->x, pptSrc->y, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); ENG_DONE(); } Bool I128XaaInit(ScreenPtr pScreen) { XAAInfoRecPtr infoPtr; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I128Ptr pI128 = I128PTR(pScrn); BoxRec AvailFBArea; CARD32 buf_ctrl; int maxlines; pI128->XaaInfoRec = infoPtr = XAACreateInfoRec(); if (!infoPtr) return FALSE; infoPtr->Flags = PIXMAP_CACHE | OFFSCREEN_PIXMAPS | LINEAR_FRAMEBUFFER ; infoPtr->Sync = I128EngineDone; /* screen to screen copy */ infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY; if (pI128->Chipset == PCI_CHIP_I128_T2R) infoPtr->ScreenToScreenCopyFlags |= ONLY_LEFT_TO_RIGHT_BITBLT; infoPtr->SetupForScreenToScreenCopy = I128SetupForScreenToScreenCopy; infoPtr->SubsequentScreenToScreenCopy = I128SubsequentScreenToScreenCopy; #if 0 /* screen to screen color expansion */ if (pI128->Chipset == PCI_CHIP_I128_T2R) infoPtr->ScreenToScreenColorExpandFillFlags |= ONLY_LEFT_TO_RIGHT_BITBLT; infoPtr->SetupForScreenToScreenColorExpandFill = I128SetupForScreenToScreenColorExpandFill; infoPtr->SubsequentScreenToScreenColorExpandFill = I128SubsequentScreenToScreenColorExpandFill; #endif /* solid fills */ infoPtr->SetupForSolidFill = I128SetupForSolidFill; infoPtr->SubsequentSolidFillRect = I128SubsequentSolidFillRect; infoPtr->FillSolidRects = I128FillSolidRects; /* solid lines */ infoPtr->SubsequentSolidTwoPointLine = I128SubsequentSolidTwoPointLine; /* clipping */ infoPtr->ClippingFlags = HARDWARE_CLIP_LINE; infoPtr->SetClippingRectangle = I128SetClippingRectangle; infoPtr->PolyFillRectSolidFlags = 0; maxlines = ((pI128->MemorySize * 1024) - 1024) / (pScrn->displayWidth * pI128->bitsPerPixel / 8); AvailFBArea.x1 = 0; AvailFBArea.x2 = pI128->displayWidth; AvailFBArea.y1 = 0; AvailFBArea.y2 = maxlines; xf86InitFBManager(pScreen, &AvailFBArea); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %d lines for offscreen memory\n", maxlines - pScrn->virtualY); switch (pI128->bitsPerPixel) { case 8: buf_ctrl = BC_PSIZ_8B; break; case 16: buf_ctrl = BC_PSIZ_16B; break; case 24: case 32: buf_ctrl = BC_PSIZ_32B; break; default: buf_ctrl = 0; break; /* error */ } if (pI128->Chipset == PCI_CHIP_I128_T2R) { if (pI128->MemoryType == I128_MEMORY_SGRAM) buf_ctrl |= BC_MDM_PLN; else buf_ctrl |= BC_BLK_ENA; } pI128->mem.rbase_a[BUF_CTRL] = buf_ctrl; pI128->mem.rbase_a[DE_PGE] = 0x00; pI128->mem.rbase_a[DE_SORG] = pI128->displayOffset; pI128->mem.rbase_a[DE_DORG] = pI128->displayOffset; pI128->mem.rbase_a[DE_MSRC] = 0x00; pI128->mem.rbase_a[DE_WKEY] = 0x00; pI128->mem.rbase_a[DE_SPTCH] = pI128->mem.rbase_g[DB_PTCH]; pI128->mem.rbase_a[DE_DPTCH] = pI128->mem.rbase_g[DB_PTCH]; if (pI128->Chipset == PCI_CHIP_I128_T2R4) pI128->mem.rbase_a[DE_ZPTCH] = pI128->mem.rbase_g[DB_PTCH]; pI128->mem.rbase_a[RMSK] = 0x00000000; pI128->mem.rbase_a[XY4_ZM] = ZOOM_NONE; pI128->mem.rbase_a[LPAT] = 0xffffffff; /* for lines */ pI128->mem.rbase_a[PCTRL] = 0x00000000; /* for lines */ pI128->mem.rbase_a[CLPTL] = 0x00000000; pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ; pI128->mem.rbase_a[ACNTRL] = 0x00000000; pI128->mem.rbase_a[INTM] = 0x03; if (pI128->Debug) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I128XaaInit done\n"); I128DumpActiveRegisters(pScrn); } return(XAAInit(pScreen, infoPtr)); }