#ifndef lint static char *rid="$XConsortium: amigaGX.c,v 1.26 94/04/17 20:29:38 kaleb Exp $"; #endif /* lint */ /* Copyright (c) 1991 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. * * Author: Keith Packard, MIT X Consortium */ /* $XFree86: xc/programs/Xserver/hw/xfree68/77c32blt/ncr77c32.c,v 1.1.2.2 1999/05/25 12:00:29 hohndel Exp $ */ #if 0 #if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) #define NAME(subname) ncr77c32##subname #else #define NAME(subname) ncr77c32/**/subname #endif #endif #ifndef PSZ #define PSZ 8 #endif #define MAX_COLORS 256 #if 0 #define GetScreenPrivate(s) ((amigaScreenPtr) ((s)->devPrivates[amigaScreenInd ex].ptr)) #define SetupScreen(s) amigaScreenPtr pPrivate = GetScreenPrivate(s) #endif #include "Xmd.h" #include "gcstruct.h" #include "scrnintstr.h" #include "pixmapstr.h" #include "regionstr.h" #include "mistruct.h" #include "mifillarc.h" #include "fontstruct.h" #include "dixfontstr.h" #include "colormapst.h" #include "cfb/cfb.h" #include "cfb/cfbmskbits.h" #include "cfb/cfb8bit.h" #include "fastblt.h" #include "mergerop.h" #include "../common/xf86.h" #include "ncr77c32.h" #include "migc.h" /* make cfb somewhat more consistent.. */ #define cfb8CopyArea cfbCopyArea #define cfb8BitBlt cfbBitBlt #define cfb8CopyPlane cfbCopyPlane #define cfb8CopyPlane8to1 cfbCopyPlane8to1 #define cfb8PolyGlyphBlt8 cfbPolyGlyphBlt8 #define cfb8NonTEOps cfbNonTEOps #define cfb8ValidateGC cfbValidateGC #define cfb8CopyRotatePixmap cfbCopyRotatePixmap #define cfb8DestroyPixmap cfbDestroyPixmap #define cfb8ReduceRasterOp cfbReduceRasterOp #define cfb8ZeroPolyArcSS8Xor cfbZeroPolyArcSS8Xor #define cfb8ZeroPolyArcSS8Copy cfbZeroPolyArcSS8Copy #define cfb8ZeroPolyArcSS8General cfbZeroPolyArcSS8General #define cfb8LineSS cfbLineSS #define cfb8LineSD cfbLineSD #define cfb8SegmentSS cfbSegmentSS #define cfb8SegmentSD cfbSegmentSD #define cfb8Tile32FSCopy cfbTile32FSCopy #define cfb8Tile32FSGeneral cfbTile32FSGeneral #define cfb8UnnaturalTileFS cfbUnnaturalTileFS #define cfb8UnnaturalStippleFS cfbUnnaturalStippleFS #define cfb8PolyFillRect cfbPolyFillRect #define cfb8PushPixels8 cfbPushPixels8 #define cfb8CreateWindow cfbCreateWindow #define cfb8DestroyWindow cfbDestroyWindow #define cfb8XRotatePixmap cfbXRotatePixmap #define cfb8YRotatePixmap cfbYRotatePixmap #define cfb8CopyRotatePixmap cfbCopyRotatePixmap #define cfb8FillBoxTile32 cfbFillBoxTile32 #define cfb8FillBoxTileOdd cfbFillBoxTileOdd #define cfb8SetSpans cfbSetSpans #define cfb8PutImage cfbPutImage #define cfb8PolyPoint cfbPolyPoint #define cfb8GetTypedWidthAndPointer(pDrawable, width, pointer, wtype, ptype) {\ PixmapPtr _pPix; \ if ((pDrawable)->type != DRAWABLE_PIXMAP) \ _pPix = cfbGetScreenPixmap(pDrawable->pScreen); \ else \ _pPix = (PixmapPtr) (pDrawable); \ (pointer) = (ptype *) _pPix->devPrivate.ptr; \ (width) = ((int) _pPix->devKind) / sizeof (wtype); \ } #define cfb8GetByteWidthAndPointer(pDrawable, width, pointer) \ cfb8GetTypedWidthAndPointer(pDrawable, width, pointer, unsigned char, unsigned char) #define cfb8GetLongWidthAndPointer(pDrawable, width, pointer) \ cfb8GetTypedWidthAndPointer(pDrawable, width, pointer, unsigned long, unsigned long) #define cfb16GetScreenPixmap(s) ((PixmapPtr) (s)->devPrivates[cfb16ScreenPrivateIndex].ptr) #define cfb16GetTypedWidthAndPointer(pDrawable, width, pointer, wtype, ptype) {\ PixmapPtr _pPix; \ if ((pDrawable)->type != DRAWABLE_PIXMAP) \ _pPix = cfb16GetScreenPixmap(pDrawable->pScreen); \ else \ _pPix = (PixmapPtr) (pDrawable); \ (pointer) = (ptype *) _pPix->devPrivate.ptr; \ (width) = ((int) _pPix->devKind) / sizeof (wtype); \ } #define cfb16GetByteWidthAndPointer(pDrawable, width, pointer) \ cfb16GetTypedWidthAndPointer(pDrawable, width, pointer, unsigned char, unsigned char) #define cfb16GetLongWidthAndPointer(pDrawable, width, pointer) \ cfb16GetTypedWidthAndPointer(pDrawable, width, pointer, unsigned long, unsigned long) #define cfb32GetScreenPixmap(s) ((PixmapPtr) (s)->devPrivates[cfb32ScreenPrivateIndex].ptr) #define cfb32GetTypedWidthAndPointer(pDrawable, width, pointer, wtype, ptype) {\ PixmapPtr _pPix; \ if ((pDrawable)->type != DRAWABLE_PIXMAP) \ _pPix = cfb32GetScreenPixmap(pDrawable->pScreen); \ else \ _pPix = (PixmapPtr) (pDrawable); \ (pointer) = (ptype *) _pPix->devPrivate.ptr; \ (width) = ((int) _pPix->devKind) / sizeof (wtype); \ } #define cfb32GetByteWidthAndPointer(pDrawable, width, pointer) \ cfb32GetTypedWidthAndPointer(pDrawable, width, pointer, unsigned char, unsigned char) #define cfb32GetLongWidthAndPointer(pDrawable, width, pointer) \ cfb32GetTypedWidthAndPointer(pDrawable, width, pointer, unsigned long, unsigned long) extern int cfb16ScreenPrivateIndex, cfb32ScreenPrivateIndex; extern void (*fbdevBitBlt)(); extern ScrnInfoRec fbdevInfoRec; extern unsigned long fbdevVirtBase, fbdevRegBase; /* blitter ops works like this: * - there are three input sources to logically combine and form a * result * - these are: source-bitmap (S), pattern-bitmap (P), destination-bitmap (D) * - there are 8 possible combinations of the above 3 and their negated sources * - bit values are ("s" means negated "S"): * 7: PSD 6: PSd 5: PsD 4: Psd 3: pSD 2: pSd 1: psD 0: psd * or as a tree (sort of): * P p * S s S s * D d D d D d D d * - that's how the following tables are built. *******************************************************************/ /* blitting rops: there are two tables each, one ignoring a pattern, * second using pattern as a plane mask */ static Uchar blit_rop_table[16] = { 0x00, /* GXclear */ 0x88, /* GXand */ 0x44, /* GXandReverse */ 0xcc, /* GXcopy */ 0x22, /* GXandInverted */ 0xaa, /* GXnoop */ 0x66, /* GXxor */ 0xee, /* GXor */ 0x11, /* GXnor */ 0x99, /* GXequiv */ 0x55, /* GXinvert */ 0xdd, /* GXorReverse */ 0x33, /* GXcopyInverted */ 0xbb, /* GXorInverted */ 0x77, /* GXnand */ 0xff, /* GXset */ }; static Uchar blit_rop_table_masked[16] = { 0x0A, /* GXclear */ 0x8A, /* GXand */ 0x4A, /* GXandReverse */ 0xcA, /* GXcopy */ 0x2A, /* GXandInverted */ 0xaA, /* GXnoop */ 0x6A, /* GXxor */ 0xeA, /* GXor */ 0x1A, /* GXnor */ 0x9A, /* GXequiv */ 0x5A, /* GXinvert */ 0xdA, /* GXorReverse */ 0x3A, /* GXcopyInverted */ 0xbA, /* GXorInverted */ 0x7A, /* GXnand */ 0xfA, /* GXset */ }; /* rops for drawing stipples. these can only be used with a planemask of all * 1 since the pattern is now used for drawing. We're again using * color-expansion here, use of the transparency-bit decides whether the * operation is "stipple" or "opaque stipple". */ static Uchar stipple_rop_table[16] = { 0x00, /* GXclear */ 0xa0, /* GXand */ 0x50, /* GXandReverse */ 0xf0, /* GXcopy */ 0x0a, /* GXandInverted */ 0xaa, /* GXnoop */ 0x5a, /* GXxor */ 0xfa, /* GXor */ 0x05, /* GXnor */ 0xa5, /* GXequiv */ 0x55, /* GXinvert */ 0xf5, /* GXorReverse */ 0x0f, /* GXcopyInverted */ 0xaf, /* GXorInverted */ 0x5f, /* GXnand */ 0xff, /* GXset */ }; /* those != 0 need the src-register to be setup */ static char optabs[] = { 0, -1, -1, -1, -1, 0, -1, -1, -1, -1, 0, -1, -1, -1, -1, 0 }; int ncr77c32ScreenPrivateIndex; int amigaGXGCPrivateIndex; int amigaGXWindowPrivateIndex; int amigaGXGeneration; #if 0 #define amigaGXFillSpan(acm,inf,y,x1,x2,bpp) \ { VUint *feed = (VUint *) fbdevVirtBase; \ Uint ltmp; \ ltmp = *feed; \ RZ3Blit1toFB(acm,0,0,x1,y,(((x2)-(x1))+1),1,inf->virtualX,bpp,0); \ while ((acm->status & 1) == 0) *feed = ~0; \ *feed = ltmp; } #else static void __inline amigaGXFillSpan(acm, inf, y, x1, x2, bpp) struct ACM *acm; ScrnInfoRec *inf; int y, x1, x2, bpp; { VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; ltmp = *feed; RZ3Blit1toFB(acm,0,0,x1,y,(((x2)-(x1))+1),1,inf->virtualX,bpp,0); while ((acm->status & 1) == 0) *feed = ~0; *feed = ltmp; } #endif /* amigaGXDoBitBlt ============= Bit Blit for all window to window blits. */ void amigaGXDoBitblt(pSrc, pDst, alu, prgnDst, pptSrc, planemask) DrawablePtr pSrc, pDst; int alu; RegionPtr prgnDst; DDXPointPtr pptSrc; unsigned long planemask; { register long r; register BoxPtr pboxTmp; register DDXPointPtr pptTmp; register int nbox; BoxPtr pboxNext,pboxBase,pbox; ScrnInfoPtr inf = amigaInfo(pSrc->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; Uint mask = (1<y < pbox->y1) && (nbox > 1) ){ if( (pptSrc->x < pbox->x1) && (nbox > 1) ){ /* reverse order of bands and rects in each band */ pboxTmp=pbox+nbox; pptTmp=pptSrc+nbox; while (nbox--){ pboxTmp--; pptTmp--; RZ3BlitFB2FB(acm, alu, pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, (pboxTmp->x2 - pboxTmp->x1), (pboxTmp->y2 - pboxTmp->y1), inf->virtualX, bpp); RZ3WaitDone(acm); } } else{ /* keep ordering in each band, reverse order of bands */ pboxBase = pboxNext = pbox+nbox-1; while (pboxBase >= pbox){ /* for each band */ /* find first box in band */ while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) pboxNext--; pboxTmp = pboxNext+1; /* first box in band */ pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */ while (pboxTmp <= pboxBase){ /* for each box in band */ RZ3BlitFB2FB(acm, alu, pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, (pboxTmp->x2 - pboxTmp->x1), (pboxTmp->y2 - pboxTmp->y1), inf->virtualX, bpp); ++pboxTmp; ++pptTmp; RZ3WaitDone(acm); } pboxBase = pboxNext; } } } else{ if( (pptSrc->x < pbox->x1) && (nbox > 1) ){ /* reverse order of rects in each band */ pboxBase = pboxNext = pbox; while (pboxBase < pbox+nbox){ /* for each band */ /* find last box in band */ while ((pboxNext < pbox+nbox) && (pboxNext->y1 == pboxBase->y1)) pboxNext++; pboxTmp = pboxNext; /* last box in band */ pptTmp = pptSrc + (pboxTmp - pbox); /* last point in band */ while (pboxTmp != pboxBase){ /* for each box in band */ --pboxTmp; --pptTmp; RZ3BlitFB2FB(acm, alu, pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, (pboxTmp->x2 - pboxTmp->x1), (pboxTmp->y2 - pboxTmp->y1), inf->virtualX, bpp); RZ3WaitDone(acm); } pboxBase = pboxNext; } } else{ /* dont need to change order of anything */ pptTmp=pptSrc; pboxTmp=pbox; while(nbox--){ RZ3BlitFB2FB(acm, alu, pptTmp->x, pptTmp->y, pboxTmp->x1, pboxTmp->y1, (pboxTmp->x2 - pboxTmp->x1), (pboxTmp->y2 - pboxTmp->y1), inf->virtualX, bpp); ++pboxTmp; ++pptTmp; RZ3WaitDone(acm); } } } } extern RegionPtr cfb8CopyArea(), cfb16CopyArea(), cfb32CopyArea(); extern RegionPtr cfb8CopyPlane(), cfb16CopyPlane(), cfb32CopyPlane(); extern RegionPtr cfb8BitBlt(), cfb16BitBlt(), cfb32BitBlt(); RegionPtr amiga8GXCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty) register DrawablePtr pSrcDrawable; register DrawablePtr pDstDrawable; GC *pGC; int srcx, srcy; int width, height; int dstx, dsty; { __dolog("amiga8GXCopyArea -> %s\n", pSrcDrawable->type != DRAWABLE_WINDOW ? "cfbCopyArea" : "cfbBitBlt"); if (pSrcDrawable->type != DRAWABLE_WINDOW || pDstDrawable->type != DRAWABLE_WINDOW) return cfb8CopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); return cfb8BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, amigaGXDoBitblt, 0); } RegionPtr amiga16GXCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty) register DrawablePtr pSrcDrawable; register DrawablePtr pDstDrawable; GC *pGC; int srcx, srcy; int width, height; int dstx, dsty; { __dolog("amiga16GXCopyArea -> %s\n", pSrcDrawable->type != DRAWABLE_WINDOW ? "cfbCopyArea" : "cfbBitBlt"); if (pSrcDrawable->type != DRAWABLE_WINDOW || pDstDrawable->type != DRAWABLE_WINDOW) return cfb16CopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); return cfb16BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, amigaGXDoBitblt, 0); } RegionPtr amiga24GXCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty) register DrawablePtr pSrcDrawable; register DrawablePtr pDstDrawable; GC *pGC; int srcx, srcy; int width, height; int dstx, dsty; { __dolog("amiga24GXCopyArea -> %s\n", pSrcDrawable->type != DRAWABLE_WINDOW ? "cfbCopyArea" : "cfbBitBlt"); if (pSrcDrawable->type != DRAWABLE_WINDOW && pDstDrawable->type != DRAWABLE_WINDOW) return cfb32CopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); else if (pSrcDrawable->type != DRAWABLE_WINDOW || pDstDrawable->type != DRAWABLE_WINDOW) return miCopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); else return cfb32BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, amigaGXDoBitblt, 0); } static unsigned long copyPlaneFG, copyPlaneBG; static void amigaGXCopyPlane1to8 (pSrcDrawable, pDstDrawable, rop, prgnDst, pptSrc, planemask, bitPlane) DrawablePtr pSrcDrawable; DrawablePtr pDstDrawable; int rop; RegionPtr prgnDst; DDXPointPtr pptSrc; unsigned long planemask; unsigned long bitPlane; { int srcx, srcy, dstx, dsty, width, height; int dstLastx, dstRightx; int xoffSrc, widthSrc, widthRest; int widthLast; unsigned long *psrcBase, *psrcLine, *psrc; unsigned char bits, tmp, lastTmp; register int leftShift, rightShift; register int nl, nlMiddle; int nbox; BoxPtr pbox; register int r; ScrnInfoPtr inf = amigaInfo(pSrcDrawable->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; Uint mask = (1<fg = ltmp; ltmp = copyPlaneBG; M2I(ltmp); acm->bg = ltmp; nbox = REGION_NUM_RECTS(prgnDst); pbox = REGION_RECTS(prgnDst); while (nbox--) { dstx = pbox->x1; dsty = pbox->y1; srcx = pptSrc->x; srcy = pptSrc->y; dstLastx = pbox->x2; width = dstLastx - dstx; height = pbox->y2 - dsty; pbox++; pptSrc++; if (!width) continue; psrc = psrcBase + srcy * widthSrc + (srcx >> 5); __dolog("psrcBase=0x%08x, srcy=%d, srcx=%d, psrc=0x%08x\n", psrcBase, srcy, srcx, psrc); dstLastx--; dstRightx = dstx + 31; nlMiddle = (width + 31) >> 5; widthLast = width & 31; xoffSrc = srcx & 0x1f; leftShift = xoffSrc; rightShift = 32 - leftShift; widthRest = widthSrc - nlMiddle; if (widthLast) nlMiddle--; RZ3Blit1toFB(acm,rop,xoffSrc,dstx,dsty,width,height, inf->virtualX, bpp, 0); __dolog("widthSrc = %d, nlMiddle = %d, widthLast = %d\n", widthSrc, nlMiddle, widthLast); while (height--) { nl = nlMiddle; while (nl--) { if (acm->status & 0x10) while (!(acm->status & 0x04)) ; __dolog("%08x ", *psrc); *feed = *psrc++; } if (widthLast) { if (acm->status & 0x10) while (!(acm->status & 0x04)) ; __dolog("{%08x} ", *psrc); *feed = *psrc++; } __dolog("\n"); psrc += widthRest; } RZ3WaitDone(acm); } } RegionPtr amiga8GXCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane) DrawablePtr pSrcDrawable; DrawablePtr pDstDrawable; GCPtr pGC; int srcx, srcy; int width, height; int dstx, dsty; unsigned long bitPlane; { RegionPtr ret; int (*doBitBlt)(); __dolog("amigaGXCopyPlane: s(%d) -> d(%d), plane = %d\n", pSrcDrawable->bitsPerPixel, pDstDrawable->bitsPerPixel, bitPlane); if (pDstDrawable->type != DRAWABLE_WINDOW) return cfb8CopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 8) { if (bitPlane == 1) { copyPlaneFG = pGC->fgPixel; copyPlaneBG = pGC->bgPixel; ret = cfb8BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, amigaGXCopyPlane1to8, bitPlane); } else ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 1) { extern int InverseAlu[16]; int oldalu; oldalu = pGC->alu; if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1) pGC->alu = InverseAlu[pGC->alu]; else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1)) pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel); ret = cfb8BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, cfb8CopyPlane8to1, bitPlane); pGC->alu = oldalu; } else { PixmapPtr pBitmap; ScreenPtr pScreen = pSrcDrawable->pScreen; GCPtr pGC1; unsigned long fg, bg; pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1); if (!pBitmap) return NULL; pGC1 = GetScratchGC (1, pScreen); if (!pGC1) { (*pScreen->DestroyPixmap) (pBitmap); return NULL; } /* * don't need to set pGC->fgPixel,bgPixel as copyPlane8to1 * ignores pixel values, expecting the rop to "do the * right thing", which GXcopy will. */ ValidateGC ((DrawablePtr) pBitmap, pGC1); /* no exposures here, scratch GC's don't get graphics expose */ (void) cfb8BitBlt (pSrcDrawable, (DrawablePtr) pBitmap, pGC1, srcx, srcy, width, height, 0, 0, cfb8CopyPlane8to1, bitPlane); copyPlaneFG = pGC->fgPixel; copyPlaneBG = pGC->bgPixel; (void) cfb8BitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC, 0, 0, width, height, dstx, dsty, amigaGXCopyPlane1to8, 1); FreeScratchGC (pGC1); (*pScreen->DestroyPixmap) (pBitmap); /* compute resultant exposures */ ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } return ret; } RegionPtr amiga16GXCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane) DrawablePtr pSrcDrawable; DrawablePtr pDstDrawable; GCPtr pGC; int srcx, srcy; int width, height; int dstx, dsty; unsigned long bitPlane; { RegionPtr ret; int (*doBitBlt)(); __dolog("amigaGXCopyPlane: s(%d) -> d(%d), plane = %d\n", pSrcDrawable->bitsPerPixel, pDstDrawable->bitsPerPixel, bitPlane); if (pDstDrawable->type != DRAWABLE_WINDOW) return cfb16CopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 16) { if (bitPlane == 1) { copyPlaneFG = pGC->fgPixel; copyPlaneBG = pGC->bgPixel; ret = cfb16BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, amigaGXCopyPlane1to8, bitPlane); } else ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } else { ret = cfb16CopyPlane (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } return ret; } RegionPtr amiga24GXCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane) DrawablePtr pSrcDrawable; DrawablePtr pDstDrawable; GCPtr pGC; int srcx, srcy; int width, height; int dstx, dsty; unsigned long bitPlane; { RegionPtr ret; int (*doBitBlt)(); __dolog("amigaGXCopyPlane: s(%d) -> d(%d), plane = %d\n", pSrcDrawable->bitsPerPixel, pDstDrawable->bitsPerPixel, bitPlane); if (pSrcDrawable->type != DRAWABLE_WINDOW && pDstDrawable->type != DRAWABLE_WINDOW) return cfb32CopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); else if (pDstDrawable->type != DRAWABLE_WINDOW) return miCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); if (pSrcDrawable->bitsPerPixel == 1) { if (bitPlane == 1) { copyPlaneFG = pGC->fgPixel; copyPlaneBG = pGC->bgPixel; ret = cfb32BitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, amigaGXCopyPlane1to8, bitPlane); } else ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } else { ret = miCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } return ret; } void amigaGXFillRectAll (pDrawable, pGC, nBox, pBox) DrawablePtr pDrawable; GCPtr pGC; int nBox; BoxPtr pBox; { register int r; ScrnInfoRec *inf = amigaInfo(pDrawable->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; /* can't deal with stipple-operations in here since we use the pattern channel to implement the planemasking feature. */ Uint mask = (1<alu, pGC->planemask, pGC->fgPixel, pGC->bgPixel); if ((mask & pGC->planemask) == mask) { /* no masking, simple rop table */ RZ3BlitInit(acm, blit_rop_table, pGC->alu); } else { /* use pattern as mask, and replicate the planemask as many * times as necessary. */ RZ3BlitInit(acm, blit_rop_table_masked, pGC->alu); RZ3MaskInit(acm, fbdevVirtBase, pGC->planemask, bpp); } ltmp = pGC->fgPixel; M2I(ltmp); acm->fg = ltmp; ltmp = pGC->bgPixel; M2I(ltmp); acm->bg = ltmp; /* just to be sure.. */ ltmp = *feed; while (nBox--) { RZ3Blit1toFB(acm, 0, 0, pBox->x1, pBox->y1, (pBox->x2 - pBox->x1), (pBox->y2 - pBox->y1), inf->virtualX, bpp, 0); while ((acm->status & 1) == 0) *feed = ~0; pBox++; } *feed = ltmp; } #define NUM_STACK_RECTS 1024 void amigaGXPolyFillRect(pDrawable, pGC, nrectFill, prectInit) DrawablePtr pDrawable; register GCPtr pGC; int nrectFill; /* number of rectangles to fill */ xRectangle *prectInit; /* Pointer to first rectangle to fill */ { xRectangle *prect; RegionPtr prgnClip; register BoxPtr pbox; register BoxPtr pboxClipped; BoxPtr pboxClippedBase; BoxPtr pextent; BoxRec stackRects[NUM_STACK_RECTS]; cfbPrivGC *priv; int numRects; int n; int xorg, yorg; __dolog("GXPolyFillRect: nrect=%d, alu=0x%02x, planemask=0x%08x, fg=%d, bg=%d=n", nrectFill, pGC->alu, pGC->planemask, pGC->fgPixel, pGC->bgPixel); priv = (cfbPrivGC *) pGC->devPrivates[cfbGCPrivateIndex].ptr; prgnClip = priv->pCompositeClip; prect = prectInit; xorg = pDrawable->x; yorg = pDrawable->y; if (xorg || yorg) { prect = prectInit; n = nrectFill; while(n--) { prect->x += xorg; prect->y += yorg; prect++; } } prect = prectInit; numRects = REGION_NUM_RECTS(prgnClip) * nrectFill; if (numRects > NUM_STACK_RECTS) { pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec)); if (!pboxClippedBase) return; } else pboxClippedBase = stackRects; pboxClipped = pboxClippedBase; if (REGION_NUM_RECTS(prgnClip) == 1) { int x1, y1, x2, y2, bx2, by2; pextent = REGION_RECTS(prgnClip); x1 = pextent->x1; y1 = pextent->y1; x2 = pextent->x2; y2 = pextent->y2; while (nrectFill--) { if ((pboxClipped->x1 = prect->x) < x1) pboxClipped->x1 = x1; if ((pboxClipped->y1 = prect->y) < y1) pboxClipped->y1 = y1; bx2 = (int) prect->x + (int) prect->width; if (bx2 > x2) bx2 = x2; pboxClipped->x2 = bx2; by2 = (int) prect->y + (int) prect->height; if (by2 > y2) by2 = y2; pboxClipped->y2 = by2; prect++; if ((pboxClipped->x1 < pboxClipped->x2) && (pboxClipped->y1 < pboxClipped->y2)) { pboxClipped++; } } } else { int x1, y1, x2, y2, bx2, by2; pextent = REGION_EXTENTS(pGC->pScreen, prgnClip); x1 = pextent->x1; y1 = pextent->y1; x2 = pextent->x2; y2 = pextent->y2; while (nrectFill--) { BoxRec box; if ((box.x1 = prect->x) < x1) box.x1 = x1; if ((box.y1 = prect->y) < y1) box.y1 = y1; bx2 = (int) prect->x + (int) prect->width; if (bx2 > x2) bx2 = x2; box.x2 = bx2; by2 = (int) prect->y + (int) prect->height; if (by2 > y2) by2 = y2; box.y2 = by2; prect++; if ((box.x1 >= box.x2) || (box.y1 >= box.y2)) continue; n = REGION_NUM_RECTS (prgnClip); pbox = REGION_RECTS(prgnClip); /* clip the rectangle to each box in the clip region this is logically equivalent to calling Intersect() */ while(n--) { pboxClipped->x1 = max(box.x1, pbox->x1); pboxClipped->y1 = max(box.y1, pbox->y1); pboxClipped->x2 = min(box.x2, pbox->x2); pboxClipped->y2 = min(box.y2, pbox->y2); pbox++; /* see if clipping left anything */ if(pboxClipped->x1 < pboxClipped->x2 && pboxClipped->y1 < pboxClipped->y2) { pboxClipped++; } } } } if (pboxClipped != pboxClippedBase) amigaGXFillRectAll(pDrawable, pGC, pboxClipped-pboxClippedBase, pboxClippedBase); if (pboxClippedBase != stackRects) DEALLOCATE_LOCAL(pboxClippedBase); } void amigaGXFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted) DrawablePtr pDrawable; GCPtr pGC; int n; /* number of spans to fill */ DDXPointPtr ppt; /* pointer to list of start points */ int *pwidth; /* pointer to list of n widths */ int fSorted; { int x, y; int width; /* next three parameters are post-clip */ int nTmp; int *pwidthFree;/* copies of the pointers to free */ DDXPointPtr pptFree; cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC); register int r; BoxPtr extents; ScrnInfoRec *inf = amigaInfo(pDrawable->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; Uint mask = (1<alu, pGC->planemask, pGC->fgPixel, pGC->bgPixel); /* can't deal with stipple-operations in here since we use the pattern channel to implement the planemasking feature. */ if ((mask & pGC->planemask) == mask) { /* no masking, simple rop table */ RZ3BlitInit(acm, blit_rop_table, pGC->alu); } else { /* use pattern as mask, and replicate the planemask as many * times as necessary. */ RZ3BlitInit(acm, blit_rop_table_masked, pGC->alu); RZ3MaskInit(acm, fbdevVirtBase, pGC->planemask, bpp); } ltmp = pGC->fgPixel; M2I(ltmp); acm->fg = ltmp; ltmp = pGC->bgPixel; M2I(ltmp); acm->bg = ltmp; { nTmp = n * miFindMaxBand(devPriv->pCompositeClip); pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int)); pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec)); if(!pptFree || !pwidthFree) { if (pptFree) DEALLOCATE_LOCAL(pptFree); if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree); return; } n = miClipSpans(devPriv->pCompositeClip, ppt, pwidth, n, pptFree, pwidthFree, fSorted); pwidth = pwidthFree; ppt = pptFree; } while (n--) { x = ppt->x; y = ppt->y; ppt++; width = *pwidth++; if (width) { amigaGXFillSpan(acm,inf,y,x,x + width - 1,bpp); } } { DEALLOCATE_LOCAL(pptFree); DEALLOCATE_LOCAL(pwidthFree); } } #define FILLSPAN(acm,inf,y,x1,x2,bpp,x_off,y_off) {\ if (x2 >= x1) {\ amigaGXFillSpan(acm,inf,(y)+y_off,(x1)+x_off,(x2)+x_off,bpp); \ } \ } #define FILLSLICESPANS(flip,y) \ if (!flip) \ { \ FILLSPAN(acm,inf,y,xl,xr,bpp,x_off,y_off) \ } \ else \ { \ xc = xorg - x; \ FILLSPAN(acm,inf, y, xc, xr, bpp,x_off,y_off) \ xc += slw - 1; \ FILLSPAN(acm,inf, y, xl, xc, bpp,x_off,y_off) \ } #ifdef __STDC__ static void amigaGXFillEllipse (DrawablePtr, struct ACM *, ScrnInfoRec *, int, xArc *, int, int); #endif static void amigaGXFillEllipse (pDraw, acm, inf, bpp, arc, x_off, y_off) DrawablePtr pDraw; struct ACM *acm; ScrnInfoRec *inf; int bpp; xArc *arc; int x_off, y_off; { int x, y, e; int yk, xk, ym, xm, dx, dy, xorg, yorg; int y_top, y_bot; miFillArcRec info; register int xpos; int r; int slw; miFillArcSetup(arc, &info); MIFILLARCSETUP(); y_top = yorg - y; y_bot = yorg + y + dy; while (y) { y_top++; y_bot--; MIFILLARCSTEP(slw); if (!slw) continue; xpos = xorg - x; amigaGXFillSpan (acm,inf,y_top+y_off,xpos+x_off,xpos+x_off+slw - 1,bpp); if (miFillArcLower(slw)) amigaGXFillSpan (acm,inf,y_bot+y_off,xpos+x_off,xpos+x_off+slw - 1,bpp); } } #ifdef __STDC__ static void amigaGXFillArcSlice (DrawablePtr, GCPtr, struct ACM *, ScrnInfoRec *, int, xArc *, int, int); #endif static void amigaGXFillArcSlice (pDraw, pGC, acm, inf, bpp, arc, x_off, y_off) DrawablePtr pDraw; GCPtr pGC; struct ACM *acm; ScrnInfoRec *inf; int bpp; xArc *arc; int x_off, y_off; { int yk, xk, ym, xm, dx, dy, xorg, yorg, slw; register int x, y, e; miFillArcRec info; miArcSliceRec slice; int xl, xr, xc; int y_top, y_bot; int r; miFillArcSetup(arc, &info); miFillArcSliceSetup(arc, &slice, pGC); MIFILLARCSETUP(); y_top = yorg - y; y_bot = yorg + y + dy; while (y > 0) { y_top++; y_bot--; MIFILLARCSTEP(slw); MIARCSLICESTEP(slice.edge1); MIARCSLICESTEP(slice.edge2); if (miFillSliceUpper(slice)) { MIARCSLICEUPPER(xl, xr, slice, slw); FILLSLICESPANS(slice.flip_top, y_top); } if (miFillSliceLower(slice)) { MIARCSLICELOWER(xl, xr, slice, slw); FILLSLICESPANS(slice.flip_bot, y_bot); } } } #define UNSET_CIRCLE void amigaGXPolyFillArc (pDraw, pGC, narcs, parcs) DrawablePtr pDraw; GCPtr pGC; int narcs; xArc *parcs; { register xArc *arc; register int i; int x, y; BoxRec box; BoxPtr extents; RegionPtr cclip; cfbPrivGCPtr devPriv; register int r; ScrnInfoRec *inf = amigaInfo(pDraw->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; Uint mask = (1<planemask) == mask) { /* no masking, simple rop table */ RZ3BlitInit(acm, blit_rop_table, pGC->alu); } else { /* use pattern as mask, and replicate the planemask as many * times as necessary. */ RZ3BlitInit(acm, blit_rop_table_masked, pGC->alu); RZ3MaskInit(acm, fbdevVirtBase, pGC->planemask, bpp); } ltmp = pGC->fgPixel; M2I(ltmp); acm->fg = ltmp; ltmp = pGC->bgPixel; M2I(ltmp); acm->bg = ltmp; devPriv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr); cclip = devPriv->pCompositeClip; x_off = pDraw->x; y_off = pDraw->y; for (arc = parcs, i = narcs; --i >= 0; arc++) { if (miFillArcEmpty(arc)) continue; if (miCanFillArc(arc)) { x = arc->x; y = arc->y; { box.x1 = x + pDraw->x; box.y1 = y + pDraw->y; box.x2 = box.x1 + (int)arc->width + 1; box.y2 = box.y1 + (int)arc->height + 1; } if (RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) { if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) { { amigaGXFillEllipse (pDraw, acm, inf, bpp, arc, x_off, y_off); } } else { amigaGXFillArcSlice (pDraw, pGC, acm, inf, bpp, arc, x_off, y_off); } continue; } } miPolyFillArc(pDraw, pGC, 1, arc); } } static void amigaGXPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) DrawablePtr pDrawable; GCPtr pGC; int x, y; unsigned int nglyph; CharInfoPtr *ppci; /* array of character info */ pointer pglyphBase; { int h; int w; CharInfoPtr pci; unsigned long *bits; register int r; RegionPtr clip; BoxRec box; ScrnInfoRec *inf = amigaInfo(pDrawable->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; int width, height; Uint mask = (1<alu, pGC->planemask, pGC->fgPixel, pGC->bgPixel); /* can't deal with stipple-operations in here since we use the pattern channel to implement the planemasking feature. */ if ((mask & pGC->planemask) == mask) { /* no masking, simple rop table */ RZ3BlitInit(acm, blit_rop_table, pGC->alu); } else { /* use pattern as mask, and replicate the planemask as many * times as necessary. */ RZ3BlitInit(acm, blit_rop_table_masked, pGC->alu); RZ3MaskInit(acm, fbdevVirtBase, pGC->planemask, bpp); } ltmp = pGC->fgPixel; M2I(ltmp); acm->fg = ltmp; ltmp = pGC->bgPixel; M2I(ltmp); acm->bg = ltmp; clip = ((cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip; { /* compute an approximate (but covering) bounding box */ box.x1 = 0; if ((ppci[0]->metrics.leftSideBearing < 0)) box.x1 = ppci[0]->metrics.leftSideBearing; h = nglyph - 1; w = ppci[h]->metrics.rightSideBearing; while (--h >= 0) w += ppci[h]->metrics.characterWidth; box.x2 = w; box.y1 = -FONTMAXBOUNDS(pGC->font,ascent); box.y2 = FONTMAXBOUNDS(pGC->font,descent); box.x1 += pDrawable->x + x; box.x2 += pDrawable->x + x; box.y1 += pDrawable->y + y; box.y2 += pDrawable->y + y; switch (RECT_IN_REGION(pGC->pScreen, clip, &box)) { case rgnPART: if (bpp == 1) cfb8PolyGlyphBlt8 (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); else if (bpp == 2) cfb16PolyGlyphBlt8 (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); else miPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); case rgnOUT: return; } } x += pDrawable->x; y += pDrawable->y; while (nglyph--) { pci = *ppci++; width = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; height = pci->metrics.ascent + pci->metrics.descent; if (width && height && pci->bits) { RZ3Blit1toFB(acm, pGC->alu, 0, (x + pci->metrics.leftSideBearing), (y - pci->metrics.ascent), width, height, inf->virtualX, bpp, 1); h = height; bits = (unsigned long *) pci->bits; while (h--) { *feed = *bits++; } RZ3WaitDone(acm); } x += pci->metrics.characterWidth; } } static void amigaGXTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) DrawablePtr pDrawable; GCPtr pGC; int x, y; unsigned int nglyph; CharInfoPtr *ppci; /* array of character info */ pointer pglyphBase; /* start of array of glyphs */ { int h, hTmp; int w; FontPtr pfont = pGC->font; register int r; unsigned long *char1, *char2, *char3, *char4; int widthGlyphs, widthGlyph; RegionPtr clip; BoxRec bbox; unsigned short rop; ScrnInfoRec *inf = amigaInfo(pDrawable->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; Uint mask = (1<alu, pGC->planemask, pGC->fgPixel, pGC->bgPixel); widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); h = FONTASCENT(pfont) + FONTDESCENT(pfont); clip = ((cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr))->pCompositeClip; { bbox.x1 = x + pDrawable->x; bbox.x2 = bbox.x1 + (widthGlyph * nglyph); bbox.y1 = y + pDrawable->y - FONTASCENT(pfont); bbox.y2 = bbox.y1 + h; switch (RECT_IN_REGION(pGC->pScreen, clip, &bbox)) { case rgnPART: if (pglyphBase) if (bpp == 1) cfb8PolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, NULL); else if (bpp == 2) cfb16PolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, NULL); else miPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, NULL); else miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); case rgnOUT: return; } } rop = pglyphBase ? pGC->alu : GXcopy; if ((mask & pGC->planemask) == mask) { /* no masking, simple rop table */ RZ3BlitInit(acm, blit_rop_table, rop); } else { /* use pattern as mask, and replicate the planemask as many * times as necessary. */ RZ3BlitInit(acm, blit_rop_table_masked, rop); RZ3MaskInit(acm, fbdevVirtBase, pGC->planemask, bpp); } ltmp = pGC->fgPixel; M2I(ltmp); acm->fg = ltmp; ltmp = pGC->bgPixel; M2I(ltmp); acm->bg = ltmp; y = y + pDrawable->y - FONTASCENT(pfont); x += pDrawable->x; /* we start at (x, y), with font data which is (h) high and (widthGlyphs) * wide. */ acm->start = 2; dst = 8 * bpp * (x + y * inf->virtualX); pat = 8 * PAT_MEM_OFF; M2I(pat); acm->pattern = pat; acm->control = 0xc06a; /* RIGHT,DOWN,SRC=M,DST=fb,ColExp,static-pattern */ /* font data is enough aligned */ acm->src = 0; #define LoopIt(count, w, loadup, fetch) \ dimen = (w) | (h << 16); \ M2I(dimen); \ acm->dimension = dimen; \ while (nglyph >= count) \ { \ dstTmp = dst; M2I(dstTmp); \ acm->dst = dstTmp; \ acm->start = 1; \ nglyph -= count; \ loadup \ hTmp = h; \ while (hTmp--) \ *feed = fetch; \ dst += 8 * w * bpp; \ RZ3WaitDone(acm); \ } if (widthGlyph <= 8) { widthGlyphs = widthGlyph << 2; LoopIt(4, widthGlyphs, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits; char3 = (unsigned long *) (*ppci++)->bits; char4 = (unsigned long *) (*ppci++)->bits;, (*char1++ | ((*char2++ | ((*char3++ | (*char4++ >> widthGlyph)) >> widthGlyph)) >> widthGlyph))) } else if (widthGlyph <= 10) { widthGlyphs = (widthGlyph << 1) + widthGlyph; LoopIt(3, widthGlyphs, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits; char3 = (unsigned long *) (*ppci++)->bits;, (*char1++ | ((*char2++ | (*char3++ >> widthGlyph)) >> widthGlyph))) } else if (widthGlyph <= 16) { widthGlyphs = widthGlyph << 1; LoopIt(2, widthGlyphs, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits;, (*char1++ | (*char2++ >> widthGlyph))) } dimen = widthGlyph | (h << 16); M2I(dimen); acm->dimension = dimen; while (nglyph--) { dstTmp = dst; M2I(dstTmp); acm->dst = dstTmp; acm->start = 1; char1 = (unsigned long *) (*ppci++)->bits; hTmp = h; while (hTmp--) *feed = *char1++; dst += 8 * widthGlyph * bpp; RZ3WaitDone(acm); } } static void amigaGXPolyTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) DrawablePtr pDrawable; GCPtr pGC; int x, y; unsigned int nglyph; CharInfoPtr *ppci; /* array of character info */ pointer pglyphBase; /* start of array of glyphs */ { amigaGXTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1); } static void amigaGXFillBoxSolid (pDrawable, nBox, pBox, pixel) DrawablePtr pDrawable; int nBox; BoxPtr pBox; unsigned long pixel; { register int r; ScrnInfoRec *inf = amigaInfo(pDrawable->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); short bpp = fbdevInfoRec.bitsPerPixel >> 3; VUint *feed = (VUint *) fbdevVirtBase; Uint ltmp; __dolog("GXFillBoxSolid: nBox=%d, (%d,%d) - (%d,%d)\n", nBox, pBox->x1, pBox->y1, pBox->x2, pBox->y2); /* no masking, simple rop table */ RZ3BlitInit(acm, blit_rop_table, GXcopy); ltmp = pixel; M2I(ltmp); acm->fg = ltmp; ltmp = *feed; while (nBox--) { RZ3Blit1toFB(acm, 0, 0, pBox->x1, pBox->y1, (pBox->x2 - pBox->x1), (pBox->y2 - pBox->y1), inf->virtualX, bpp, 0); while ((acm->status & 1) == 0) *feed = ~0; pBox++; } *feed = ltmp; } #if 0 void amigaGXFillBoxStipple (pDrawable, nBox, pBox, stipple) DrawablePtr pDrawable; int nBox; BoxPtr pBox; amigaGXStipplePtr stipple; { register amigaGXPtr gx = amigaGXGetScreenPrivate (pDrawable->pScreen); register int r; int patx, paty; patx = 16 - (pDrawable->x & 0xf); paty = 16 - (pDrawable->y & 0xf); stipple->patalign = (patx << 16) | paty; GXDrawInit(gx,0,gx_solid_rop_table[GXcopy]|POLY_N,~0); GXStippleInit(gx, stipple); while (nBox--) { gx->arecty = pBox->y1; gx->arectx = pBox->x1; gx->arecty = pBox->y2; gx->arectx = pBox->x2; pBox++; GXDrawDone(gx,r); } GXWait(gx,r); } amigaGXCheckTile (pPixmap, stipple) PixmapPtr pPixmap; amigaGXStipplePtr stipple; { unsigned short *sbits; unsigned int fg = (unsigned int)~0, bg = (unsigned int)~0; unsigned char *tilebitsLine, *tilebits, tilebit; unsigned short sbit, mask; int nbwidth; int h, w; int x, y; int s_y, s_x; h = pPixmap->drawable.height; if (h > 16 || (h & (h - 1))) return FALSE; w = pPixmap->drawable.width; if (w > 16 || (w & (w - 1))) return FALSE; sbits = (unsigned short *) stipple->bits; tilebitsLine = (unsigned char *) pPixmap->devPrivate.ptr; nbwidth = pPixmap->devKind; for (y = 0; y < h; y++) { tilebits = tilebitsLine; tilebitsLine += nbwidth; sbit = 0; mask = 1 << 15; for (x = 0; x < w; x++) { tilebit = *tilebits++; if (tilebit == fg) sbit |= mask; else if (tilebit != bg) { if (fg == ~0) { fg = tilebit; sbit |= mask; } else if (bg == ~0) { bg = tilebit; } else { return FALSE; } } mask >>= 1; } for (s_x = w; s_x < 16; s_x <<= 1) sbit = sbit | (sbit >> s_x); for (s_y = y; s_y < 16; s_y += h) sbits[s_y] = sbit; } stipple->fore = fg; stipple->back = bg; return TRUE; } amigaGXCheckStipple (pPixmap, stipple) PixmapPtr pPixmap; amigaGXStipplePtr stipple; { unsigned short *sbits; unsigned long *stippleBits; unsigned long sbit, mask; int h, w; int y; int s_y, s_x; h = pPixmap->drawable.height; if (h > 16 || (h & (h - 1))) return FALSE; w = pPixmap->drawable.width; if (w > 16 || (w & (w - 1))) return FALSE; sbits = (unsigned short *) stipple->bits; stippleBits = (unsigned long *) pPixmap->devPrivate.ptr; mask = ((1 << w) - 1) << (16 - w); for (y = 0; y < h; y++) { sbit = (*stippleBits++ >> 16) & mask; for (s_x = w; s_x < 16; s_x <<= 1) sbit = sbit | (sbit >> s_x); for (s_y = y; s_y < 16; s_y += h) sbits[s_y] = sbit; } return TRUE; } /* cache one stipple; figuring out if we can use the stipple is as hard as * computing it, so we just use this one and leave it here if it * can't be used this time */ static amigaGXStipplePtr tmpStipple; amigaGXCheckFill (pGC, pDrawable) GCPtr pGC; DrawablePtr pDrawable; { amigaGXPrivGCPtr gxPriv = amigaGXGetGCPrivate (pGC); amigaGXStipplePtr stipple; Uint alu; int xrot, yrot; if (pGC->fillStyle == FillSolid) { if (gxPriv->stipple) { xfree (gxPriv->stipple); gxPriv->stipple = 0; } return TRUE; } if (!(stipple = gxPriv->stipple)) { if (!tmpStipple) { tmpStipple = (amigaGXStipplePtr) xalloc (sizeof *tmpStipple); if (!tmpStipple) return FALSE; } stipple = tmpStipple; } alu = gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; switch (pGC->fillStyle) { case FillTiled: if (!amigaGXCheckTile (pGC->tile.pixmap, stipple)) { if (gxPriv->stipple) { xfree (gxPriv->stipple); gxPriv->stipple = 0; } return FALSE; } break; case FillStippled: alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; case FillOpaqueStippled: if (!amigaGXCheckStipple (pGC->stipple, stipple)) { if (gxPriv->stipple) { xfree (gxPriv->stipple); gxPriv->stipple = 0; } return FALSE; } stipple->fore = pGC->fgPixel; stipple->back = pGC->bgPixel; break; } xrot = (pGC->patOrg.x + pDrawable->x) & 0xf; yrot = (pGC->patOrg.y + pDrawable->y) & 0xf; /* stipple->patalign = ((16 - (xrot & 0xf)) << 16) | (16 - (yrot & 0xf)); */ xrot = 16 - xrot; yrot = 16 - yrot; stipple->patalign = (xrot << 16) | yrot; stipple->alu = alu; gxPriv->stipple = stipple; if (stipple == tmpStipple) tmpStipple = 0; return TRUE; } #endif void amigaGXValidateGC (); void amigaGXDestroyGC (); void amiga8GXValidateGC (), amiga16GXValidateGC (), amiga24GXValidateGC (); GCFuncs amiga8GXGCFuncs = { amiga8GXValidateGC, miChangeGC, miCopyGC, amigaGXDestroyGC, miChangeClip, miDestroyClip, miCopyClip }; GCFuncs amiga16GXGCFuncs = { amiga16GXValidateGC, miChangeGC, miCopyGC, amigaGXDestroyGC, miChangeClip, miDestroyClip, miCopyClip }; GCFuncs amiga24GXGCFuncs = { amiga24GXValidateGC, miChangeGC, miCopyGC, amigaGXDestroyGC, miChangeClip, miDestroyClip, miCopyClip }; extern void cfb8SetSpans(), cfb16SetSpans(), cfb32SetSpans(); extern void cfb8PutImage(), cfb16PutImage(), cfb32PutImage(); extern void cfb8PolyPoint(), cfb16PolyPoint(), cfb32PolyPoint(); extern void cfb8LineSS(), cfb16LineSS(), cfb32LineSS(); extern void cfb8SegmentSS(), cfb16SegmentSS(), cfb32SegmentSS(); extern void cfb8LineSD(), cfb16LineSD(), cfb32LineSD(); extern void cfb8SegmentSD(), cfb16SegmentSD(), cfb32SegmentSD(); extern void cfb8ZeroPolyArcSS8Copy(), cfb16ZeroPolyArcSSCopy(); extern void cfb8PushPixels8(); extern void cfb8ZeroPolyArcSS8Xor(), cfb16ZeroPolyArcSSXor(); extern void cfb8ZeroPolyArcSS8General(),cfb16ZeroPolyArcSSGeneral(); extern void cfb8Tile32FSCopy(),cfb16Tile32FSCopy(),cfb32Tile32FSCopy(); extern void cfb8Tile32FSGeneral(),cfb16Tile32FSGeneral(),cfb32Tile32FSGeneral(); extern void cfb8UnnaturalTileFS(), cfb16UnnaturalTileFS(), cfb32UnnaturalTileFS(); extern void cfb8Stipple32FS(); extern void cfb8UnnaturalStippleFS(),cfb16UnnaturalStippleFS(),cfb32UnnaturalStippleFS(); extern void cfb8OpaqueStipple32FS(); extern void cfb8UnnaturalStippleFS(),cfb16UnnaturalStippleFS(),cfb32UnnaturalStippleFS(); extern void cfb8PolyFillRect(),cfb16PolyFillRect(); void amiga24GXSetSpans(), amiga24GXGetSpans(), amiga24GXGetImage(); void amiga24GXResolveColor(); Bool amiga24GXInitializeColormap(); GCOps amiga8GXTEOps = { amigaGXFillSpans, cfb8SetSpans, cfb8PutImage, amiga8GXCopyArea, amiga8GXCopyPlane, cfb8PolyPoint, cfb8LineSS, cfb8SegmentSS, miPolyRectangle, cfb8ZeroPolyArcSS8Copy, miFillPolygon, amigaGXPolyFillRect, amigaGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, amigaGXTEGlyphBlt, amigaGXPolyTEGlyphBlt, cfb8PushPixels8 #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps amiga8GXNonTEOps = { amigaGXFillSpans, cfb8SetSpans, cfb8PutImage, amiga8GXCopyArea, amiga8GXCopyPlane, cfb8PolyPoint, cfb8LineSS, cfb8SegmentSS, miPolyRectangle, cfb8ZeroPolyArcSS8Copy, miFillPolygon, amigaGXPolyFillRect, amigaGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, miImageGlyphBlt, amigaGXPolyGlyphBlt, cfb8PushPixels8 #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps amiga16GXTEOps = { amigaGXFillSpans, cfb16SetSpans, cfb16PutImage, amiga16GXCopyArea, amiga16GXCopyPlane, cfb16PolyPoint, cfb16LineSS, cfb16SegmentSS, miPolyRectangle, cfb16ZeroPolyArcSSCopy, miFillPolygon, amigaGXPolyFillRect, amigaGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, amigaGXTEGlyphBlt, amigaGXPolyTEGlyphBlt, mfbPushPixels #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps amiga16GXNonTEOps = { amigaGXFillSpans, cfb16SetSpans, cfb16PutImage, amiga16GXCopyArea, amiga16GXCopyPlane, cfb16PolyPoint, cfb16LineSS, cfb16SegmentSS, miPolyRectangle, cfb16ZeroPolyArcSSCopy, miFillPolygon, amigaGXPolyFillRect, amigaGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, miImageGlyphBlt, amigaGXPolyGlyphBlt, mfbPushPixels #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps amiga24GXTEOps = { amigaGXFillSpans, amiga24GXSetSpans, miPutImage, amiga24GXCopyArea, amiga24GXCopyPlane, miPolyPoint, miZeroLine, miPolySegment, miPolyRectangle, miZeroPolyArc, miFillPolygon, amigaGXPolyFillRect, amigaGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, amigaGXTEGlyphBlt, amigaGXPolyTEGlyphBlt, mfbPushPixels #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps amiga24GXNonTEOps = { amigaGXFillSpans, amiga24GXSetSpans, miPutImage, amiga24GXCopyArea, amiga24GXCopyPlane, miPolyPoint, miZeroLine, miPolySegment, miPolyRectangle, miZeroPolyArc, miFillPolygon, amigaGXPolyFillRect, amigaGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, miImageGlyphBlt, amigaGXPolyGlyphBlt, mfbPushPixels #ifdef NEED_LINEHELPER ,NULL #endif }; #define FONTWIDTH(font) (FONTMAXBOUNDS(font,rightSideBearing) - \ FONTMINBOUNDS(font,leftSideBearing)) GCOps * amigaGXMatchCommon (pGC, devPriv, bpp) GCPtr pGC; cfbPrivGCPtr devPriv; int bpp; { if (pGC->lineWidth != 0) return 0; if (pGC->lineStyle != LineSolid) return 0; if (pGC->fillStyle != FillSolid) return 0; if (devPriv->rop != GXcopy) return 0; if (pGC->font && FONTWIDTH (pGC->font) <= 32 && FONTMINBOUNDS(pGC->font,characterWidth) >= 0) { if (bpp == 8) { if (TERMINALFONT(pGC->font)) return &amiga8GXTEOps; else return &amiga8GXNonTEOps; } else if (bpp == 16) { if (TERMINALFONT(pGC->font)) return &amiga16GXTEOps; else return &amiga16GXNonTEOps; } else { if (TERMINALFONT(pGC->font)) return &amiga24GXTEOps; else return &amiga24GXNonTEOps; } } return 0; } void amiga8GXValidateGC (pGC, changes, pDrawable, bpp) GCPtr pGC; Mask changes; DrawablePtr pDrawable; { int mask; /* stateChanges */ int index; /* used for stepping through bitfields */ int new_rrop; int new_line, new_text, new_fillspans, new_fillarea; int new_rotate; int xrot, yrot; /* flags for changing the proc vector */ cfbPrivGCPtr devPriv; amigaGXPrivGCPtr gxPriv; int oneRect; int canGX; gxPriv = amigaGXGetGCPrivate (pGC); if (pDrawable->type != DRAWABLE_WINDOW) { if (gxPriv->type == DRAWABLE_WINDOW) { extern GCOps cfb8NonTEOps; miDestroyGCOps (pGC->ops); pGC->ops = &cfb8NonTEOps; changes = (1 << GCLastBit+1) - 1; pGC->stateChanges = changes; gxPriv->type = pDrawable->type; } cfb8ValidateGC (pGC, changes, pDrawable); return; } if (gxPriv->type != DRAWABLE_WINDOW) { changes = (1 << GCLastBit+1) - 1; gxPriv->type = DRAWABLE_WINDOW; } new_rotate = pGC->lastWinOrg.x != pDrawable->x || pGC->lastWinOrg.y != pDrawable->y; pGC->lastWinOrg.x = pDrawable->x; pGC->lastWinOrg.y = pDrawable->y; devPriv = ((cfbPrivGCPtr) (pGC->devPrivates[cfbGCPrivateIndex].ptr)); new_rrop = FALSE; new_line = FALSE; new_text = FALSE; new_fillspans = FALSE; new_fillarea = FALSE; /* * if the client clip is different or moved OR the subwindowMode has * changed OR the window's clip has changed since the last validation * we need to recompute the composite clip */ if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) ) { miComputeCompositeClip(pGC, pDrawable); #if 0 oneRect = REGION_NUM_RECTS(devPriv->pCompositeClip) == 1; if (oneRect != devPriv->oneRect) { new_line = TRUE; new_fillarea = TRUE; devPriv->oneRect = oneRect; } #endif } mask = changes; while (mask) { index = lowbit (mask); mask &= ~index; /* * this switch acculmulates a list of which procedures might have * to change due to changes in the GC. in some cases (e.g. * changing one 16 bit tile for another) we might not really need * a change, but the code is being paranoid. this sort of batching * wins if, for example, the alu and the font have been changed, * or any other pair of items that both change the same thing. */ switch (index) { case GCFunction: case GCForeground: new_rrop = TRUE; break; case GCPlaneMask: new_rrop = TRUE; new_text = TRUE; break; case GCBackground: break; case GCLineStyle: case GCLineWidth: new_line = TRUE; break; case GCCapStyle: break; case GCJoinStyle: break; case GCFillStyle: new_text = TRUE; new_fillspans = TRUE; new_line = TRUE; new_fillarea = TRUE; break; case GCFillRule: break; case GCTile: new_fillspans = TRUE; new_fillarea = TRUE; break; case GCStipple: new_fillspans = TRUE; new_fillarea = TRUE; break; case GCTileStipXOrigin: new_rotate = TRUE; break; case GCTileStipYOrigin: new_rotate = TRUE; break; case GCFont: new_text = TRUE; break; case GCSubwindowMode: break; case GCGraphicsExposures: break; case GCClipXOrigin: break; case GCClipYOrigin: break; case GCClipMask: break; case GCDashOffset: break; case GCDashList: break; case GCArcMode: break; default: break; } } /* * If the drawable has changed, check its depth & ensure suitable * entries are in the proc vector. */ if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) { new_fillspans = TRUE; /* deal with FillSpans later */ } if ((new_rotate || new_fillspans)) { Bool new_pix = FALSE; xrot = pGC->patOrg.x + pDrawable->x; yrot = pGC->patOrg.y + pDrawable->y; #if 0 if (!amigaGXCheckFill (pGC, pDrawable)) #endif { switch (pGC->fillStyle) { case FillTiled: if (!pGC->tileIsPixel) { int width = pGC->tile.pixmap->drawable.width * PSZ; if ((width <= 32) && !(width & (width - 1))) { cfb8CopyRotatePixmap(pGC->tile.pixmap, &devPriv->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } } break; case FillStippled: case FillOpaqueStippled: { int width = pGC->stipple->drawable.width; if ((width <= 32) && !(width & (width - 1))) { mfbCopyRotatePixmap(pGC->stipple, &devPriv->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } } break; } } if (!new_pix && devPriv->pRotatedPixmap) { cfb8DestroyPixmap(devPriv->pRotatedPixmap); devPriv->pRotatedPixmap = (PixmapPtr) NULL; } } if (new_rrop) { int old_rrop; #if 0 if (gxPriv->stipple) { if (pGC->fillStyle == FillStippled) gxPriv->stipple->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; else gxPriv->stipple->alu = gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; if (pGC->fillStyle != FillTiled) { gxPriv->stipple->fore = pGC->fgPixel; gxPriv->stipple->back = pGC->bgPixel; } } #endif old_rrop = devPriv->rop; devPriv->rop = cfb8ReduceRasterOp (pGC->alu, pGC->fgPixel, pGC->planemask, &devPriv->and, &devPriv->xor); if (old_rrop == devPriv->rop) new_rrop = FALSE; else { new_line = TRUE; new_text = TRUE; new_fillspans = TRUE; new_fillarea = TRUE; } } if (new_rrop || new_fillspans || new_text || new_fillarea || new_line) { GCOps *newops; if (newops = amigaGXMatchCommon (pGC, devPriv, 8)) { if (pGC->ops->devPrivate.val) miDestroyGCOps (pGC->ops); pGC->ops = newops; new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0; } else { if (!pGC->ops->devPrivate.val) { pGC->ops = miCreateGCOps (pGC->ops); pGC->ops->devPrivate.val = 1; } } } canGX = pGC->fillStyle == FillSolid /*|| gxPriv->stipple*/; /* deal with the changes we've collected */ if (new_line) { pGC->ops->FillPolygon = miFillPolygon; if (pGC->lineWidth == 0) { if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)) { switch (devPriv->rop) { case GXxor: pGC->ops->PolyArc = cfb8ZeroPolyArcSS8Xor; break; case GXcopy: pGC->ops->PolyArc = cfb8ZeroPolyArcSS8Copy; break; default: pGC->ops->PolyArc = cfb8ZeroPolyArcSS8General; break; } } else pGC->ops->PolyArc = miZeroPolyArc; } else pGC->ops->PolyArc = miPolyArc; pGC->ops->PolySegment = miPolySegment; switch (pGC->lineStyle) { case LineSolid: if(pGC->lineWidth == 0) { if (pGC->fillStyle == FillSolid) { pGC->ops->Polylines = cfb8LineSS; pGC->ops->PolySegment = cfb8SegmentSS; } else pGC->ops->Polylines = miZeroLine; } else pGC->ops->Polylines = miWideLine; break; case LineOnOffDash: case LineDoubleDash: if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) { pGC->ops->Polylines = cfb8LineSD; pGC->ops->PolySegment = cfb8SegmentSD; } else pGC->ops->Polylines = miWideDash; break; } } if (new_text && (pGC->font)) { if (FONTWIDTH(pGC->font) > 32 || FONTMINBOUNDS(pGC->font,characterWidth) < 0) { pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } else { if (pGC->fillStyle == FillSolid) { if (TERMINALFONT (pGC->font)) pGC->ops->PolyGlyphBlt = amigaGXPolyTEGlyphBlt; else pGC->ops->PolyGlyphBlt = amigaGXPolyGlyphBlt; } else pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; /* special case ImageGlyphBlt for terminal emulator fonts */ if (TERMINALFONT(pGC->font)) pGC->ops->ImageGlyphBlt = amigaGXTEGlyphBlt; else pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } } if (new_fillspans) { if (canGX) pGC->ops->FillSpans = amigaGXFillSpans; else switch (pGC->fillStyle) { case FillTiled: if (devPriv->pRotatedPixmap) { if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK) pGC->ops->FillSpans = cfb8Tile32FSCopy; else pGC->ops->FillSpans = cfb8Tile32FSGeneral; } else pGC->ops->FillSpans = cfb8UnnaturalTileFS; break; case FillStippled: if (devPriv->pRotatedPixmap) pGC->ops->FillSpans = cfb8Stipple32FS; else pGC->ops->FillSpans = cfb8UnnaturalStippleFS; break; case FillOpaqueStippled: if (devPriv->pRotatedPixmap) pGC->ops->FillSpans = cfb8OpaqueStipple32FS; else pGC->ops->FillSpans = cfb8UnnaturalStippleFS; break; default: FatalError("cfb8ValidateGC: illegal fillStyle\n"); } } /* end of new_fillspans */ if (new_fillarea) { pGC->ops->PolyFillRect = cfb8PolyFillRect; pGC->ops->PolyFillArc = miPolyFillArc; if (canGX) { pGC->ops->PolyFillArc = amigaGXPolyFillArc; pGC->ops->PolyFillRect = amigaGXPolyFillRect; } pGC->ops->PushPixels = mfbPushPixels; if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy) pGC->ops->PushPixels = cfb8PushPixels8; } } void amiga16GXValidateGC (pGC, changes, pDrawable, bpp) GCPtr pGC; Mask changes; DrawablePtr pDrawable; { int mask; /* stateChanges */ int index; /* used for stepping through bitfields */ int new_rrop; int new_line, new_text, new_fillspans, new_fillarea; int new_rotate; int xrot, yrot; /* flags for changing the proc vector */ cfbPrivGCPtr devPriv; amigaGXPrivGCPtr gxPriv; int oneRect; int canGX; gxPriv = amigaGXGetGCPrivate (pGC); if (pDrawable->type != DRAWABLE_WINDOW) { if (gxPriv->type == DRAWABLE_WINDOW) { extern GCOps cfb16NonTEOps; miDestroyGCOps (pGC->ops); pGC->ops = &cfb16NonTEOps; changes = (1 << GCLastBit+1) - 1; pGC->stateChanges = changes; gxPriv->type = pDrawable->type; } cfb16ValidateGC (pGC, changes, pDrawable); return; } if (gxPriv->type != DRAWABLE_WINDOW) { changes = (1 << GCLastBit+1) - 1; gxPriv->type = DRAWABLE_WINDOW; } new_rotate = pGC->lastWinOrg.x != pDrawable->x || pGC->lastWinOrg.y != pDrawable->y; pGC->lastWinOrg.x = pDrawable->x; pGC->lastWinOrg.y = pDrawable->y; devPriv = ((cfbPrivGCPtr) (pGC->devPrivates[cfbGCPrivateIndex].ptr)); new_rrop = FALSE; new_line = FALSE; new_text = FALSE; new_fillspans = FALSE; new_fillarea = FALSE; /* * if the client clip is different or moved OR the subwindowMode has * changed OR the window's clip has changed since the last validation * we need to recompute the composite clip */ if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) ) { miComputeCompositeClip(pGC, pDrawable); #if 0 oneRect = REGION_NUM_RECTS(devPriv->pCompositeClip) == 1; if (oneRect != devPriv->oneRect) { new_line = TRUE; new_fillarea = TRUE; devPriv->oneRect = oneRect; } #endif } mask = changes; while (mask) { index = lowbit (mask); mask &= ~index; /* * this switch acculmulates a list of which procedures might have * to change due to changes in the GC. in some cases (e.g. * changing one 16 bit tile for another) we might not really need * a change, but the code is being paranoid. this sort of batching * wins if, for example, the alu and the font have been changed, * or any other pair of items that both change the same thing. */ switch (index) { case GCFunction: case GCForeground: new_rrop = TRUE; break; case GCPlaneMask: new_rrop = TRUE; new_text = TRUE; break; case GCBackground: break; case GCLineStyle: case GCLineWidth: new_line = TRUE; break; case GCCapStyle: break; case GCJoinStyle: break; case GCFillStyle: new_text = TRUE; new_fillspans = TRUE; new_line = TRUE; new_fillarea = TRUE; break; case GCFillRule: break; case GCTile: new_fillspans = TRUE; new_fillarea = TRUE; break; case GCStipple: new_fillspans = TRUE; new_fillarea = TRUE; break; case GCTileStipXOrigin: new_rotate = TRUE; break; case GCTileStipYOrigin: new_rotate = TRUE; break; case GCFont: new_text = TRUE; break; case GCSubwindowMode: break; case GCGraphicsExposures: break; case GCClipXOrigin: break; case GCClipYOrigin: break; case GCClipMask: break; case GCDashOffset: break; case GCDashList: break; case GCArcMode: break; default: break; } } /* * If the drawable has changed, check its depth & ensure suitable * entries are in the proc vector. */ if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) { new_fillspans = TRUE; /* deal with FillSpans later */ } if ((new_rotate || new_fillspans)) { Bool new_pix = FALSE; xrot = pGC->patOrg.x + pDrawable->x; yrot = pGC->patOrg.y + pDrawable->y; #if 0 if (!amigaGXCheckFill (pGC, pDrawable)) #endif { switch (pGC->fillStyle) { case FillTiled: if (!pGC->tileIsPixel) { int width = pGC->tile.pixmap->drawable.width * PSZ; if ((width <= 32) && !(width & (width - 1))) { cfb16CopyRotatePixmap(pGC->tile.pixmap, &devPriv->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } } break; case FillStippled: case FillOpaqueStippled: { int width = pGC->stipple->drawable.width; if ((width <= 32) && !(width & (width - 1))) { mfbCopyRotatePixmap(pGC->stipple, &devPriv->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } } break; } } if (!new_pix && devPriv->pRotatedPixmap) { cfb16DestroyPixmap(devPriv->pRotatedPixmap); devPriv->pRotatedPixmap = (PixmapPtr) NULL; } } if (new_rrop) { int old_rrop; #if 0 if (gxPriv->stipple) { if (pGC->fillStyle == FillStippled) gxPriv->stipple->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; else gxPriv->stipple->alu = gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; if (pGC->fillStyle != FillTiled) { gxPriv->stipple->fore = pGC->fgPixel; gxPriv->stipple->back = pGC->bgPixel; } } #endif old_rrop = devPriv->rop; devPriv->rop = cfb16ReduceRasterOp (pGC->alu, pGC->fgPixel, pGC->planemask, &devPriv->and, &devPriv->xor); if (old_rrop == devPriv->rop) new_rrop = FALSE; else { new_line = TRUE; new_text = TRUE; new_fillspans = TRUE; new_fillarea = TRUE; } } if (new_rrop || new_fillspans || new_text || new_fillarea || new_line) { GCOps *newops; if (newops = amigaGXMatchCommon (pGC, devPriv, 16)) { if (pGC->ops->devPrivate.val) miDestroyGCOps (pGC->ops); pGC->ops = newops; new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0; } else { if (!pGC->ops->devPrivate.val) { pGC->ops = miCreateGCOps (pGC->ops); pGC->ops->devPrivate.val = 1; } } } canGX = pGC->fillStyle == FillSolid /*|| gxPriv->stipple*/; /* deal with the changes we've collected */ if (new_line) { pGC->ops->FillPolygon = miFillPolygon; if (pGC->lineWidth == 0) { if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)) { switch (devPriv->rop) { case GXxor: pGC->ops->PolyArc = cfb16ZeroPolyArcSSXor; break; case GXcopy: pGC->ops->PolyArc = cfb16ZeroPolyArcSSCopy; break; default: pGC->ops->PolyArc = cfb16ZeroPolyArcSSGeneral; break; } } else pGC->ops->PolyArc = miZeroPolyArc; } else pGC->ops->PolyArc = miPolyArc; pGC->ops->PolySegment = miPolySegment; switch (pGC->lineStyle) { case LineSolid: if(pGC->lineWidth == 0) { if (pGC->fillStyle == FillSolid) { pGC->ops->Polylines = cfb16LineSS; pGC->ops->PolySegment = cfb16SegmentSS; } else pGC->ops->Polylines = miZeroLine; } else pGC->ops->Polylines = miWideLine; break; case LineOnOffDash: case LineDoubleDash: if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) { pGC->ops->Polylines = cfb16LineSD; pGC->ops->PolySegment = cfb16SegmentSD; } else pGC->ops->Polylines = miWideDash; break; } } if (new_text && (pGC->font)) { if (FONTWIDTH(pGC->font) > 32 || FONTMINBOUNDS(pGC->font,characterWidth) < 0) { pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } else { if (pGC->fillStyle == FillSolid) { if (TERMINALFONT (pGC->font)) pGC->ops->PolyGlyphBlt = amigaGXPolyTEGlyphBlt; else pGC->ops->PolyGlyphBlt = amigaGXPolyGlyphBlt; } else pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; /* special case ImageGlyphBlt for terminal emulator fonts */ if (TERMINALFONT(pGC->font)) pGC->ops->ImageGlyphBlt = amigaGXTEGlyphBlt; else pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } } if (new_fillspans) { if (canGX) pGC->ops->FillSpans = amigaGXFillSpans; else switch (pGC->fillStyle) { case FillTiled: if (devPriv->pRotatedPixmap) { if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK) pGC->ops->FillSpans = cfb16Tile32FSCopy; else pGC->ops->FillSpans = cfb16Tile32FSGeneral; } else pGC->ops->FillSpans = cfb16UnnaturalTileFS; break; case FillStippled: pGC->ops->FillSpans = cfb16UnnaturalStippleFS; break; case FillOpaqueStippled: pGC->ops->FillSpans = cfb16UnnaturalStippleFS; break; default: FatalError("cfb16ValidateGC: illegal fillStyle\n"); } } /* end of new_fillspans */ if (new_fillarea) { pGC->ops->PolyFillRect = cfb16PolyFillRect; pGC->ops->PolyFillArc = miPolyFillArc; if (canGX) { pGC->ops->PolyFillArc = amigaGXPolyFillArc; pGC->ops->PolyFillRect = amigaGXPolyFillRect; } pGC->ops->PushPixels = mfbPushPixels; if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy) pGC->ops->PushPixels = mfbPushPixels; } } void amiga24GXValidateGC (pGC, changes, pDrawable, bpp) GCPtr pGC; Mask changes; DrawablePtr pDrawable; { int mask; /* stateChanges */ int index; /* used for stepping through bitfields */ int new_rrop; int new_line, new_text, new_fillspans, new_fillarea; int new_rotate; int xrot, yrot; /* flags for changing the proc vector */ cfbPrivGCPtr devPriv; amigaGXPrivGCPtr gxPriv; int oneRect; int canGX; gxPriv = amigaGXGetGCPrivate (pGC); if (pDrawable->type != DRAWABLE_WINDOW) { if (gxPriv->type == DRAWABLE_WINDOW) { extern GCOps cfb32NonTEOps; miDestroyGCOps (pGC->ops); pGC->ops = &cfb32NonTEOps; changes = (1 << GCLastBit+1) - 1; pGC->stateChanges = changes; gxPriv->type = pDrawable->type; } cfb32ValidateGC (pGC, changes, pDrawable); return; } /* starting here, we're ONLY dealing with FRAMEBUFFER manipulation, * so *no* cfb32 calls on the drawable are permitted! ******************************************************************/ if (gxPriv->type != DRAWABLE_WINDOW) { changes = (1 << GCLastBit+1) - 1; gxPriv->type = DRAWABLE_WINDOW; } new_rotate = pGC->lastWinOrg.x != pDrawable->x || pGC->lastWinOrg.y != pDrawable->y; pGC->lastWinOrg.x = pDrawable->x; pGC->lastWinOrg.y = pDrawable->y; devPriv = ((cfbPrivGCPtr) (pGC->devPrivates[cfbGCPrivateIndex].ptr)); new_rrop = FALSE; new_line = FALSE; new_text = FALSE; new_fillspans = FALSE; new_fillarea = FALSE; /* * if the client clip is different or moved OR the subwindowMode has * changed OR the window's clip has changed since the last validation * we need to recompute the composite clip */ if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) || (pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS)) ) { miComputeCompositeClip(pGC, pDrawable); #if 0 oneRect = REGION_NUM_RECTS(devPriv->pCompositeClip) == 1; if (oneRect != devPriv->oneRect) { new_line = TRUE; new_fillarea = TRUE; devPriv->oneRect = oneRect; } #endif } mask = changes; while (mask) { index = lowbit (mask); mask &= ~index; /* * this switch acculmulates a list of which procedures might have * to change due to changes in the GC. in some cases (e.g. * changing one 16 bit tile for another) we might not really need * a change, but the code is being paranoid. this sort of batching * wins if, for example, the alu and the font have been changed, * or any other pair of items that both change the same thing. */ switch (index) { case GCFunction: case GCForeground: new_rrop = TRUE; break; case GCPlaneMask: new_rrop = TRUE; new_text = TRUE; break; case GCBackground: break; case GCLineStyle: case GCLineWidth: new_line = TRUE; break; case GCCapStyle: break; case GCJoinStyle: break; case GCFillStyle: new_text = TRUE; new_fillspans = TRUE; new_line = TRUE; new_fillarea = TRUE; break; case GCFillRule: break; case GCTile: new_fillspans = TRUE; new_fillarea = TRUE; break; case GCStipple: new_fillspans = TRUE; new_fillarea = TRUE; break; case GCTileStipXOrigin: new_rotate = TRUE; break; case GCTileStipYOrigin: new_rotate = TRUE; break; case GCFont: new_text = TRUE; break; case GCSubwindowMode: break; case GCGraphicsExposures: break; case GCClipXOrigin: break; case GCClipYOrigin: break; case GCClipMask: break; case GCDashOffset: break; case GCDashList: break; case GCArcMode: break; default: break; } } /* * If the drawable has changed, check its depth & ensure suitable * entries are in the proc vector. */ if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) { new_fillspans = TRUE; /* deal with FillSpans later */ } if ((new_rotate || new_fillspans)) { Bool new_pix = FALSE; xrot = pGC->patOrg.x + pDrawable->x; yrot = pGC->patOrg.y + pDrawable->y; #if 0 if (!amigaGXCheckFill (pGC, pDrawable)) #endif { switch (pGC->fillStyle) { case FillTiled: if (!pGC->tileIsPixel) { int width = pGC->tile.pixmap->drawable.width * PSZ; if ((width <= 32) && !(width & (width - 1))) { /* cfb32 on tile, not drawable */ cfb32CopyRotatePixmap(pGC->tile.pixmap, &devPriv->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } } break; case FillStippled: case FillOpaqueStippled: { int width = pGC->stipple->drawable.width; if ((width <= 32) && !(width & (width - 1))) { mfbCopyRotatePixmap(pGC->stipple, &devPriv->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } } break; } } if (!new_pix && devPriv->pRotatedPixmap) { cfb32DestroyPixmap(devPriv->pRotatedPixmap); devPriv->pRotatedPixmap = (PixmapPtr) NULL; } } if (new_rrop) { int old_rrop; #if 0 if (gxPriv->stipple) { if (pGC->fillStyle == FillStippled) gxPriv->stipple->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; else gxPriv->stipple->alu = gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; if (pGC->fillStyle != FillTiled) { gxPriv->stipple->fore = pGC->fgPixel; gxPriv->stipple->back = pGC->bgPixel; } } #endif old_rrop = devPriv->rop; devPriv->rop = cfb32ReduceRasterOp (pGC->alu, pGC->fgPixel, pGC->planemask, &devPriv->and, &devPriv->xor); if (old_rrop == devPriv->rop) new_rrop = FALSE; else { new_line = TRUE; new_text = TRUE; new_fillspans = TRUE; new_fillarea = TRUE; } } if (new_rrop || new_fillspans || new_text || new_fillarea || new_line) { GCOps *newops; if (newops = amigaGXMatchCommon (pGC, devPriv, 24)) { if (pGC->ops->devPrivate.val) miDestroyGCOps (pGC->ops); pGC->ops = newops; new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0; } else { if (!pGC->ops->devPrivate.val) { pGC->ops = miCreateGCOps (pGC->ops); pGC->ops->devPrivate.val = 1; } } } canGX = pGC->fillStyle == FillSolid /*|| gxPriv->stipple*/; /* deal with the changes we've collected */ if (new_line) { pGC->ops->FillPolygon = miFillPolygon; if (pGC->lineWidth == 0) pGC->ops->PolyArc = miZeroPolyArc; else pGC->ops->PolyArc = miPolyArc; pGC->ops->PolySegment = miPolySegment; switch (pGC->lineStyle) { case LineSolid: #if 0 if(pGC->lineWidth == 0) { if (pGC->fillStyle == FillSolid) { pGC->ops->Polylines = cfb32LineSS; pGC->ops->PolySegment = cfb32SegmentSS; } else pGC->ops->Polylines = miZeroLine; } else pGC->ops->Polylines = miWideLine; #else if (pGC->lineWidth == 0 && pGC->fillStyle != FillSolid) pGC->ops->Polylines = miZeroLine; else pGC->ops->Polylines = miWideLine; #endif break; case LineOnOffDash: case LineDoubleDash: #if 0 if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid) { pGC->ops->Polylines = cfb32LineSD; pGC->ops->PolySegment = cfb32SegmentSD; } else #endif pGC->ops->Polylines = miWideDash; break; } } if (new_text && (pGC->font)) { if (FONTWIDTH(pGC->font) > 32 || FONTMINBOUNDS(pGC->font,characterWidth) < 0) { pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } else { if (pGC->fillStyle == FillSolid) { if (TERMINALFONT (pGC->font)) pGC->ops->PolyGlyphBlt = amigaGXPolyTEGlyphBlt; else pGC->ops->PolyGlyphBlt = amigaGXPolyGlyphBlt; } else pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; /* special case ImageGlyphBlt for terminal emulator fonts */ if (TERMINALFONT(pGC->font)) pGC->ops->ImageGlyphBlt = amigaGXTEGlyphBlt; else pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } } if (new_fillspans) { #if 0 if (canGX) #endif pGC->ops->FillSpans = amigaGXFillSpans; #if 0 else switch (pGC->fillStyle) { case FillTiled: if (devPriv->pRotatedPixmap) { if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK) pGC->ops->FillSpans = cfb32Tile32FSCopy; else pGC->ops->FillSpans = cfb32Tile32FSGeneral; } else pGC->ops->FillSpans = cfb32UnnaturalTileFS; break; case FillStippled: pGC->ops->FillSpans = cfb32UnnaturalStippleFS; break; case FillOpaqueStippled: pGC->ops->FillSpans = cfb32UnnaturalStippleFS; break; default: FatalError("cfb32ValidateGC: illegal fillStyle\n"); } #endif } /* end of new_fillspans */ if (new_fillarea) { pGC->ops->PolyFillRect = miPolyFillRect; pGC->ops->PolyFillArc = miPolyFillArc; if (canGX) { pGC->ops->PolyFillArc = amigaGXPolyFillArc; pGC->ops->PolyFillRect = amigaGXPolyFillRect; } pGC->ops->PushPixels = mfbPushPixels; if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy) pGC->ops->PushPixels = mfbPushPixels; } } #if AMIGAMAXDEPTH == 32 Bool amigaCfbCreateGC(pGC) GCPtr pGC; { if (pGC->depth == 1) { return mfbCreateGC (pGC); } else if (pGC->depth <= 8) { return cfbCreateGC (pGC); } else if (pGC->depth <= 16) { return cfb16CreateGC (pGC); } else if (pGC->depth <= 32) { return cfb32CreateGC (pGC); } return FALSE; } #endif void amigaGXDestroyGC (pGC) GCPtr pGC; { amigaGXPrivGCPtr gxPriv = amigaGXGetGCPrivate (pGC); #if 0 if (gxPriv->stipple) xfree (gxPriv->stipple); #endif miDestroyGC (pGC); } amigaGXCreateGC (pGC) GCPtr pGC; { amigaGXPrivGCPtr gxPriv; if (pGC->depth == 1) return mfbCreateGC (pGC); #if AMIGAMAXDEPTH == 32 if (!amigaCfbCreateGC(pGC)) #else if (!cfbCreateGC (pGC)) #endif return FALSE; if (pGC->depth == 8) { pGC->ops = &amiga8GXNonTEOps; pGC->funcs = &amiga8GXGCFuncs; } else if (pGC->depth == 16) { pGC->ops = &amiga16GXNonTEOps; pGC->funcs = &amiga16GXGCFuncs; } else { pGC->ops = &amiga24GXNonTEOps; pGC->funcs = &amiga24GXGCFuncs; } gxPriv = amigaGXGetGCPrivate(pGC); gxPriv->type = DRAWABLE_WINDOW; gxPriv->stipple = 0; return TRUE; } Bool amiga8GXCreateWindow (pWin) WindowPtr pWin; { if (!cfb8CreateWindow (pWin)) return FALSE; pWin->devPrivates[amigaGXWindowPrivateIndex].ptr = 0; return TRUE; } Bool amiga16GXCreateWindow (pWin) WindowPtr pWin; { if (!cfb16CreateWindow (pWin)) return FALSE; pWin->devPrivates[amigaGXWindowPrivateIndex].ptr = 0; return TRUE; } Bool amiga24GXCreateWindow (pWin) WindowPtr pWin; { if (!cfb32CreateWindow (pWin)) return FALSE; pWin->devPrivates[amigaGXWindowPrivateIndex].ptr = 0; return TRUE; } Bool amiga8GXDestroyWindow (pWin) WindowPtr pWin; { #if 0 amigaGXStipplePtr stipple; if (stipple = amigaGXGetWindowPrivate(pWin)) xfree (stipple); #endif return cfb8DestroyWindow (pWin); } Bool amiga16GXDestroyWindow (pWin) WindowPtr pWin; { #if 0 amigaGXStipplePtr stipple; if (stipple = amigaGXGetWindowPrivate(pWin)) xfree (stipple); #endif return cfb16DestroyWindow (pWin); } Bool amiga24GXDestroyWindow (pWin) WindowPtr pWin; { #if 0 amigaGXStipplePtr stipple; if (stipple = amigaGXGetWindowPrivate(pWin)) xfree (stipple); #endif return cfb32DestroyWindow (pWin); } amiga8GXChangeWindowAttributes (pWin, mask) WindowPtr pWin; Mask mask; { #if 0 amigaGXStipplePtr stipple; #endif Mask index; WindowPtr pBgWin; register cfbPrivWin *pPrivWin; int width; pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr); /* * When background state changes from ParentRelative and * we had previously rotated the fast border pixmap to match * the parent relative origin, rerotate to match window */ if (mask & (CWBackPixmap | CWBackPixel) && pWin->backgroundState != ParentRelative && pPrivWin->fastBorder && (pPrivWin->oldRotate.x != pWin->drawable.x || pPrivWin->oldRotate.y != pWin->drawable.y)) { cfb8XRotatePixmap(pPrivWin->pRotatedBorder, pWin->drawable.x - pPrivWin->oldRotate.x); cfb8YRotatePixmap(pPrivWin->pRotatedBorder, pWin->drawable.y - pPrivWin->oldRotate.y); pPrivWin->oldRotate.x = pWin->drawable.x; pPrivWin->oldRotate.y = pWin->drawable.y; } while (mask) { index = lowbit(mask); mask &= ~index; switch (index) { case CWBackPixmap: #if 0 stipple = amigaGXGetWindowPrivate(pWin); #endif if (pWin->backgroundState == None || pWin->backgroundState == ParentRelative) { pPrivWin->fastBackground = FALSE; #if 0 if (stipple) { xfree (stipple); amigaGXSetWindowPrivate(pWin,0); } #endif /* Rotate border to match parent origin */ if (pWin->backgroundState == ParentRelative && pPrivWin->pRotatedBorder) { for (pBgWin = pWin->parent; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb8XRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.x - pPrivWin->oldRotate.x); cfb8YRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.y - pPrivWin->oldRotate.y); } break; } #if 0 if (!stipple) { if (!tmpStipple) tmpStipple = (amigaGXStipplePtr) xalloc (sizeof *tmpStipple); stipple = tmpStipple; } if (stipple && amigaGXCheckTile (pWin->background.pixmap, stipple)) { stipple->alu = gx_opaque_stipple_rop_table[GXcopy]|GX_PATTERN_MASK; pPrivWin->fastBackground = FALSE; if (stipple == tmpStipple) { amigaGXSetWindowPrivate(pWin, stipple); tmpStipple = 0; } break; } if (stipple = amigaGXGetWindowPrivate(pWin)) { xfree (stipple); amigaGXSetWindowPrivate(pWin,0); } #endif if (((width = (pWin->background.pixmap->drawable.width * PSZ)) <= 32) && !(width & (width - 1))) { cfb8CopyRotatePixmap(pWin->background.pixmap, &pPrivWin->pRotatedBackground, pWin->drawable.x, pWin->drawable.y); if (pPrivWin->pRotatedBackground) { pPrivWin->fastBackground = TRUE; pPrivWin->oldRotate.x = pWin->drawable.x; pPrivWin->oldRotate.y = pWin->drawable.y; } else { pPrivWin->fastBackground = FALSE; } break; } pPrivWin->fastBackground = FALSE; break; case CWBackPixel: pPrivWin->fastBackground = FALSE; break; case CWBorderPixmap: /* don't bother with accelerator for border tiles (just lazy) */ if (((width = (pWin->border.pixmap->drawable.width * PSZ)) <= 32) && !(width & (width - 1))) { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb8CopyRotatePixmap(pWin->border.pixmap, &pPrivWin->pRotatedBorder, pBgWin->drawable.x, pBgWin->drawable.y); if (pPrivWin->pRotatedBorder) { pPrivWin->fastBorder = TRUE; pPrivWin->oldRotate.x = pBgWin->drawable.x; pPrivWin->oldRotate.y = pBgWin->drawable.y; } else { pPrivWin->fastBorder = TRUE; } } else { pPrivWin->fastBorder = FALSE; } break; case CWBorderPixel: pPrivWin->fastBorder = FALSE; break; } } return (TRUE); } amiga16GXChangeWindowAttributes (pWin, mask) WindowPtr pWin; Mask mask; { #if 0 amigaGXStipplePtr stipple; #endif Mask index; WindowPtr pBgWin; register cfbPrivWin *pPrivWin; int width; pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr); /* * When background state changes from ParentRelative and * we had previously rotated the fast border pixmap to match * the parent relative origin, rerotate to match window */ if (mask & (CWBackPixmap | CWBackPixel) && pWin->backgroundState != ParentRelative && pPrivWin->fastBorder && (pPrivWin->oldRotate.x != pWin->drawable.x || pPrivWin->oldRotate.y != pWin->drawable.y)) { cfb16XRotatePixmap(pPrivWin->pRotatedBorder, pWin->drawable.x - pPrivWin->oldRotate.x); cfb16YRotatePixmap(pPrivWin->pRotatedBorder, pWin->drawable.y - pPrivWin->oldRotate.y); pPrivWin->oldRotate.x = pWin->drawable.x; pPrivWin->oldRotate.y = pWin->drawable.y; } while (mask) { index = lowbit(mask); mask &= ~index; switch (index) { case CWBackPixmap: #if 0 stipple = amigaGXGetWindowPrivate(pWin); #endif if (pWin->backgroundState == None || pWin->backgroundState == ParentRelative) { pPrivWin->fastBackground = FALSE; #if 0 if (stipple) { xfree (stipple); amigaGXSetWindowPrivate(pWin,0); } #endif /* Rotate border to match parent origin */ if (pWin->backgroundState == ParentRelative && pPrivWin->pRotatedBorder) { for (pBgWin = pWin->parent; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb16XRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.x - pPrivWin->oldRotate.x); cfb16YRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.y - pPrivWin->oldRotate.y); } break; } #if 0 if (!stipple) { if (!tmpStipple) tmpStipple = (amigaGXStipplePtr) xalloc (sizeof *tmpStipple); stipple = tmpStipple; } if (stipple && amigaGXCheckTile (pWin->background.pixmap, stipple)) { stipple->alu = gx_opaque_stipple_rop_table[GXcopy]|GX_PATTERN_MASK; pPrivWin->fastBackground = FALSE; if (stipple == tmpStipple) { amigaGXSetWindowPrivate(pWin, stipple); tmpStipple = 0; } break; } if (stipple = amigaGXGetWindowPrivate(pWin)) { xfree (stipple); amigaGXSetWindowPrivate(pWin,0); } #endif if (((width = (pWin->background.pixmap->drawable.width * PSZ)) <= 32) && !(width & (width - 1))) { cfb16CopyRotatePixmap(pWin->background.pixmap, &pPrivWin->pRotatedBackground, pWin->drawable.x, pWin->drawable.y); if (pPrivWin->pRotatedBackground) { pPrivWin->fastBackground = TRUE; pPrivWin->oldRotate.x = pWin->drawable.x; pPrivWin->oldRotate.y = pWin->drawable.y; } else { pPrivWin->fastBackground = FALSE; } break; } pPrivWin->fastBackground = FALSE; break; case CWBackPixel: pPrivWin->fastBackground = FALSE; break; case CWBorderPixmap: /* don't bother with accelerator for border tiles (just lazy) */ if (((width = (pWin->border.pixmap->drawable.width * PSZ)) <= 32) && !(width & (width - 1))) { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb16CopyRotatePixmap(pWin->border.pixmap, &pPrivWin->pRotatedBorder, pBgWin->drawable.x, pBgWin->drawable.y); if (pPrivWin->pRotatedBorder) { pPrivWin->fastBorder = TRUE; pPrivWin->oldRotate.x = pBgWin->drawable.x; pPrivWin->oldRotate.y = pBgWin->drawable.y; } else { pPrivWin->fastBorder = TRUE; } } else { pPrivWin->fastBorder = FALSE; } break; case CWBorderPixel: pPrivWin->fastBorder = FALSE; break; } } return (TRUE); } amiga24GXChangeWindowAttributes (pWin, mask) WindowPtr pWin; Mask mask; { #if 0 amigaGXStipplePtr stipple; #endif Mask index; WindowPtr pBgWin; register cfbPrivWin *pPrivWin; int width; pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr); /* * When background state changes from ParentRelative and * we had previously rotated the fast border pixmap to match * the parent relative origin, rerotate to match window */ if (mask & (CWBackPixmap | CWBackPixel) && pWin->backgroundState != ParentRelative && pPrivWin->fastBorder && (pPrivWin->oldRotate.x != pWin->drawable.x || pPrivWin->oldRotate.y != pWin->drawable.y)) { cfb32XRotatePixmap(pPrivWin->pRotatedBorder, pWin->drawable.x - pPrivWin->oldRotate.x); cfb32YRotatePixmap(pPrivWin->pRotatedBorder, pWin->drawable.y - pPrivWin->oldRotate.y); pPrivWin->oldRotate.x = pWin->drawable.x; pPrivWin->oldRotate.y = pWin->drawable.y; } while (mask) { index = lowbit(mask); mask &= ~index; switch (index) { case CWBackPixmap: #if 0 stipple = amigaGXGetWindowPrivate(pWin); #endif if (pWin->backgroundState == None || pWin->backgroundState == ParentRelative) { pPrivWin->fastBackground = FALSE; #if 0 if (stipple) { xfree (stipple); amigaGXSetWindowPrivate(pWin,0); } #endif /* Rotate border to match parent origin */ if (pWin->backgroundState == ParentRelative && pPrivWin->pRotatedBorder) { for (pBgWin = pWin->parent; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb32XRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.x - pPrivWin->oldRotate.x); cfb32YRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.y - pPrivWin->oldRotate.y); } break; } #if 0 if (!stipple) { if (!tmpStipple) tmpStipple = (amigaGXStipplePtr) xalloc (sizeof *tmpStipple); stipple = tmpStipple; } if (stipple && amigaGXCheckTile (pWin->background.pixmap, stipple)) { stipple->alu = gx_opaque_stipple_rop_table[GXcopy]|GX_PATTERN_MASK; pPrivWin->fastBackground = FALSE; if (stipple == tmpStipple) { amigaGXSetWindowPrivate(pWin, stipple); tmpStipple = 0; } break; } if (stipple = amigaGXGetWindowPrivate(pWin)) { xfree (stipple); amigaGXSetWindowPrivate(pWin,0); } #endif if (((width = (pWin->background.pixmap->drawable.width * PSZ)) <= 32) && !(width & (width - 1))) { cfb32CopyRotatePixmap(pWin->background.pixmap, &pPrivWin->pRotatedBackground, pWin->drawable.x, pWin->drawable.y); if (pPrivWin->pRotatedBackground) { pPrivWin->fastBackground = TRUE; pPrivWin->oldRotate.x = pWin->drawable.x; pPrivWin->oldRotate.y = pWin->drawable.y; } else { pPrivWin->fastBackground = FALSE; } break; } pPrivWin->fastBackground = FALSE; break; case CWBackPixel: pPrivWin->fastBackground = FALSE; break; case CWBorderPixmap: /* don't bother with accelerator for border tiles (just lazy) */ if (((width = (pWin->border.pixmap->drawable.width * PSZ)) <= 32) && !(width & (width - 1))) { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb32CopyRotatePixmap(pWin->border.pixmap, &pPrivWin->pRotatedBorder, pBgWin->drawable.x, pBgWin->drawable.y); if (pPrivWin->pRotatedBorder) { pPrivWin->fastBorder = TRUE; pPrivWin->oldRotate.x = pBgWin->drawable.x; pPrivWin->oldRotate.y = pBgWin->drawable.y; } else { pPrivWin->fastBorder = TRUE; } } else { pPrivWin->fastBorder = FALSE; } break; case CWBorderPixel: pPrivWin->fastBorder = FALSE; break; } } return (TRUE); } void amiga8GXPaintWindow(pWin, pRegion, what) WindowPtr pWin; RegionPtr pRegion; int what; { register cfbPrivWin *pPrivWin; #if 0 amigaGXStipplePtr stipple; #endif WindowPtr pBgWin; pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr); switch (what) { case PW_BACKGROUND: #if 0 stipple = amigaGXGetWindowPrivate(pWin); #endif switch (pWin->backgroundState) { case None: return; case ParentRelative: do { pWin = pWin->parent; } while (pWin->backgroundState == ParentRelative); (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, what); return; case BackgroundPixmap: #if 0 if (stipple) { amigaGXFillBoxStipple ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), stipple); } else #endif if (pPrivWin->fastBackground) { cfb8FillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBackground); } else { cfb8FillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixmap, (int) pWin->drawable.x, (int) pWin->drawable.y); } return; case BackgroundPixel: amigaGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixel); return; } break; case PW_BORDER: if (pWin->borderIsPixel) { amigaGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixel); return; } else if (pPrivWin->fastBorder) { cfb8FillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBorder); return; } else { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb8FillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixmap, (int) pBgWin->drawable.x, (int) pBgWin->drawable.y); return; } break; } } void amiga16GXPaintWindow(pWin, pRegion, what) WindowPtr pWin; RegionPtr pRegion; int what; { register cfbPrivWin *pPrivWin; #if 0 amigaGXStipplePtr stipple; #endif WindowPtr pBgWin; pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr); switch (what) { case PW_BACKGROUND: #if 0 stipple = amigaGXGetWindowPrivate(pWin); #endif switch (pWin->backgroundState) { case None: return; case ParentRelative: do { pWin = pWin->parent; } while (pWin->backgroundState == ParentRelative); (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, what); return; case BackgroundPixmap: #if 0 if (stipple) { amigaGXFillBoxStipple ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), stipple); } else #endif #if 1 if (pPrivWin->fastBackground) { cfb16FillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBackground); } else #endif { cfb16FillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixmap, (int) pWin->drawable.x, (int) pWin->drawable.y); } return; case BackgroundPixel: amigaGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixel); return; } break; case PW_BORDER: if (pWin->borderIsPixel) { amigaGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixel); return; } else #if 1 if (pPrivWin->fastBorder) { cfb16FillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBorder); return; } else #endif { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb16FillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixmap, (int) pBgWin->drawable.x, (int) pBgWin->drawable.y); return; } break; } } void amiga24GXPaintWindow(pWin, pRegion, what) WindowPtr pWin; RegionPtr pRegion; int what; { register cfbPrivWin *pPrivWin; #if 0 amigaGXStipplePtr stipple; #endif WindowPtr pBgWin; pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr); switch (what) { case PW_BACKGROUND: #if 0 stipple = amigaGXGetWindowPrivate(pWin); #endif switch (pWin->backgroundState) { case None: return; case ParentRelative: do { pWin = pWin->parent; } while (pWin->backgroundState == ParentRelative); (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion, what); return; case BackgroundPixmap: #if 0 #if 0 if (stipple) { amigaGXFillBoxStipple ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), stipple); } else #endif if (pPrivWin->fastBackground) { cfb32FillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBackground); } else { cfb32FillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixmap, (int) pWin->drawable.x, (int) pWin->drawable.y); } return; #endif case BackgroundPixel: amigaGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixel); return; } break; case PW_BORDER: #if 0 if (pWin->borderIsPixel) { #endif amigaGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixel); return; #if 0 } else #if 1 if (pPrivWin->fastBorder) { cfb32FillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBorder); return; } else #endif { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfb32FillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixmap, (int) pBgWin->drawable.x, (int) pBgWin->drawable.y); return; } #endif break; } } void amigaGXCopyWindow(pWin, ptOldOrg, prgnSrc) WindowPtr pWin; DDXPointRec ptOldOrg; RegionPtr prgnSrc; { DDXPointPtr pptSrc; register DDXPointPtr ppt; RegionPtr prgnDst; register BoxPtr pbox; register int dx, dy; register int i, nbox; WindowPtr pwinRoot; extern WindowPtr *WindowTable; pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; prgnDst = REGION_CREATE(pWin->drawable.pScreen, NULL, 1); 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, prgnDst, &pWin->borderClip, prgnSrc); pbox = REGION_RECTS(prgnDst); nbox = REGION_NUM_RECTS(prgnDst); if(!(pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec)))) return; ppt = pptSrc; for (i = nbox; --i >= 0; ppt++, pbox++) { ppt->x = pbox->x1 + dx; ppt->y = pbox->y1 + dy; } amigaGXDoBitblt ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, GXcopy, prgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); REGION_DESTROY(pWin->drawable.pScreen, prgnDst); } #if NeedFunctionPrototypes amigaGXInit ( ScreenPtr pScreen, ScrnInfoRec *fb) #else amigaGXInit (pScreen, fb) ScreenPtr pScreen; ScrnInfoRec *fb; #endif { Uint mode; register long r; if (serverGeneration != amigaGXGeneration) { ncr77c32ScreenPrivateIndex = AllocateScreenPrivateIndex(); if (ncr77c32ScreenPrivateIndex == -1) return FALSE; amigaGXGCPrivateIndex = AllocateGCPrivateIndex (); amigaGXWindowPrivateIndex = AllocateWindowPrivateIndex (); amigaGXGeneration = serverGeneration; } if (!AllocateGCPrivate(pScreen, amigaGXGCPrivateIndex, sizeof (amigaGXPrivGCRec))) return FALSE; if (!AllocateWindowPrivate(pScreen, amigaGXWindowPrivateIndex, 0)) return FALSE; /* * Replace various screen functions */ if (fb->bitsPerPixel == 8) { pScreen->CreateGC = amigaGXCreateGC; pScreen->CreateWindow = amiga8GXCreateWindow; pScreen->ChangeWindowAttributes = amiga8GXChangeWindowAttributes; pScreen->DestroyWindow = amiga8GXDestroyWindow; pScreen->PaintWindowBackground = amiga8GXPaintWindow; pScreen->PaintWindowBorder = amiga8GXPaintWindow; pScreen->CopyWindow = amigaGXCopyWindow; } else if (fb->bitsPerPixel == 16) { pScreen->CreateGC = amigaGXCreateGC; pScreen->CreateWindow = amiga16GXCreateWindow; pScreen->ChangeWindowAttributes = amiga16GXChangeWindowAttributes; pScreen->DestroyWindow = amiga16GXDestroyWindow; pScreen->PaintWindowBackground = amiga16GXPaintWindow; pScreen->PaintWindowBorder = amiga16GXPaintWindow; pScreen->CopyWindow = amigaGXCopyWindow; } else { pScreen->CreateGC = amigaGXCreateGC; pScreen->CreateWindow = amiga24GXCreateWindow; pScreen->ChangeWindowAttributes = amiga24GXChangeWindowAttributes; pScreen->DestroyWindow = amiga24GXDestroyWindow; pScreen->PaintWindowBackground = amiga24GXPaintWindow; pScreen->PaintWindowBorder = amiga24GXPaintWindow; pScreen->CopyWindow = amigaGXCopyWindow; pScreen->GetSpans = amiga24GXGetSpans; pScreen->GetImage = amiga24GXGetImage; pScreen->ResolveColor = amiga24GXResolveColor; pScreen->CreateColormap = amiga24GXInitializeColormap; } return TRUE; } int ncr77c32_init(ScreenPtr pScreen) { if (!amigaGXInit(pScreen, &fbdevInfoRec)) return FALSE; fbdevBitBlt = amigaGXDoBitblt; return TRUE; } /* GetSpans -- for each span, gets bits from drawable starting at ppt[i] * and continuing for pwidth[i] bits * Each scanline returned will be server scanline padded, i.e., it will come * out to an integral number of words. */ void amiga24GXGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart) DrawablePtr pDrawable; /* drawable from which to get bits */ int wMax; /* largest value of all *pwidths */ register DDXPointPtr ppt; /* points to start copying from */ int *pwidth; /* list of number of bits to copy */ int nspans; /* number of scanlines to copy */ char *pchardstStart; /* where to put the bits */ { unsigned long *pdstStart = (unsigned long *)pchardstStart; register unsigned long *pdst; /* where to put the bits */ register unsigned char *psrc; /* where to get the bits */ register unsigned long tmpSrc; /* scratch buffer for bits */ unsigned char *psrcBase; /* start of src bitmap */ int widthSrc; /* width of pixmap in bytes */ register DDXPointPtr pptLast; /* one past last point to get */ int xEnd; /* last pixel to copy from */ register int nstart; int nend; unsigned char startmask, endmask; int nlMiddle, nl, srcBit; int w; unsigned long *pdstNext; switch (pDrawable->bitsPerPixel) { case 1: mfbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); return; case 8: cfbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); return; case 16: cfb16GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); return; case 32: break; default: FatalError("amiga24GXGetSpans: invalid depth\n"); } if (pDrawable->type != DRAWABLE_WINDOW) { cfb32GetSpans (pDrawable, wMax, ppt, pwidth, nspans, pchardstStart); return; } cfb32GetByteWidthAndPointer (pDrawable, widthSrc, psrcBase) pdst = pdstStart; pptLast = ppt + nspans; while(ppt < pptLast) { xEnd = min(ppt->x + *pwidth, widthSrc); psrc = psrcBase + (ppt->y * widthSrc + ppt->x) * 3; w = xEnd - ppt->x; while (w--) { /* breaks convention of only accessing fb's long aligned */ *pdst++ = *(unsigned long *)psrc >> 8; psrc += 3; } ppt++; pwidth++; } } /* cfbSetScanline -- copies the bits from psrc to the drawable starting at * (xStart, y) and continuing to (xEnd, y). xOrigin tells us where psrc * starts on the scanline. (I.e., if this scanline passes through multiple * boxes, we may not want to start grabbing bits at psrc but at some offset * further on.) */ amiga24GXSetScanline(inf, acm, y, xOrigin, xStart, xEnd, psrc, alu, pdstBase, widthDst, planemask) ScrnInfoRec *inf; struct ACM *acm; int y; int xOrigin; /* where this scanline starts */ int xStart; /* first bit to use from scanline */ int xEnd; /* last bit to use from scanline + 1 */ register unsigned int *psrc; register int alu; /* raster op */ int *pdstBase; /* start of the drawable */ int widthDst; /* width of drawable in pixels */ unsigned long planemask; { int w; /* width of scanline in bits */ Uint dst, dim; VUint *feed = (VUint *) fbdevVirtBase; Uint mask = 0x00ffffff; Uint l1, l2, l3, l4; if ((mask & planemask) == mask) { /* no masking, simple rop table */ RZ3BlitInit(acm, blit_rop_table, alu); } else { /* use pattern as mask, and replicate the planemask as many * times as necessary. */ RZ3BlitInit(acm, blit_rop_table_masked, alu); RZ3MaskInit(acm, fbdevVirtBase, planemask, 3); dst = 8 * PAT_MEM_OFF; M2I(dst); acm->pattern = dst; } psrc += xStart - xOrigin; w = xEnd - xStart; dst = 24 * (y * widthDst + xStart); M2I(dst); acm->dst = dst; acm->src = 0; acm->control = 0xc062; dim = w | (1 << 16); M2I(dim); acm->dimension = dim; acm->start = 0; acm->start = 1; while (w >= 4) { l1 = *psrc++ << 8; l2 = *psrc++ << 8; l3 = *psrc++ << 8; l4 = *psrc++ << 8; *feed = l1 | (l2 >> 24); *feed = (l2 << 8) | (l3 >> 16); *feed = (l3 << 16) | (l4 >> 8); w -= 4; } l1 = l2 = l3 = 0; switch (w) { case 3: l3 = psrc[2] << 8; /* fall into */ case 2: l2 = psrc[1] << 8; /* fall into */ case 1: l1 = psrc[0] << 8; /* fall into */ case 0: psrc += w; break; } if (w-- > 0) { *feed = l1 | (l2 >> 24); if (w-- > 0) { *feed = (l2 << 8) | (l3 >> 16); if (w-- > 0) *feed = l3 << 16; } } RZ3WaitDone(acm); } /* SetSpans -- for each span copy pwidth[i] bits from psrc to pDrawable at * ppt[i] using the raster op from the GC. If fSorted is TRUE, the scanlines * are in increasing Y order. * Source bit lines are server scanline padded so that they always begin * on a word boundary. */ void amiga24GXSetSpans(pDrawable, pGC, pcharsrc, ppt, pwidth, nspans, fSorted) DrawablePtr pDrawable; GCPtr pGC; char *pcharsrc; register DDXPointPtr ppt; int *pwidth; int nspans; int fSorted; { unsigned int *psrc = (unsigned int *)pcharsrc; unsigned long *pdstBase; /* start of dst bitmap */ int widthDst; /* width of bitmap in pixels */ register BoxPtr pbox, pboxLast, pboxTest; register DDXPointPtr pptLast; int alu; RegionPtr prgnDst; int xStart, xEnd; int yMax; ScrnInfoRec *inf = amigaInfo(pDrawable->pScreen); struct ACM *acm = (struct ACM *) (fbdevRegBase + ACM_OFFSET); if (pDrawable->type != DRAWABLE_WINDOW) { cfb32SetSpans (pDrawable, pGC, pcharsrc, ppt, pwidth, nspans, fSorted); return; } alu = pGC->alu; prgnDst = cfbGetCompositeClip(pGC); pptLast = ppt + nspans; cfb32GetLongWidthAndPointer (pDrawable, widthDst, pdstBase) yMax = (int) pDrawable->y + (int) pDrawable->height; pbox = REGION_RECTS(prgnDst); pboxLast = pbox + REGION_NUM_RECTS(prgnDst); if(fSorted) { /* scan lines sorted in ascending order. Because they are sorted, we * don't have to check each scanline against each clip box. We can be * sure that this scanline only has to be clipped to boxes at or after the * beginning of this y-band */ pboxTest = pbox; while(ppt < pptLast) { pbox = pboxTest; if(ppt->y >= yMax) break; while(pbox < pboxLast) { if(pbox->y1 > ppt->y) { /* scanline is before clip box */ break; } else if(pbox->y2 <= ppt->y) { /* clip box is before scanline */ pboxTest = ++pbox; continue; } else if(pbox->x1 > ppt->x + *pwidth) { /* clip box is to right of scanline */ break; } else if(pbox->x2 <= ppt->x) { /* scanline is to right of clip box */ pbox++; continue; } /* at least some of the scanline is in the current clip box */ xStart = max(pbox->x1, ppt->x); xEnd = min(ppt->x + *pwidth, pbox->x2); amiga24GXSetScanline(inf, acm, ppt->y, ppt->x, xStart, xEnd, psrc, alu, (int *)pdstBase, widthDst, pGC->planemask); if(ppt->x + *pwidth <= pbox->x2) { /* End of the line, as it were */ break; } else pbox++; } /* We've tried this line against every box; it must be outside them * all. move on to the next point */ ppt++; psrc += PixmapWidthInPadUnits(*pwidth, pDrawable->depth); pwidth++; } } else { /* scan lines not sorted. We must clip each line against all the boxes */ while(ppt < pptLast) { if(ppt->y >= 0 && ppt->y < yMax) { for(pbox = REGION_RECTS(prgnDst); pbox< pboxLast; pbox++) { if(pbox->y1 > ppt->y) { /* rest of clip region is above this scanline, * skip it */ break; } if(pbox->y2 <= ppt->y) { /* clip box is below scanline */ pbox++; break; } if(pbox->x1 <= ppt->x + *pwidth && pbox->x2 > ppt->x) { xStart = max(pbox->x1, ppt->x); xEnd = min(pbox->x2, ppt->x + *pwidth); amiga24GXSetScanline(inf, acm, ppt->y, ppt->x, xStart, xEnd, psrc, alu, (int *)pdstBase, widthDst, pGC->planemask); } } } psrc += PixmapWidthInPadUnits(*pwidth, pDrawable->depth); ppt++; pwidth++; } } } void amiga24GXGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine) DrawablePtr pDrawable; int sx, sy, w, h; unsigned int format; unsigned long planeMask; char *pdstLine; { switch (pDrawable->bitsPerPixel) { case 1: mfbGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); break; case 8: cfbGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); break; case 16: cfb16GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); break; case 32: if (pDrawable->type != DRAWABLE_WINDOW) cfb32GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); else miGetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); break; } } /* these two in cfb just don't work with 24bit deep color data ... */ void amiga24GXResolveColor(pred, pgreen, pblue, pVisual) unsigned short *pred, *pgreen, *pblue; register VisualPtr pVisual; { /* do nothing.. */ } Bool amiga24GXInitializeColormap(pmap) register ColormapPtr pmap; { register unsigned i; register VisualPtr pVisual; unsigned maxent; pVisual = pmap->pVisual; maxent = pVisual->ColormapEntries - 1; for(i = 0; i <= maxent; i++) { pmap->red[i].co.local.red = (i << 8) | i; pmap->blue[i].co.local.blue = (i << 8) | i; pmap->green[i].co.local.green = (i << 8) | i; } return TRUE; }