/* $XFree86: xc/programs/Xserver/hw/xfree68/imstt/imstt.c,v 1.1.2.4 1999/07/23 09:00:23 hohndel Exp $ */ #include "X.h" #include "Xmd.h" #include "Xproto.h" #include "windowstr.h" #include "scrnintstr.h" #include "pixmapstr.h" #include "regionstr.h" #include "gcstruct.h" #include "xf86.h" #ifndef PSZ #define PSZ 8 #endif #include "cfb.h" #include "cfb16.h" #include "cfb24.h" #include "cfb32.h" extern void (*fbdevBitBlt)(); extern ScrnInfoRec fbdevInfoRec; extern pointer fbdevVirtBase; extern pointer fbdevRegBase; extern GCOps cfb32TEOps1Rect, cfb32TEOps, cfb32NonTEOps1Rect, cfb32NonTEOps, cfb24TEOps1Rect, cfb24TEOps, cfb24NonTEOps1Rect, cfb24NonTEOps, cfb16TEOps1Rect, cfb16TEOps, cfb16NonTEOps1Rect, cfb16NonTEOps, cfbTEOps1Rect, cfbTEOps, cfbNonTEOps1Rect, cfbNonTEOps; static int line_pitch; static int bytes_per_pixel; /* IMS TwinTurbo blitter registers and macros */ #define S1SA 0x0000 #define S2SA 0x0004 #define SP 0x0008 #define DSA 0x000c #define CNT 0x0010 #define DP_OCTL 0x0014 #define CLR 0x0018 #define BI 0x0020 #define MBC 0x0024 #define BLTCTL 0x0028 #define SSTATUS 0x0090 static inline void ttout (volatile unsigned long addr, unsigned int val) { register unsigned long base_addr = (unsigned long)fbdevRegBase; asm("stwbrx %0,%1,%2; eieio": : "r"(val), "b"(addr), "r"(base_addr):"memory"); } static inline unsigned int ttin (volatile unsigned long addr) { register unsigned long base_addr = (unsigned long)fbdevRegBase, val; asm("lwbrx %0,%1,%2": "=r"(val):"b"(addr), "r"(base_addr)); return val; } static inline void ttBitBlt (int Bpp, int lpitch, int xsrc, int ysrc, int xdst, int ydst, int w, int h) { unsigned long srcStart, dstStart; unsigned int sp, dp_octl, cnt, bltctl; xsrc *= Bpp; xdst *= Bpp; w *= Bpp; w--; h--; bltctl = 0x05; sp = lpitch << 16; cnt = h << 16; if (ysrc < ydst) { ysrc += h; ydst += h; sp |= -(lpitch) & 0xffff; dp_octl = -(lpitch) & 0xffff; } else { sp |= lpitch; dp_octl = lpitch; } if (xsrc < xdst) { xsrc += w; xdst += w; bltctl |= 0x80; cnt |= -(w) & 0xffff; } else { cnt |= w; } srcStart = ysrc * lpitch + xsrc; dstStart = ydst * lpitch + xdst; while(ttin(SSTATUS) & 0x80); ttout(S1SA, srcStart); ttout(SP, sp); ttout(DSA, dstStart); ttout(CNT, cnt); ttout(DP_OCTL, dp_octl); ttout(BLTCTL, bltctl); while(ttin(SSTATUS) & 0x80); while(ttin(SSTATUS) & 0x40); } /* * DoBitbltCopy * * Author: Keith Packard * Modifications: Radoslaw Kapitan */ static void ttDoBitbltCopy (DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask) { BoxPtr pbox; int nbox; BoxPtr pboxTmp, pboxNext, pboxBase, pboxNew1, pboxNew2; /* temporaries for shuffling rectangles */ DDXPointPtr pptTmp, pptNew1, pptNew2; /* shuffling boxes entails shuffling the source points too */ int careful; register int Bpp, lpitch; if (!(pSrc->type == DRAWABLE_WINDOW && pDst->type == DRAWABLE_WINDOW) || !xf86VTSema) { switch (pSrc->bitsPerPixel) { case 8: cfbDoBitbltCopy(pSrc, pDst, alu, prgnDst, pptSrc, planemask); break; case 16: cfb16DoBitbltCopy(pSrc, pDst, alu, prgnDst, pptSrc, planemask); break; #ifdef CONFIG_CFB24 case 24: cfb24DoBitbltCopy(pSrc, pDst, alu, prgnDst, pptSrc, planemask); break; #endif case 32: cfb32DoBitbltCopy(pSrc, pDst, alu, prgnDst, pptSrc, planemask); break; } return; } pbox = REGION_RECTS(prgnDst); nbox = REGION_NUM_RECTS(prgnDst); pboxNew1 = NULL; pptNew1 = NULL; pboxNew2 = NULL; pptNew2 = NULL; /* XXX we have to err on the side of safety when both are windows, * because we don't know if IncludeInferiors is being used. */ careful = ((pSrc == pDst) || ((pSrc->type == DRAWABLE_WINDOW) && (pDst->type == DRAWABLE_WINDOW))); if (careful && (pptSrc->y < pbox->y1)) { if (nbox > 1) { /* keep ordering in each band, reverse order of bands */ pboxNew1 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); if (!pboxNew1) return; pptNew1 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); if (!pptNew1) { DEALLOCATE_LOCAL(pboxNew1); return; } pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox) { while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) pboxNext--; pboxTmp = pboxNext+1; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp <= pboxBase) { *pboxNew1++ = *pboxTmp++; *pptNew1++ = *pptTmp++; } pboxBase = pboxNext; } pboxNew1 -= nbox; pbox = pboxNew1; pptNew1 -= nbox; pptSrc = pptNew1; } } if (careful && (pptSrc->x < pbox->x1)) { if (nbox > 1) { /* reverse order of rects in each band */ pboxNew2 = (BoxPtr)ALLOCATE_LOCAL(sizeof(BoxRec) * nbox); pptNew2 = (DDXPointPtr)ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox); if (!pboxNew2 || !pptNew2) { if (pptNew2) DEALLOCATE_LOCAL(pptNew2); if (pboxNew2) DEALLOCATE_LOCAL(pboxNew2); if (pboxNew1) { DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } return; } pboxBase = pboxNext = pbox; while (pboxBase < pbox+nbox) { while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1)) pboxNext++; pboxTmp = pboxNext; pptTmp = pptSrc + (pboxTmp - pbox); while (pboxTmp != pboxBase) { *pboxNew2++ = *--pboxTmp; *pptNew2++ = *--pptTmp; } pboxBase = pboxNext; } pboxNew2 -= nbox; pbox = pboxNew2; pptNew2 -= nbox; pptSrc = pptNew2; } } Bpp = bytes_per_pixel; lpitch = line_pitch; while (nbox--) { ttBitBlt(Bpp, lpitch, pptSrc->x, pptSrc->y, pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); pbox++; pptSrc++; } /* free up stuff */ if (pboxNew2) { DEALLOCATE_LOCAL(pptNew2); DEALLOCATE_LOCAL(pboxNew2); } if (pboxNew1) { DEALLOCATE_LOCAL(pptNew1); DEALLOCATE_LOCAL(pboxNew1); } } static RegionPtr tt8CopyArea (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { void (*doBitBlt)(); doBitBlt = ttDoBitbltCopy; if (pGC->alu != GXcopy || (pGC->planemask & 0xFF) != 0xFF) { doBitBlt = cfbDoBitbltGeneral; if ((pGC->planemask & 0xFF) == 0xFF) { switch (pGC->alu) { case GXxor: doBitBlt = cfbDoBitbltXor; break; case GXor: doBitBlt = cfbDoBitbltOr; break; } } } return cfbBitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L); } static RegionPtr tt16CopyArea (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { void (*doBitBlt)(); doBitBlt = ttDoBitbltCopy; if (pGC->alu != GXcopy || (pGC->planemask & 0xFFFF) != 0xFFFF) { doBitBlt = cfb16DoBitbltGeneral; if ((pGC->planemask & 0xFFFF) == 0xFFFF) { switch (pGC->alu) { case GXxor: doBitBlt = cfb16DoBitbltXor; break; case GXor: doBitBlt = cfb16DoBitbltOr; break; } } } return cfb16BitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L); } #ifdef CONFIG_CFB24 static RegionPtr tt24CopyArea (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { void (*doBitBlt)(); doBitBlt = ttDoBitbltCopy; if (pGC->alu != GXcopy || (pGC->planemask & 0xFFFFFF) != 0xFFFFFF) { doBitBlt = cfb24DoBitbltGeneral; if ((pGC->planemask & 0xFFFFFF) == 0xFFFFFF) { switch (pGC->alu) { case GXxor: doBitBlt = cfb24DoBitbltXor; break; case GXor: doBitBlt = cfb24DoBitbltOr; break; } } } return cfb24BitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L); } #endif static RegionPtr tt32CopyArea (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { void (*doBitBlt)(); doBitBlt = ttDoBitbltCopy; if (pGC->alu != GXcopy || (pGC->planemask & 0xFFFFFFFF) != 0xFFFFFFFF) { doBitBlt = cfb32DoBitbltGeneral; if ((pGC->planemask & 0xFFFFFFFF) == 0xFFFFFFFF) { switch (pGC->alu) { case GXxor: doBitBlt = cfb32DoBitbltXor; break; case GXor: doBitBlt = cfb32DoBitbltOr; break; } } } return cfb32BitBlt(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L); } extern WindowPtr *WindowTable; static void ttCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { DDXPointPtr pptSrc; register DDXPointPtr ppt; RegionRec rgnDst; register BoxPtr pbox; register int dx, dy; register int i, nbox; WindowPtr pwinRoot; pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; REGION_INIT(pWin->drawable.pScreen, &rgnDst, NullBox, 0); dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); pbox = REGION_RECTS(&rgnDst); nbox = REGION_NUM_RECTS(&rgnDst); if (!nbox || !(pptSrc = (DDXPointPtr) ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) { REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); return; } ppt = pptSrc; for (i = nbox; --i >= 0; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } ttDoBitbltCopy((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, GXcopy, &rgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); } static void ttTileFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { switch (pDrawable->bitsPerPixel) { case 8: cfbPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; case 16: if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) cfb16PolyFillRect(pDrawable, pGC, nrectFill, prectInit); else miPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; #ifdef CONFIG_CFB24 case 24: if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) cfb24PolyFillRect(pDrawable, pGC, nrectFill, prectInit); else miPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; #endif case 32: if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) cfb32PolyFillRect(pDrawable, pGC, nrectFill, prectInit); else miPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; } } static void ttPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { if (pDrawable->type != DRAWABLE_WINDOW || !xf86VTSema) { switch (pDrawable->bitsPerPixel) { case 8: cfbPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; case 16: if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) cfb16PolyFillRect(pDrawable, pGC, nrectFill, prectInit); else miPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; #ifdef CONFIG_CFB24 case 24: if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) cfb24PolyFillRect(pDrawable, pGC, nrectFill, prectInit); else miPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; #endif case 32: if (pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) cfb32PolyFillRect(pDrawable, pGC, nrectFill, prectInit); else miPolyFillRect(pDrawable, pGC, nrectFill, prectInit); break; } return; } /* * Optimize for solid fills */ if ((pGC->fillStyle == FillSolid) || ((pGC->fillStyle == FillOpaqueStippled) && (pGC->fgPixel == pGC->bgPixel))) { int nClipRects; /* Number of clipping rectangles */ BoxPtr pClipRects; /* Current clipping box */ int clipXMin; /* Upper left corner of clip rect */ int clipYMin; /* Upper left corner of clip rect */ int clipXMax; /* Lower right corner of clip rect */ int clipYMax; /* Lower right corner of clip rect */ int drawableXOrg; /* Drawables x origin */ int drawableYOrg; /* Drawables y origin */ cfbPrivGC *priv; int lpitch, Bpp, clr; drawableXOrg = pDrawable->x; drawableYOrg = pDrawable->y; priv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr); nClipRects = REGION_NUM_RECTS(priv->pCompositeClip); pClipRects = REGION_RECTS(priv->pCompositeClip); Bpp = bytes_per_pixel; lpitch = line_pitch; clr = pGC->fgPixel; switch(Bpp) { case 1: clr = clr | (clr << 8) | (clr << 16) | (clr << 24); break; case 2: clr = clr | (clr << 16); break; /* case 3: case 4: */ default: clr = clr; break; } *((unsigned int *)((unsigned long)fbdevRegBase + CLR)) = clr; while(ttin(SSTATUS) & 0x80); ttout(DP_OCTL, lpitch); ttout(SP, lpitch); ttout(BI, 0xffffffff); ttout(MBC, 0xffffffff); while(ttin(SSTATUS) & 0x80); while(ttin(SSTATUS) & 0x40); #if 0 regw(DP_MIX, (mach64alu[pGC->alu] << 16) | MIX_DST); regw(DP_WRITE_MASK, pGC->planemask); #endif for (; nClipRects > 0; nClipRects--, pClipRects++) { xRectangle *pRect; /* current rectangle to fill */ int nRects; /* Number of rectangles to fill */ clipYMin = pClipRects->y1; clipYMax = pClipRects->y2; clipXMin = pClipRects->x1; clipXMax = pClipRects->x2; for (nRects = nrectFill, pRect = prectInit; nRects > 0; nRects--, pRect++) { int rectX1; /* points used to find the width */ int rectX2; /* points used to find the width */ int rectY1; /* points used to find the height */ int rectY2; /* points used to find the height */ int rectWidth; /* Width of the rect to be drawn */ int rectHeight; /* Height of the rect to be drawn */ /* * Clip and translate each rect */ rectX1 = max((pRect->x + drawableXOrg), clipXMin); rectY1 = max((pRect->y + drawableYOrg), clipYMin); rectX2 = min((pRect->x + pRect->width + drawableXOrg), clipXMax); rectY2 = min((pRect->y + pRect->height + drawableYOrg), clipYMax); rectWidth = rectX2 - rectX1; rectHeight = rectY2 - rectY1; if ((rectWidth > 0) && (rectHeight > 0)) { while(ttin(SSTATUS) & 0x80); ttout(DSA, rectY1 * lpitch + rectX1 * Bpp); ttout(S1SA, rectY1 * lpitch + rectX1 * Bpp); ttout(CNT, ((rectHeight - 1) << 16) | (rectWidth * Bpp - 1)); ttout(BLTCTL, 0x840); /* 0x200000 */ while(ttin(SSTATUS) & 0x80); while(ttin(SSTATUS) & 0x40); } } /* end for loop through each rectangle to draw */ } /* end for loop through each clip rectangle */ } else { /* end section to draw solid patterns */ ttTileFillRect(pDrawable, pGC, nrectFill, prectInit); } } void imstt_init (ScreenPtr scr) { int width, Bpp; width = scr->width; Bpp = scr->rootDepth >> 3; switch (Bpp) { case 1: cfbTEOps.CopyArea = tt8CopyArea; cfbNonTEOps.CopyArea = tt8CopyArea; cfbTEOps1Rect.CopyArea = tt8CopyArea; cfbNonTEOps1Rect.CopyArea = tt8CopyArea; cfbTEOps.PolyFillRect = ttPolyFillRect; cfbNonTEOps.PolyFillRect = ttPolyFillRect; cfbTEOps1Rect.PolyFillRect = ttPolyFillRect; cfbNonTEOps1Rect.PolyFillRect = ttPolyFillRect; break; case 2: cfb16TEOps.CopyArea = tt16CopyArea; cfb16NonTEOps.CopyArea = tt16CopyArea; cfb16TEOps1Rect.CopyArea = tt16CopyArea; cfb16NonTEOps1Rect.CopyArea = tt16CopyArea; cfb16TEOps.PolyFillRect = ttPolyFillRect; cfb16NonTEOps.PolyFillRect = ttPolyFillRect; cfb16TEOps1Rect.PolyFillRect = ttPolyFillRect; cfb16NonTEOps1Rect.PolyFillRect = ttPolyFillRect; break; #ifdef CONFIG_CFB24 case 3: cfb24TEOps.CopyArea = tt24CopyArea; cfb24NonTEOps.CopyArea = tt24CopyArea; cfb24TEOps1Rect.CopyArea = tt24CopyArea; cfb24NonTEOps1Rect.CopyArea = tt24CopyArea; cfb24TEOps.PolyFillRect = ttPolyFillRect; cfb24NonTEOps.PolyFillRect = ttPolyFillRect; cfb24TEOps1Rect.PolyFillRect = ttPolyFillRect; cfb24NonTEOps1Rect.PolyFillRect = ttPolyFillRect; break; #endif case 4: cfb32TEOps.CopyArea = tt32CopyArea; cfb32NonTEOps.CopyArea = tt32CopyArea; cfb32TEOps1Rect.CopyArea = tt32CopyArea; cfb32NonTEOps1Rect.CopyArea = tt32CopyArea; cfb32TEOps.PolyFillRect = ttPolyFillRect; cfb32NonTEOps.PolyFillRect = ttPolyFillRect; cfb32TEOps1Rect.PolyFillRect = ttPolyFillRect; cfb32NonTEOps1Rect.PolyFillRect = ttPolyFillRect; break; } bytes_per_pixel = Bpp; line_pitch = width * Bpp; fbdevBitBlt = ttDoBitbltCopy; scr->CopyWindow = ttCopyWindow; }