/* * Copyright © 2000 Keith Packard * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Keith Packard not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Keith Packard makes no * representations about the suitability of this software for any purpose. It * is provided "as is" without express or implied warranty. * * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ #ifdef HAVE_CONFIG_H #include #endif #include "igs.h" #include "igsdraw.h" #include "Xmd.h" #include "gcstruct.h" #include "scrnintstr.h" #include "pixmapstr.h" #include "regionstr.h" #include "mistruct.h" #include "fontstruct.h" #include "dixfontstr.h" #include "fb.h" #include "migc.h" #include "miline.h" CARD8 igsPatRop[16] = { /* GXclear */ 0x00, /* 0 */ /* GXand */ 0xa0, /* src AND dst */ /* GXandReverse */ 0x50, /* src AND NOT dst */ /* GXcopy */ 0xf0, /* src */ /* GXandInverted*/ 0x0a, /* NOT src AND dst */ /* GXnoop */ 0xaa, /* dst */ /* GXxor */ 0x5a, /* src XOR dst */ /* GXor */ 0xfa, /* src OR dst */ /* GXnor */ 0x05, /* NOT src AND NOT dst */ /* GXequiv */ 0xa5, /* NOT src XOR dst */ /* GXinvert */ 0x55, /* NOT dst */ /* GXorReverse */ 0xf5, /* src OR NOT dst */ /* GXcopyInverted*/ 0x0f, /* NOT src */ /* GXorInverted */ 0xaf, /* NOT src OR dst */ /* GXnand */ 0x5f, /* NOT src OR NOT dst */ /* GXset */ 0xff, /* 1 */ }; /* * Handle pixel transfers */ #define BURST #ifdef BURST #define PixTransDeclare VOL32 *pix_trans_base = igsc->copData,\ *pix_trans = pix_trans_base #define PixTransStart(n) if (pix_trans + (n) > pix_trans_base + 16384) pix_trans = pix_trans_base #define PixTransStore(t) *pix_trans++ = (t) #else #define PixTransDeclare VOL32 *pix_trans = igsc->copData #define PixTransStart(n) #define PixTransStore(t) *pix_trans = (t) #endif static IgsPattern * igsSetPattern (ScreenPtr pScreen, PixmapPtr pPixmap, CARD8 fillStyle, INT32 xrot, INT32 yrot) { KdScreenPriv(pScreen); igsCardInfo(pScreenPriv); igsScreenInfo(pScreenPriv); int i; IgsPatternCache *c; IgsPattern *p; if (fillStyle == FillTiled) c = &igss->tile; else c = &igss->stipple; for (i = 0; i < IGS_NUM_PATTERN; i++) { p = &c->pattern[i]; if (p->serial_number == pPixmap->drawable.serialNumber && p->xrot == xrot && p->yrot == yrot) { return p; } } p = &c->pattern[c->next]; if (++c->next == IGS_NUM_PATTERN) c->next = 0; p->serial_number = pPixmap->drawable.serialNumber; p->xrot = xrot; p->yrot = yrot; if (fillStyle != FillTiled) { FbStip *pix; FbStride pixStride; int pixBpp; int pixXoff, pixYoff; CARD8 tmp[8]; CARD32 *pat; int stipX, stipY; int y; FbStip bits; fbGetStipDrawable (&pPixmap->drawable, pix, pixStride, pixBpp, pixXoff, pixYoff); modulus (-yrot - pixYoff, pPixmap->drawable.height, stipY); modulus (-xrot - pixXoff, FB_UNIT, stipX); pat = (CARD32 *) p->base; for (y = 0; y < 8; y++) { bits = pix[stipY * pixStride]; FbRotLeft (bits, stipX); tmp[y] = (CARD8) bits; stipY++; if (stipY == pPixmap->drawable.height) stipY = 0; } for (i = 0; i < 2; i++) { bits = (tmp[i*4+0] | (tmp[i*4+1] << 8) | (tmp[i*4+2] << 16) | (tmp[i*4+3] << 24)); IgsAdjustBits32 (bits); *pat++ = bits; } } else { FbBits *pix; FbStride pixStride; int pixBpp; FbBits *pat; FbStride patStride; int patBpp; int patXoff, patYoff; fbGetDrawable (&pPixmap->drawable, pix, pixStride, pixBpp, patXoff, patYoff); pat = (FbBits *) p->base; patBpp = pixBpp; patStride = (patBpp * IGS_PATTERN_WIDTH) / (8 * sizeof (FbBits)); fbTile (pat, patStride, 0, patBpp * IGS_PATTERN_WIDTH, IGS_PATTERN_HEIGHT, pix, pixStride, pPixmap->drawable.width * pixBpp, pPixmap->drawable.height, GXcopy, FB_ALLONES, pixBpp, (xrot - patXoff) * pixBpp, yrot - patYoff); } return p; } void igsFillBoxSolid (DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel, int alu, unsigned long planemask) { SetupIgs(pDrawable->pScreen); CARD32 cmd; _igsSetSolidRect(cop,alu,planemask,pixel,cmd); while (nBox--) { _igsRect(cop,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); pBox++; } KdMarkSync (pDrawable->pScreen); } void igsFillBoxTiled (DrawablePtr pDrawable, int nBox, BoxPtr pBox, PixmapPtr pPixmap, int xrot, int yrot, int alu) { SetupIgs(pDrawable->pScreen); CARD32 cmd; IgsPattern *p = igsSetPattern (pDrawable->pScreen, pPixmap, FillTiled, xrot, yrot); _igsSetTiledRect(cop,alu,planemask,p->offset,cmd); while (nBox--) { _igsPatRect(cop,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); pBox++; } KdMarkSync (pDrawable->pScreen); } void igsFillBoxStippled (DrawablePtr pDrawable, GCPtr pGC, int nBox, BoxPtr pBox) { SetupIgs(pDrawable->pScreen); CARD32 cmd; int xrot = pGC->patOrg.x + pDrawable->x; int yrot = pGC->patOrg.y + pDrawable->y; IgsPattern *p = igsSetPattern (pDrawable->pScreen, pGC->stipple, pGC->fillStyle, xrot, yrot); if (pGC->fillStyle == FillStippled) { _igsSetStippledRect (cop,pGC->alu,planemask,pGC->fgPixel,p->offset,cmd); } else { _igsSetOpaqueStippledRect (cop,pGC->alu,planemask, pGC->fgPixel,pGC->bgPixel,p->offset,cmd); } while (nBox--) { _igsPatRect(cop,pBox->x1,pBox->y1,pBox->x2-pBox->x1,pBox->y2-pBox->y1,cmd); pBox++; } KdMarkSync (pDrawable->pScreen); } void igsStipple (ScreenPtr pScreen, CARD32 cmd, FbStip *psrcBase, FbStride widthSrc, int srcx, int srcy, int dstx, int dsty, int width, int height) { SetupIgs(pScreen); FbStip *psrcLine, *psrc; FbStride widthRest; FbStip bits, tmp, lastTmp; int leftShift, rightShift; int nl, nlMiddle; int r; PixTransDeclare; /* Compute blt address and parameters */ psrc = psrcBase + srcy * widthSrc + (srcx >> 5); nlMiddle = (width + 31) >> 5; leftShift = srcx & 0x1f; rightShift = 32 - leftShift; widthRest = widthSrc - nlMiddle; _igsPlaneBlt(cop,dstx,dsty,width,height,cmd); if (leftShift == 0) { while (height--) { nl = nlMiddle; PixTransStart(nl); while (nl--) { tmp = *psrc++; IgsAdjustBits32 (tmp); PixTransStore (tmp); } psrc += widthRest; } } else { widthRest--; while (height--) { bits = *psrc++; nl = nlMiddle; PixTransStart(nl); while (nl--) { tmp = FbStipLeft(bits, leftShift); bits = *psrc++; tmp |= FbStipRight(bits, rightShift); IgsAdjustBits32(tmp); PixTransStore (tmp); } psrc += widthRest; } } } void igsCopyNtoN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { SetupIgs(pDstDrawable->pScreen); int srcX, srcY, dstX, dstY; int w, h; CARD32 flags; CARD32 cmd; CARD8 alu; if (pGC) { alu = pGC->alu; if (sourceInvarient (pGC->alu)) { igsFillBoxSolid (pDstDrawable, nbox, pbox, 0, pGC->alu, pGC->planemask); return; } } else alu = GXcopy; _igsSetBlt(cop,alu,pGC->planemask,reverse,upsidedown,cmd); while (nbox--) { w = pbox->x2 - pbox->x1; h = pbox->y2 - pbox->y1; if (reverse) dstX = pbox->x2 - 1; else dstX = pbox->x1; srcX = dstX + dx; if (upsidedown) dstY = pbox->y2 - 1; else dstY = pbox->y1; srcY = dstY + dy; _igsBlt (cop, srcX, srcY, dstX, dstY, w, h, cmd); pbox++; } KdMarkSync (pDstDrawable->pScreen); } RegionPtr igsCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { KdScreenPriv(pDstDrawable->pScreen); FbBits depthMask; depthMask = FbFullMask (pDstDrawable->depth); if ((pGC->planemask & depthMask) == depthMask && pSrcDrawable->type == DRAWABLE_WINDOW && pDstDrawable->type == DRAWABLE_WINDOW) { return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, igsCopyNtoN, 0, 0); } return KdCheckCopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); } typedef struct _igs1toNargs { unsigned long copyPlaneFG, copyPlaneBG; Bool opaque; } igs1toNargs; void igsCopy1toN (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy, Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) { SetupIgs(pDstDrawable->pScreen); igs1toNargs *args = closure; int dstx, dsty; FbStip *psrcBase; FbStride widthSrc; int srcBpp; int srcXoff, srcYoff; CARD32 cmd; if (args->opaque && sourceInvarient (pGC->alu)) { igsFillBoxSolid (pDstDrawable, nbox, pbox, pGC->bgPixel, pGC->alu, pGC->planemask); return; } fbGetStipDrawable (pSrcDrawable, psrcBase, widthSrc, srcBpp, srcXoff, srcYoff); if (args->opaque) { _igsSetOpaquePlaneBlt (cop, pGC->alu, pGC->planemask, args->copyPlaneFG, args->copyPlaneBG, cmd); } else { _igsSetTransparentPlaneBlt (cop, pGC->alu, pGC->planemask, args->copyPlaneFG, cmd); } while (nbox--) { dstx = pbox->x1; dsty = pbox->y1; igsStipple (pDstDrawable->pScreen, cmd, psrcBase, widthSrc, dstx + dx - srcXoff, dsty + dy - srcYoff, dstx, dsty, pbox->x2 - dstx, pbox->y2 - dsty); pbox++; } KdMarkSync (pDstDrawable->pScreen); } RegionPtr igsCopyPlane (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, unsigned long bitPlane) { RegionPtr ret; igs1toNargs args; FbBits depthMask; depthMask = FbFullMask (pDstDrawable->depth); if ((pGC->planemask & depthMask) == depthMask && pDstDrawable->type == DRAWABLE_WINDOW && pSrcDrawable->depth == 1) { args.copyPlaneFG = pGC->fgPixel; args.copyPlaneBG = pGC->bgPixel; args.opaque = TRUE; return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, igsCopy1toN, bitPlane, &args); } return KdCheckCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } #if 0 /* would you believe this is slower than fb? */ void igsPushPixels (GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable, int w, int h, int x, int y) { igs1toNargs args; FbBits depthMask; depthMask = FbFullMask (pDstDrawable->depth); if ((pGC->planemask & depthMask) == depthMask && pDrawable->type == DRAWABLE_WINDOW && pGC->fillStyle == FillSolid) { args.opaque = FALSE; args.copyPlaneFG = pGC->fgPixel; (void) fbDoCopy ((DrawablePtr) pBitmap, pDrawable, pGC, 0, 0, w, h, x, y, igsCopy1toN, 1, &args); } else { KdCheckPushPixels (pGC, pBitmap, pDrawable, w, h, x, y); } } #else #define igsPushPixels KdCheckPushPixels #endif BOOL igsFillOk (GCPtr pGC) { FbBits depthMask; depthMask = FbFullMask(pGC->depth); if ((pGC->planemask & depthMask) != depthMask) return FALSE; switch (pGC->fillStyle) { case FillSolid: return TRUE; case FillTiled: return (igsPatternDimOk (pGC->tile.pixmap->drawable.width) && igsPatternDimOk (pGC->tile.pixmap->drawable.height)); case FillStippled: case FillOpaqueStippled: return (igsPatternDimOk (pGC->stipple->drawable.width) && igsPatternDimOk (pGC->stipple->drawable.height)); } return FALSE; } void igsFillSpans (DrawablePtr pDrawable, GCPtr pGC, int n, DDXPointPtr ppt, int *pwidth, int fSorted) { SetupIgs(pDrawable->pScreen); DDXPointPtr pptFree; FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); int *pwidthFree;/* copies of the pointers to free */ CARD32 cmd; int nTmp; INT16 x, y; int width; IgsPattern *p; if (!igsFillOk (pGC)) { KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); return; } nTmp = n * miFindMaxBand(fbGetCompositeClip(pGC)); 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(fbGetCompositeClip(pGC), ppt, pwidth, n, pptFree, pwidthFree, fSorted); pwidth = pwidthFree; ppt = pptFree; switch (pGC->fillStyle) { case FillSolid: _igsSetSolidRect(cop,pGC->alu,pGC->planemask,pGC->fgPixel,cmd); break; case FillTiled: p = igsSetPattern (pDrawable->pScreen, pGC->tile.pixmap, FillTiled, pGC->patOrg.x + pDrawable->x, pGC->patOrg.y + pDrawable->y); _igsSetTiledRect (cop,pGC->alu,pGC->planemask,p->offset,cmd); break; default: p = igsSetPattern (pDrawable->pScreen, pGC->stipple, pGC->fillStyle, pGC->patOrg.x + pDrawable->x, pGC->patOrg.y + pDrawable->y); if (pGC->fillStyle == FillStippled) { _igsSetStippledRect (cop,pGC->alu,pGC->planemask, pGC->fgPixel,p->offset,cmd); } else { _igsSetOpaqueStippledRect (cop,pGC->alu,pGC->planemask, pGC->fgPixel,pGC->bgPixel,p->offset,cmd); } break; } while (n--) { x = ppt->x; y = ppt->y; ppt++; width = *pwidth++; if (width) { _igsPatRect(cop,x,y,width,1,cmd); } } DEALLOCATE_LOCAL(pptFree); DEALLOCATE_LOCAL(pwidthFree); KdMarkSync (pDrawable->pScreen); } #define NUM_STACK_RECTS 1024 void igsPolyFillRect (DrawablePtr pDrawable, GCPtr pGC, int nrectFill, xRectangle *prectInit) { SetupIgs(pDrawable->pScreen); xRectangle *prect; RegionPtr prgnClip; register BoxPtr pbox; register BoxPtr pboxClipped; BoxPtr pboxClippedBase; BoxPtr pextent; BoxRec stackRects[NUM_STACK_RECTS]; FbGCPrivPtr fbPriv = fbGetGCPrivate (pGC); int numRects; int n; int xorg, yorg; int x, y; if (!igsFillOk (pGC)) { KdCheckPolyFillRect (pDrawable, pGC, nrectFill, prectInit); return; } prgnClip = fbGetCompositeClip (pGC); 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)xalloc(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) { switch (pGC->fillStyle) { case FillSolid: igsFillBoxSolid(pDrawable, pboxClipped-pboxClippedBase, pboxClippedBase, pGC->fgPixel, pGC->alu, pGC->planemask); break; case FillTiled: igsFillBoxTiled(pDrawable, pboxClipped-pboxClippedBase, pboxClippedBase, pGC->tile.pixmap, pGC->patOrg.x + pDrawable->x, pGC->patOrg.y + pDrawable->y, pGC->alu); break; case FillStippled: case FillOpaqueStippled: igsFillBoxStippled (pDrawable, pGC, pboxClipped-pboxClippedBase, pboxClippedBase); break; } } if (pboxClippedBase != stackRects) xfree(pboxClippedBase); } int igsTextInRegion (GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci) { int w; FontPtr pfont = pGC->font; BoxRec bbox; if (FONTCONSTMETRICS(pfont)) w = FONTMAXBOUNDS(pfont,characterWidth) * nglyph; else { w = 0; while (nglyph--) w += (*ppci++)->metrics.characterWidth; } if (w < 0) { bbox.x1 = x + w; bbox.x2 = x; } else { bbox.x1 = x; bbox.x2 = x + w; } w = FONTMINBOUNDS(pfont,leftSideBearing); if (w < 0) bbox.x1 += w; w = FONTMAXBOUNDS(pfont, rightSideBearing) - FONTMINBOUNDS(pfont, characterWidth); if (w > 0) bbox.x2 += w; bbox.y1 = y - FONTMAXBOUNDS(pfont,ascent); bbox.y2 = y + FONTMAXBOUNDS(pfont,descent); return RECT_IN_REGION(pGC->pScreen, fbGetCompositeClip(pGC), &bbox); } void igsGlyphBltClipped (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppciInit, Bool image) { SetupIgs(pDrawable->pScreen); CARD32 cmd; int h; int w; int xBack, yBack; int hBack, wBack; int lw; FontPtr pfont = pGC->font; CharInfoPtr pci; unsigned long *bits; BoxPtr extents; BoxRec bbox; CARD32 b; CharInfoPtr *ppci; FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); RegionPtr pClip = fbGetCompositeClip(pGC); BoxPtr pBox; int nbox; int x1, y1, x2, y2; unsigned char alu; Bool set; PixTransDeclare; if (image) { xBack = x; yBack = y - FONTASCENT(pGC->font); wBack = 0; hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); if (hBack) { h = nglyph; ppci = ppciInit; while (h--) wBack += (*ppci++)->metrics.characterWidth; } if (wBack < 0) { xBack = xBack + wBack; wBack = -wBack; } if (hBack < 0) { yBack = yBack + hBack; hBack = -hBack; } alu = GXcopy; if (wBack) { _igsSetSolidRect (cop, GXcopy, pGC->planemask, pGC->bgPixel, cmd); for (nbox = REGION_NUM_RECTS (pClip), pBox = REGION_RECTS (pClip); nbox--; pBox++) { x1 = xBack; x2 = xBack + wBack; y1 = yBack; y2 = yBack + hBack; if (x1 < pBox->x1) x1 = pBox->x1; if (x2 > pBox->x2) x2 = pBox->x2; if (y1 < pBox->y1) y1 = pBox->y1; if (y2 > pBox->y2) y2 = pBox->y2; if (x1 < x2 && y1 < y2) { _igsRect (cop, x1, y1, x2 - x1, y2 - y1, cmd); } } KdMarkSync (pDrawable->pScreen); } } else { wBack = 0; alu = pGC->alu; } ppci = ppciInit; set = FALSE; while (nglyph--) { pci = *ppci++; h = pci->metrics.ascent + pci->metrics.descent; w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; x1 = x + pci->metrics.leftSideBearing; y1 = y - pci->metrics.ascent; bbox.x1 = x1; bbox.y1 = y1; bbox.x2 = x1 + w; bbox.y2 = y1 + h; switch (RECT_IN_REGION(pGC->pScreen, pClip, &bbox)) { case rgnIN: lw = h * ((w + 31) >> 5); if (lw) { if (!set) { _igsSetTransparentPlaneBlt (cop, alu, pGC->planemask, pGC->fgPixel, cmd); set = TRUE; } _igsPlaneBlt(cop, x + pci->metrics.leftSideBearing, y - pci->metrics.ascent, w, h, cmd); bits = (unsigned long *) pci->bits; PixTransStart (lw); while (lw--) { b = *bits++; IgsAdjustBits32 (b); PixTransStore(b); } KdMarkSync (pDrawable->pScreen); } break; case rgnPART: set = FALSE; KdCheckSync (pDrawable->pScreen); fbPutXYImage (pDrawable, pClip, fbPriv->fg, fbPriv->bg, fbPriv->pm, alu, FALSE, x1, y1, w, h, (FbStip *) pci->bits, (w + 31) >> 5, 0); break; case rgnOUT: break; } x += pci->metrics.characterWidth; } } void igsGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppciInit, Bool image) { SetupIgs(pDrawable->pScreen); CARD32 cmd; int h; int w; int xBack, yBack; int hBack, wBack; int lw; FontPtr pfont = pGC->font; CharInfoPtr pci; unsigned long *bits; BoxPtr extents; BoxRec bbox; CARD32 b; CharInfoPtr *ppci; unsigned char alu; PixTransDeclare; /* * Paint background for image text */ if (image) { xBack = x; yBack = y - FONTASCENT(pGC->font); wBack = 0; hBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font); if (hBack) { h = nglyph; ppci = ppciInit; while (h--) wBack += (*ppci++)->metrics.characterWidth; } if (wBack < 0) { xBack = xBack + wBack; wBack = -wBack; } if (hBack < 0) { yBack = yBack + hBack; hBack = -hBack; } alu = GXcopy; if (wBack) { _igsSetSolidRect (cop, GXcopy, pGC->planemask, pGC->bgPixel, cmd); _igsRect (cop, xBack, yBack, wBack, hBack, cmd); } } else { wBack = 0; alu = pGC->alu; } _igsSetTransparentPlaneBlt (cop, alu, pGC->planemask, pGC->fgPixel, cmd); ppci = ppciInit; while (nglyph--) { pci = *ppci++; h = pci->metrics.ascent + pci->metrics.descent; w = pci->metrics.rightSideBearing - pci->metrics.leftSideBearing; lw = h * ((w + 31) >> 5); if (lw) { _igsPlaneBlt(cop, x + pci->metrics.leftSideBearing, y - pci->metrics.ascent, w, h, cmd); bits = (unsigned long *) pci->bits; PixTransStart(lw); while (lw--) { b = *bits++; IgsAdjustBits32 (b); PixTransStore(b); } } x += pci->metrics.characterWidth; } KdMarkSync (pDrawable->pScreen); } void igsTEGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int xInit, int yInit, unsigned int nglyph, CharInfoPtr *ppci, Bool image) { SetupIgs(pDrawable->pScreen); CARD32 cmd; int x, y; int h, lw, lwTmp; int w; FontPtr pfont = pGC->font; unsigned long *char1, *char2, *char3, *char4; int widthGlyphs, widthGlyph; BoxRec bbox; CARD32 tmp; PixTransDeclare; widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); if (!widthGlyph) return; h = FONTASCENT(pfont) + FONTDESCENT(pfont); if (!h) return; x = xInit + FONTMAXBOUNDS(pfont,leftSideBearing); y = yInit - FONTASCENT(pfont); if (image) { _igsSetOpaquePlaneBlt (cop, GXcopy, pGC->planemask, pGC->fgPixel, pGC->bgPixel, cmd); } else { _igsSetTransparentPlaneBlt (cop, pGC->alu, pGC->planemask, pGC->fgPixel, cmd); } #if BITMAP_BIT_ORDER == LSBFirst #define SHIFT << #else #define SHIFT >> #endif #define LoopIt(count, w, loadup, fetch) \ while (nglyph >= count) \ { \ nglyph -= count; \ _igsPlaneBlt (cop, x, y, w, h, cmd); \ x += w; \ loadup \ lwTmp = h; \ PixTransStart(h); \ while (lwTmp--) { \ tmp = fetch; \ IgsAdjustBits32(tmp); \ PixTransStore(tmp); \ } \ } 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++ SHIFT widthGlyph)) SHIFT widthGlyph)) SHIFT 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++ SHIFT widthGlyph)) SHIFT widthGlyph))) } else if (widthGlyph <= 16) { widthGlyphs = widthGlyph << 1; LoopIt(2, widthGlyphs, char1 = (unsigned long *) (*ppci++)->bits; char2 = (unsigned long *) (*ppci++)->bits;, (*char1++ | (*char2++ SHIFT widthGlyph))) } lw = h * ((widthGlyph + 31) >> 5); while (nglyph--) { _igsPlaneBlt (cop, x, y, widthGlyph, h, cmd); x += widthGlyph; char1 = (unsigned long *) (*ppci++)->bits; lwTmp = lw; PixTransStart(lw); while (lwTmp--) { tmp = *char1++; IgsAdjustBits32(tmp); PixTransStore(tmp); } } KdMarkSync (pDrawable->pScreen); } /* * Blt glyphs using image transfer window */ void igsPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { if (pGC->fillStyle != FillSolid || fbGetGCPrivate(pGC)->pm != FB_ALLONES) { KdCheckPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); return; } x += pDrawable->x; y += pDrawable->y; switch (igsTextInRegion (pGC, x, y, nglyph, ppci)) { case rgnIN: if (TERMINALFONT(pGC->font)) igsTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE); else igsGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, FALSE); break; case rgnPART: igsGlyphBltClipped (pDrawable, pGC, x, y, nglyph, ppci, FALSE); break; case rgnOUT: break; } } void igsImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, pointer pglyphBase) { if (fbGetGCPrivate(pGC)->pm != FB_ALLONES) { KdCheckImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); return; } x += pDrawable->x; y += pDrawable->y; switch (igsTextInRegion (pGC, x, y, nglyph, ppci)) { case rgnIN: if (TERMINALFONT(pGC->font)) igsTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE); else igsGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, TRUE); break; case rgnPART: igsGlyphBltClipped (pDrawable, pGC, x, y, nglyph, ppci, TRUE); break; case rgnOUT: break; } } static void igsInvalidatePattern (IgsPatternCache *c, PixmapPtr pPixmap) { int i; if (c->base) { for (i = 0; i < IGS_NUM_PATTERN; i++) { if (c->pattern[i].serial_number == pPixmap->drawable.serialNumber) c->pattern[i].serial_number = ~0; } } } static void igsInitPattern (IgsPatternCache *c, int bsize, int psize) { int i; int boffset; int poffset; for (i = 0; i < IGS_NUM_PATTERN; i++) { boffset = i * bsize; poffset = i * psize; c->pattern[i].xrot = -1; c->pattern[i].yrot = -1; c->pattern[i].serial_number = ~0; c->pattern[i].offset = c->offset + poffset; c->pattern[i].base = c->base + boffset; } c->next = 0; } static const GCOps igsOps = { igsFillSpans, KdCheckSetSpans, KdCheckPutImage, igsCopyArea, igsCopyPlane, KdCheckPolyPoint, KdCheckPolylines, KdCheckPolySegment, miPolyRectangle, KdCheckPolyArc, miFillPolygon, igsPolyFillRect, KdCheckPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, igsImageGlyphBlt, igsPolyGlyphBlt, igsPushPixels, }; void igsValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable) { FbGCPrivPtr fbPriv = fbGetGCPrivate(pGC); fbValidateGC (pGC, changes, pDrawable); if (pDrawable->type == DRAWABLE_WINDOW) pGC->ops = (GCOps *) &igsOps; else pGC->ops = (GCOps *) &fbGCOps; } GCFuncs igsGCFuncs = { igsValidateGC, miChangeGC, miCopyGC, miDestroyGC, miChangeClip, miDestroyClip, miCopyClip }; int igsCreateGC (GCPtr pGC) { if (!fbCreateGC (pGC)) return FALSE; if (pGC->depth != 1) pGC->funcs = &igsGCFuncs; return TRUE; } void igsCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWin->drawable.pScreen; KdScreenPriv(pScreen); RegionRec rgnDst; int dx, dy; WindowPtr pwinRoot; pwinRoot = WindowTable[pWin->drawable.pScreen->myNum]; dx = ptOldOrg.x - pWin->drawable.x; dy = ptOldOrg.y - pWin->drawable.y; REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); fbCopyRegion ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, 0, &rgnDst, dx, dy, igsCopyNtoN, 0, 0); REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); } void igsPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { KdScreenPriv(pWin->drawable.pScreen); PixmapPtr pTile; if (!REGION_NUM_RECTS(pRegion)) return; switch (what) { case PW_BACKGROUND: 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: pTile = pWin->background.pixmap; if (igsPatternDimOk (pTile->drawable.width) && igsPatternDimOk (pTile->drawable.height)) { igsFillBoxTiled ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pTile, pWin->drawable.x, pWin->drawable.y, GXcopy); return; } break; case BackgroundPixel: igsFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixel, GXcopy, ~0); return; } break; case PW_BORDER: if (pWin->borderIsPixel) { igsFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixel, GXcopy, ~0); return; } else { pTile = pWin->border.pixmap; if (igsPatternDimOk (pTile->drawable.width) && igsPatternDimOk (pTile->drawable.height)) { igsFillBoxTiled ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pTile, pWin->drawable.x, pWin->drawable.y, GXcopy); return; } } break; } KdCheckPaintWindow (pWin, pRegion, what); } Bool igsDrawInit (ScreenPtr pScreen) { KdScreenPriv(pScreen); igsCardInfo(pScreenPriv); igsScreenInfo(pScreenPriv); int i; int pattern_size; int boffset, poffset; KdScreenInitAsync (pScreen); /* * Replace various fb screen functions */ pScreen->CreateGC = igsCreateGC; pScreen->CopyWindow = igsCopyWindow; pScreen->PaintWindowBackground = igsPaintWindow; pScreen->PaintWindowBorder = igsPaintWindow; /* * Initialize patterns */ if (igss->tile.base) { pattern_size = IgsTileSize(pScreenPriv->screen->fb[0].bitsPerPixel); igsInitPattern (&igss->tile, pattern_size, pattern_size * 8 / pScreenPriv->screen->fb[0].bitsPerPixel); pattern_size = IgsStippleSize(pScreenPriv->screen->fb[0].bitsPerPixel); igsInitPattern (&igss->stipple, pattern_size, pattern_size * 8 / pScreenPriv->screen->fb[0].bitsPerPixel); } return TRUE; } void igsDrawEnable (ScreenPtr pScreen) { SetupIgs(pScreen); CARD32 cmd; CARD32 base; CARD16 stride; CARD32 format; stride = pScreenPriv->screen->fb[0].pixelStride; _igsWaitIdleEmpty(cop); _igsReset(cop); switch (pScreenPriv->screen->fb[0].bitsPerPixel) { case 8: format = IGS_FORMAT_8BPP; break; case 16: format = IGS_FORMAT_16BPP; break; case 24: format = IGS_FORMAT_24BPP; break; case 32: format = IGS_FORMAT_32BPP; break; } cop->format = format; cop->dst_stride = stride - 1; cop->src1_stride = stride - 1; cop->src2_stride = stride - 1; cop->src1_start = 0; cop->src2_start = 0; cop->extension |= IGS_BLOCK_COP_REG | IGS_BURST_ENABLE; _igsSetSolidRect(cop, GXcopy, ~0, pScreen->blackPixel, cmd); _igsRect (cop, 0, 0, pScreenPriv->screen->width, pScreenPriv->screen->height, cmd); _igsWaitIdleEmpty (cop); } void igsDrawDisable (ScreenPtr pScreen) { } void igsDrawFini (ScreenPtr pScreen) { } void igsDrawSync (ScreenPtr pScreen) { SetupIgs(pScreen); _igsWaitIdleEmpty(cop); }