/* static char *rid="$Xorg: sunGX.c,v 1.5 2001/02/09 02:04:44 xorgcvs Exp $"; */ /* Copyright 1991, 1998 The Open Group 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. 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 OPEN GROUP 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 Open Group 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 Open Group. * * Author: Keith Packard, MIT X Consortium */ /* $XFree86: xc/programs/Xserver/hw/sun/sunGX.c,v 1.9 2003/11/17 22:20:36 dawes Exp $ */ #include "sun.h" #include #include "gcstruct.h" #include "pixmapstr.h" #include "regionstr.h" #include "mistruct.h" #include #include "dixfontstr.h" #include "fb.h" #include "sunGX.h" #include "migc.h" #include "mispans.h" #define sunGXFillSpan(gx,y,x1,x2,r) {\ (gx)->apointy = (y); \ (gx)->apointx = (x1); \ (gx)->arectx = (x2); \ GXDrawDone(gx,r); \ } #define GXSetClip(gx,pbox) {\ (gx)->clipminx = (pbox)->x1; \ (gx)->clipminy = (pbox)->y1; \ (gx)->clipmaxx = (pbox)->x2 - 1; \ (gx)->clipmaxy = (pbox)->y2 - 1; \ } #define GXSetOff(gx,x,y) {\ (gx)->offx = (x); \ (gx)->offy = (y); \ } #define GXResetClip(gx,pScreen) { \ (gx)->clipminx = 0; \ (gx)->clipminy = 0; \ (gx)->clipmaxx = (pScreen)->width - 1; \ (gx)->clipmaxy = (pScreen)->height - 1; \ } #define GXResetOff(gx) {\ (gx)->offx = 0; \ (gx)->offy = 0; \ } #define sunGXGetAddrRange(pDrawable,extents,base,lo,hi) {\ int __x__; \ cfbGetWindowByteWidthAndPointer((WindowPtr)pDrawable,__x__,base); \ lo = (base) + WIDTH_MUL((extents)->y1) + (extents)->x1; \ hi = (base) + WIDTH_MUL((extents)->y2 - 1) + (extents)->x2 - 1; \ (base) = (base) + WIDTH_MUL(pDrawable->y) + pDrawable->x; \ } /* rop_tables ========== lookup tables for GX raster ops, with the plane_mask,pixel_mask,pattern_mask ,attrib_sel, polygon_draw,raster_mode encoded into the top half. There is a lookup table for each commonly used combination. */ /* rops for bit blit / copy area with: Plane Mask - use plane mask reg. Pixel Mask - use all ones. Patt Mask - use all ones. */ #define POLY_O GX_POLYG_OVERLAP #define POLY_N GX_POLYG_NONOVERLAP #define ROP_STANDARD (GX_PLANE_MASK |\ GX_PIXEL_ONES |\ GX_ATTR_SUPP |\ GX_RAST_BOOL |\ GX_PLOT_PLOT) /* fg = don't care bg = don't care */ #define ROP_BLIT(O,I) (ROP_STANDARD | \ GX_PATTERN_ONES |\ GX_ROP_11_1(I) |\ GX_ROP_11_0(O) |\ GX_ROP_10_1(I) |\ GX_ROP_10_0(O) |\ GX_ROP_01_1(I) |\ GX_ROP_01_0(O) |\ GX_ROP_00_1(I) |\ GX_ROP_00_0(O)) /* fg = fgPixel bg = don't care */ #define ROP_FILL(O,I) (ROP_STANDARD | \ GX_PATTERN_ONES |\ GX_ROP_11_1(I) |\ GX_ROP_11_0(I) |\ GX_ROP_10_1(I) |\ GX_ROP_10_0(I) | \ GX_ROP_01_1(O) |\ GX_ROP_01_0(O) |\ GX_ROP_00_1(O) |\ GX_ROP_00_0(O)) /* fg = fgPixel bg = don't care */ #define ROP_STIP(O,I) (ROP_STANDARD |\ GX_ROP_11_1(I) |\ GX_ROP_11_0(GX_ROP_NOOP) |\ GX_ROP_10_1(I) |\ GX_ROP_10_0(GX_ROP_NOOP) | \ GX_ROP_01_1(O) |\ GX_ROP_01_0(GX_ROP_NOOP) |\ GX_ROP_00_1(O) |\ GX_ROP_00_0(GX_ROP_NOOP)) /* fg = fgPixel bg = bgPixel */ #define ROP_OSTP(O,I) (ROP_STANDARD |\ GX_ROP_11_1(I) |\ GX_ROP_11_0(I) |\ GX_ROP_10_1(I) |\ GX_ROP_10_0(O) |\ GX_ROP_01_1(O) |\ GX_ROP_01_0(I) |\ GX_ROP_00_1(O) |\ GX_ROP_00_0(O)) #define ROP_ITXT(O,I) (ROP_STANDARD |\ GX_PATTERN_ONES |\ GX_ROP_11_1(I) |\ GX_ROP_11_0(I) |\ GX_ROP_10_1(I) |\ GX_ROP_10_0(O) |\ GX_ROP_01_1(O) |\ GX_ROP_01_0(I) |\ GX_ROP_00_1(O) |\ GX_ROP_00_0(O)) #define ROP_PTXT(O,I) (ROP_STANDARD |\ GX_PATTERN_ONES |\ GX_ROP_11_1(I) |\ GX_ROP_11_0(GX_ROP_NOOP) |\ GX_ROP_10_1(I) |\ GX_ROP_10_0(GX_ROP_NOOP) | \ GX_ROP_01_1(O) |\ GX_ROP_01_0(GX_ROP_NOOP) |\ GX_ROP_00_1(O) |\ GX_ROP_00_0(GX_ROP_NOOP)) static void sunGXDoBitblt(DrawablePtr, DrawablePtr, int, RegionPtr, DDXPointPtr, unsigned long); static RegionPtr sunGXCopyArea(DrawablePtr, DrawablePtr, GC *, int, int, int, int, int, int); static void sunGXCopyPlane1to8(DrawablePtr, DrawablePtr, int, RegionPtr, DDXPointPtr, unsigned long, unsigned long); static RegionPtr sunGXCopyPlane(DrawablePtr, DrawablePtr, GCPtr, int, int, int, int, int, int, unsigned long); static void sunGXFillRectAll(DrawablePtr, GCPtr, int, BoxPtr); static void sunGXPolyFillRect(DrawablePtr, GCPtr, int, xRectangle *); static void sunGXFillSpans(DrawablePtr, GCPtr, int, DDXPointPtr, int *, int); static void sunGXFillEllipse(DrawablePtr, sunGXPtr, xArc *); static void sunGXFillArcSlice(DrawablePtr, GCPtr, sunGXPtr, xArc *); static void sunGXPolyFillArc(DrawablePtr, GCPtr, int, xArc *); static void sunGXFillPoly1Rect(DrawablePtr, GCPtr, int, int, int, DDXPointPtr); static Uint gx_blit_rop_table[16]={ ROP_BLIT(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ ROP_BLIT(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ ROP_BLIT(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ ROP_BLIT(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ ROP_BLIT(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ ROP_BLIT(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ ROP_BLIT(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ ROP_BLIT(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ ROP_BLIT(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ ROP_BLIT(GX_ROP_SET, GX_ROP_SET), /* GXset */ }; /* rops for solid drawing with: Plane Mask - use plane mask reg. Pixel Mask - use all ones. Patt Mask - use all ones. */ static Uint gx_solid_rop_table[16]={ ROP_FILL(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ ROP_FILL(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ ROP_FILL(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ ROP_FILL(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ ROP_FILL(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ ROP_FILL(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ ROP_FILL(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ ROP_FILL(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ ROP_FILL(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ ROP_FILL(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ ROP_FILL(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ ROP_FILL(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ ROP_FILL(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ ROP_FILL(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ ROP_FILL(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ ROP_FILL(GX_ROP_SET, GX_ROP_SET), /* GXset */ }; static Uint gx_stipple_rop_table[16]={ ROP_STIP(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ ROP_STIP(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ ROP_STIP(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ ROP_STIP(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ ROP_STIP(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ ROP_STIP(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ ROP_STIP(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ ROP_STIP(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ ROP_STIP(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ ROP_STIP(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ ROP_STIP(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ ROP_STIP(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ ROP_STIP(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ ROP_STIP(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ ROP_STIP(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ ROP_STIP(GX_ROP_SET, GX_ROP_SET), /* GXset */ }; static Uint gx_opaque_stipple_rop_table[16]={ ROP_OSTP(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */ ROP_OSTP(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */ ROP_OSTP(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */ ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */ ROP_OSTP(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */ ROP_OSTP(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */ ROP_OSTP(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */ ROP_OSTP(GX_ROP_NOOP, GX_ROP_SET), /* GXor */ ROP_OSTP(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */ ROP_OSTP(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */ ROP_OSTP(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */ ROP_OSTP(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */ ROP_OSTP(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */ ROP_OSTP(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */ ROP_OSTP(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */ ROP_OSTP(GX_ROP_SET, GX_ROP_SET), /* GXset */ }; int sunGXScreenPrivateIndex; int sunGXGCPrivateIndex; int sunGXWindowPrivateIndex; int sunGXGeneration; /* sunGXDoBitBlt ============= Bit Blit for all window to window blits. */ static void sunGXDoBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask) { register sunGXPtr gx = sunGXGetScreenPrivate (pSrc->pScreen); register long r; register BoxPtr pboxTmp; register DDXPointPtr pptTmp; register int nbox; BoxPtr pboxNext,pboxBase,pbox; /* setup GX ( need fg of 0xff for blits ) */ GXBlitInit(gx,gx_blit_rop_table[alu]|POLY_O,planemask); pbox = REGION_RECTS(prgnDst); nbox = REGION_NUM_RECTS(prgnDst); /* need to blit rectangles in different orders, depending on the direction of copy so that an area isnt overwritten before it is blitted */ if( (pptSrc->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--; gx->x0=pptTmp->x; gx->y0=pptTmp->y; gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1; gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1; gx->x2=pboxTmp->x1; gx->y2=pboxTmp->y1; gx->x3=pboxTmp->x2-1; gx->y3=pboxTmp->y2-1; GXBlitDone(gx,r); } } 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 */ gx->x0=pptTmp->x; gx->y0=pptTmp->y; gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1; gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1; gx->x2=pboxTmp->x1; gx->y2=pboxTmp->y1; gx->x3=pboxTmp->x2-1; gx->y3=pboxTmp->y2-1; ++pboxTmp; ++pptTmp; GXBlitDone(gx,r); } 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; gx->x0=pptTmp->x; gx->y0=pptTmp->y; gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1; gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1; gx->x2=pboxTmp->x1; gx->y2=pboxTmp->y1; gx->x3=pboxTmp->x2-1; gx->y3=pboxTmp->y2-1; GXBlitDone(gx,r); } pboxBase = pboxNext; } } else{ /* dont need to change order of anything */ pptTmp=pptSrc; pboxTmp=pbox; while(nbox--){ gx->x0=pptTmp->x; gx->y0=pptTmp->y; gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1; gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1; gx->x2=pboxTmp->x1; gx->y2=pboxTmp->y1; gx->x3=pboxTmp->x2-1; gx->y3=pboxTmp->y2-1; pboxTmp++; pptTmp++; GXBlitDone(gx,r); } } } GXWait(gx,r); } static RegionPtr sunGXCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty) { if (pSrcDrawable->type != DRAWABLE_WINDOW) return cfbCopyArea (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); return cfbBitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, sunGXDoBitblt, 0); } static unsigned long copyPlaneFG, copyPlaneBG; static void sunGXCopyPlane1to8(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, int rop, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask, unsigned long bitPlane) { register sunGXPtr gx = sunGXGetScreenPrivate (pDstDrawable->pScreen); int srcx, srcy, dstx, dsty, width, height; int dstLastx, dstRightx; int xoffSrc, widthSrc, widthRest; int widthLast; unsigned long *psrcBase, *psrc; unsigned long bits, tmp; register int leftShift, rightShift; register int nl, nlMiddle; int nbox; BoxPtr pbox; register long r; GXDrawInit (gx, copyPlaneFG, gx_opaque_stipple_rop_table[rop]|GX_PATTERN_ONES, planemask); gx->bg = copyPlaneBG; gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1; cfbGetLongWidthAndPointer (pSrcDrawable, widthSrc, psrcBase) nbox = REGION_NUM_RECTS(prgnDst); pbox = REGION_RECTS(prgnDst); gx->incx = BITMAP_SCANLINE_UNIT; gx->incy = 0; 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 >> LOG2_BITMAP_PAD); dstLastx--; dstRightx = dstx + BITMAP_SCANLINE_UNIT - 1; nlMiddle = (width + BITMAP_SCANLINE_UNIT - 1) >> LOG2_BITMAP_PAD; widthLast = width & (BITMAP_SCANLINE_UNIT - 1); xoffSrc = srcx & ((1 << LOG2_BITMAP_PAD) - 1); leftShift = xoffSrc; rightShift = BITMAP_SCANLINE_UNIT - leftShift; widthRest = widthSrc - nlMiddle; if (widthLast) nlMiddle--; if (leftShift == 0) { while (height--) { gx->x0 = dstx; gx->x1 = dstRightx; gx->y0 = dsty++; nl = nlMiddle; while (nl--) gx->font = *psrc++; if (widthLast) { gx->x1 = dstLastx; #if BITMAP_SCANLINE_UNIT == 64 gx->font = (int)((*psrc++)>>32); #else gx->font = *psrc++; #endif } psrc += widthRest; } } else { widthRest--; while (height--) { gx->x0 = dstx; gx->x1 = dstRightx; gx->y0 = dsty++; bits = *psrc++; nl = nlMiddle; while (nl--) { tmp = BitLeft(bits, leftShift); bits = *psrc++; tmp |= BitRight(bits, rightShift); gx->font = tmp; } if (widthLast) { tmp = BitLeft(bits, leftShift); bits = *psrc++; tmp |= BitRight(bits, rightShift); gx->x1 = dstLastx; gx->font = tmp; } psrc += widthRest; } } } GXWait (gx, r); gx->incx = 0; gx->incy = 0; gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8; } static RegionPtr sunGXCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, unsigned long bitPlane) { RegionPtr ret; if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 8) { if (bitPlane == 1) { copyPlaneFG = pGC->fgPixel; copyPlaneBG = pGC->bgPixel; ret = cfbBitBlt (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, sunGXCopyPlane1to8, 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 = cfbCopyPlaneReduce (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, cfbCopyPlane8to1, bitPlane); pGC->alu = oldalu; } else { PixmapPtr pBitmap; ScreenPtr pScreen = pSrcDrawable->pScreen; GCPtr pGC1; 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) cfbCopyPlaneReduce (pSrcDrawable, (DrawablePtr) pBitmap, pGC1, srcx, srcy, width, height, 0, 0, cfbCopyPlane8to1, bitPlane); copyPlaneFG = pGC->fgPixel; copyPlaneBG = pGC->bgPixel; (void) cfbBitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC, 0, 0, width, height, dstx, dsty, sunGXCopyPlane1to8, 1); FreeScratchGC (pGC1); (*pScreen->DestroyPixmap) (pBitmap); /* compute resultant exposures */ ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty, bitPlane); } return ret; } static void sunGXFillRectAll(DrawablePtr pDrawable, GCPtr pGC, int nBox, BoxPtr pBox) { register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); register sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); register int r; GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask); if (gxPriv->stipple) GXStippleInit(gx,gxPriv->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); } #define NUM_STACK_RECTS 1024 static void sunGXPolyFillRect( DrawablePtr pDrawable, 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]; int numRects; int n; int xorg, yorg; prgnClip = pGC->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) sunGXFillRectAll(pDrawable, pGC, pboxClipped-pboxClippedBase, pboxClippedBase); if (pboxClippedBase != stackRects) DEALLOCATE_LOCAL(pboxClippedBase); } static void sunGXFillSpans( 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; register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC); register sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); register int r; BoxPtr extents; GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask) if (gxPriv->stipple) GXStippleInit(gx,gxPriv->stipple); if (devPriv->oneRect) { extents = &pGC->pCompositeClip->extents; GXSetClip (gx, extents); } else { nTmp = n * miFindMaxBand(pGC->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(pGC->pCompositeClip, ppt, pwidth, n, pptFree, pwidthFree, fSorted); pwidth = pwidthFree; ppt = pptFree; } while (n--) { x = ppt->x; y = ppt->y; ppt++; width = *pwidth++; if (width) { sunGXFillSpan(gx,y,x,x + width - 1,r); } } GXWait(gx,r); if (devPriv->oneRect) { GXResetClip (gx, pDrawable->pScreen); } else { DEALLOCATE_LOCAL(pptFree); DEALLOCATE_LOCAL(pwidthFree); } } #ifdef NOTDEF /* cfb is faster for dots */ void sunGXPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, xPoint *pptInit) { register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); RegionPtr cclip; int nbox; register int i; register BoxPtr pbox; cfbPrivGCPtr devPriv; xPoint *ppt; int x, y; int r; int off; devPriv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr); if (devPriv->rop == GXnoop) return; cclip = pGC->pCompositeClip; GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu],pGC->planemask); gx->offx = pDrawable->x; gx->offy = pDrawable->y; for (nbox = REGION_NUM_RECTS(cclip), pbox = REGION_RECTS(cclip); --nbox >= 0; pbox++) { sunGXSetClip(gx,pbox); if (mode != CoordModeOrigin) { x = 0; y = 0; for (ppt = pptInit, i = npt; --i >= 0;) { gx->apointy = y += ppt->y; gx->apointx = x += ppt->x; ++ppt; GXDrawDone(gx,r); } } else { for (ppt = pptInit, i = npt; --i >= 0;) { gx->apointy = ppt->y; gx->apointx = ppt->x; ++ppt; GXDrawDone(gx,r); } } } GXWait(gx,r); GXResetOff (gx); GXResetClip(gx,pDrawable->pScreen); } #endif #include "mifillarc.h" #define FILLSPAN(gx,y,x1,x2,r) {\ if (x2 >= x1) {\ sunGXFillSpan(gx,y,x1,x2,r) \ } \ } #define FILLSLICESPANS(flip,y) \ if (!flip) \ { \ FILLSPAN(gx,y,xl,xr,r) \ } \ else \ { \ xc = xorg - x; \ FILLSPAN(gx, y, xc, xr, r) \ xc += slw - 1; \ FILLSPAN(gx, y, xl, xc, r) \ } static void sunGXFillEllipse(DrawablePtr pDraw, sunGXPtr gx, xArc *arc) { 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; sunGXFillSpan (gx,y_top,xpos,xpos+slw - 1,r); if (miFillArcLower(slw)) sunGXFillSpan (gx,y_bot,xpos,xpos+slw - 1,r); } } static void sunGXFillArcSlice(DrawablePtr pDraw, GCPtr pGC, sunGXPtr gx, xArc *arc) { 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 FAST_CIRCLES #ifdef FAST_CIRCLES #if (BITMAP_BIT_ORDER == MSBFirst) #define Bits32(v) (v) #define Bits16(v) (v) #define Bits8(v) (v) #else #define FlipBits2(a) ((((a) & 0x1) << 1) | (((a) & 0x2) >> 1)) #define FlipBits4(a) ((FlipBits2(a) << 2) | FlipBits2(a >> 2)) #define FlipBits8(a) ((FlipBits4(a) << 4) | FlipBits4(a >> 4)) #define FlipBits16(a) ((FlipBits8(a) << 8) | FlipBits8(a >> 8)) #define FlipBits32(a) ((FlipBits16(a) << 16) | FlipBits16(a >> 16)) #define Bits32(v) FlipBits32(v) #define Bits16(v) FlipBits16(v) #define Bits8(v) FlipBits8(v) #endif #define B(x) Bits16(x) #define DO_FILLED_ARCS #include "circleset.h" #undef B #undef Bits8 #undef Bits16 #undef Bits32 #define UNSET_CIRCLE if (old_width) \ { \ gx->alu = gx_solid_rop_table[pGC->alu]; \ old_width = -old_width; \ } #else #define UNSET_CIRCLE #endif static void sunGXPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs) { register xArc *arc; register int i; int x, y; BoxRec box; BoxPtr extents = NULL; RegionPtr cclip; register sunGXPtr gx = sunGXGetScreenPrivate (pDraw->pScreen); sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); cfbPrivGCPtr devPriv; register int r; #ifdef FAST_CIRCLES int old_width = 0; #endif GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask); if (gxPriv->stipple) GXStippleInit(gx,gxPriv->stipple); devPriv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr); cclip = pGC->pCompositeClip; GXSetOff(gx,pDraw->x,pDraw->y) if (devPriv->oneRect) { extents = &cclip->extents; GXSetClip(gx,extents); } for (arc = parcs, i = narcs; --i >= 0; arc++) { if (miFillArcEmpty(arc)) continue; if (miCanFillArc(arc)) { x = arc->x; y = arc->y; if (!devPriv->oneRect) { 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 (devPriv->oneRect || RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN) { if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE)) { #ifdef FAST_CIRCLES /* who really needs fast filled circles? */ if (arc->width == arc->height && arc->width <= 16 && !gxPriv->stipple) { int offx, offy; if (arc->width != old_width) { int i; Uint *sp; VUint *dp; if (old_width != -arc->width) { sp = (Uint *) filled_arcs[arc->width-1]; dp = gx->pattern; i = 8; while (i--) dp[i] = sp[i]; } gx->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK; old_width = arc->width; } offx = 16 - ((x + pDraw->x) & 0x0f); offy = 16 - ((y + pDraw->y) & 0x0f); gx->patalign = (offx << 16) | offy; gx->arecty = y; gx->arectx = x; gx->arecty = y + old_width-1; gx->arectx = x + old_width-1; GXDrawDone (gx, r); } else #endif { UNSET_CIRCLE sunGXFillEllipse (pDraw, gx, arc); } } else { UNSET_CIRCLE sunGXFillArcSlice (pDraw, pGC, gx, arc); } continue; } } UNSET_CIRCLE GXWait (gx,r); GXResetOff (gx); if (devPriv->oneRect) GXResetClip (gx, pDraw->pScreen); miPolyFillArc(pDraw, pGC, 1, arc); GXSetOff (gx, pDraw->x, pDraw->y); if (devPriv->oneRect) GXSetClip (gx, extents); } GXWait (gx, r); GXResetOff (gx); if (devPriv->oneRect) GXResetClip (gx, pDraw->pScreen); } static void sunGXFillPoly1Rect(DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr ptsIn) { BoxPtr extents; int x1, x2, x3, x4; int y1, y2, y3, y4; sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); int r; typedef struct { Uint x; Uint y; Uint z; } GXPointRec, *GXPointPtr; GXPointPtr tri, qua; if (count < 3) return; if (shape != Convex && count > 4) { miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn); return; } GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask); if (gxPriv->stipple) GXStippleInit(gx,gxPriv->stipple); extents = &pGC->pCompositeClip->extents; GXSetOff(gx,pDrawable->x, pDrawable->y); GXSetClip(gx,extents); if (mode == CoordModeOrigin) { tri = (GXPointPtr) &gx->atrix; qua = (GXPointPtr) &gx->aquadx; } else { tri = (GXPointPtr) &gx->rtrix; qua = (GXPointPtr) &gx->rquadx; } if (count == 3) { gx->apointy = ptsIn[0].y; gx->apointx = ptsIn[0].x; tri->y = ptsIn[1].y; tri->x = ptsIn[1].x; tri->y = ptsIn[2].y; tri->x = ptsIn[2].x; GXDrawDone (gx, r); } else if (count == 4) { gx->apointy = ptsIn[0].y; gx->apointx = ptsIn[0].x; qua->y = ptsIn[1].y; qua->x = ptsIn[1].x; qua->y = ptsIn[2].y; qua->x = ptsIn[2].x; qua->y = ptsIn[3].y; qua->x = ptsIn[3].x; GXDrawDone (gx, r); if (r < 0 && shape != Convex) { GXWait(gx,r); GXResetOff(gx); GXResetClip(gx,pDrawable->pScreen); miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn); return; } } else { y1 = ptsIn[0].y; x1 = ptsIn[0].x; y2 = ptsIn[1].y; x2 = ptsIn[1].x; count -= 2; ptsIn += 2; while (count) { x3 = ptsIn->x; y3 = ptsIn->y; ptsIn++; count--; gx->apointy = y1; gx->apointx = x1; if (count == 0) { tri->y = y2; tri->x = x2; tri->y = y3; tri->x = x3; } else { y4 = ptsIn->y; x4 = ptsIn->x; ptsIn++; count--; qua->y = y2; qua->x = x2; qua->y = y3; qua->x = x3; qua->y = y4; qua->x = x4; if (mode == CoordModeOrigin) { x2 = x4; y2 = y4; } else { x2 = x2 + x3 + x4; y2 = y2 + y3 + y4; } } GXDrawDone (gx, r); } } GXWait(gx,r); GXResetOff(gx); GXResetClip(gx,pDrawable->pScreen); } /* * Note that the GX does not allow CapNotLast, so the code fakes it. This is * expensive to do as the GX is asynchronous and must be synced with GXWait * before fetching and storing the final line point. If only the hardware was * designed for X. */ /* hard code the screen width; otherwise we'd have to check or mul */ #define WIDTH_MUL(y) (((y) << 10) + ((y) << 7)) #define GX_WIDTH 1152 #define WID_OK(s) ((s)->width == GX_WIDTH) void sunGXPolySeg1Rect(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg) { sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); BoxPtr extents; int x, y; int r; unsigned char *baseAddr, *loAddr, *hiAddr, *saveAddr = 0, save = 0; GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask); if (gxPriv->stipple) GXStippleInit(gx,gxPriv->stipple); GXSetOff (gx, pDrawable->x, pDrawable->y); extents = &pGC->pCompositeClip->extents; GXSetClip (gx, extents); if (pGC->capStyle == CapNotLast) { sunGXGetAddrRange(pDrawable,extents,baseAddr,loAddr,hiAddr); while (nseg--) { gx->aliney = pSeg->y1; gx->alinex = pSeg->x1; y = pSeg->y2; x = pSeg->x2; saveAddr = baseAddr + WIDTH_MUL(y) + x; if (saveAddr < loAddr || hiAddr < saveAddr) saveAddr = 0; else save = *saveAddr; gx->aliney = y; gx->alinex = x; GXDrawDone (gx, r); if (saveAddr) { GXWait(gx,r); *saveAddr = save; } pSeg++; } } else { while (nseg--) { gx->aliney = pSeg->y1; gx->alinex = pSeg->x1; gx->aliney = pSeg->y2; gx->alinex = pSeg->x2; pSeg++; GXDrawDone (gx, r); } } GXWait (gx, r); GXResetOff (gx); GXResetClip (gx, pDrawable->pScreen); } void sunGXPolylines1Rect(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt) { sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); BoxPtr extents; unsigned char *baseAddr, *loAddr, *hiAddr, *saveAddr, save = 0; int r; Bool careful; Bool capNotLast; if (!--npt) return; GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask); if (gxPriv->stipple) GXStippleInit(gx,gxPriv->stipple); careful = ((pGC->alu & 0xc) == 0x8 || (pGC->alu & 0x3) == 0x2); capNotLast = pGC->capStyle == CapNotLast; extents = &pGC->pCompositeClip->extents; GXSetOff (gx, pDrawable->x, pDrawable->y); GXSetClip (gx, extents); if (careful) { int x, y; sunGXGetAddrRange (pDrawable, extents, baseAddr, loAddr, hiAddr); gx->apointy = y = ppt->y; gx->apointx = x = ppt->x; ppt++; while (npt--) { if (mode == CoordModeOrigin) { y = ppt->y; x = ppt->x; } else { y += ppt->y; x += ppt->x; } ppt++; saveAddr = baseAddr + WIDTH_MUL(y) + x; if (saveAddr < loAddr || hiAddr < saveAddr) saveAddr = 0; else save = *saveAddr; gx->aliney = y; gx->alinex = x; GXDrawDone (gx, r); if (saveAddr) { GXWait(gx,r); *saveAddr = save; } } GXWait(gx,r); } else { int x, y; if (capNotLast) npt--; if (mode == CoordModeOrigin) { x = y = 0; gx->apointy = ppt->y; gx->apointx = ppt->x; ppt++; while (npt--) { gx->aliney = ppt->y; gx->alinex = ppt->x; ++ppt; GXDrawDone(gx,r); } } else { y = gx->apointy = ppt->y; x = gx->apointx = ppt->x; ppt++; while (npt--) { y += gx->rliney = ppt->y; x += gx->rlinex = ppt->x; ++ppt; GXDrawDone(gx,r); } } if (capNotLast) { sunGXGetAddrRange (pDrawable, extents, baseAddr, loAddr, hiAddr); x += ppt->x; y += ppt->y; saveAddr = baseAddr + WIDTH_MUL(y) + x; if (saveAddr < loAddr || hiAddr < saveAddr) saveAddr = 0; else save = *saveAddr; gx->aliney = y; gx->alinex = x; GXDrawDone(gx,r); GXWait(gx,r); if (saveAddr) *saveAddr = save; } else { GXWait(gx,r); } } GXResetOff (gx); GXResetClip (gx, pDrawable->pScreen); } void sunGXPolyFillRect1Rect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect) { sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); BoxPtr extents = &pGC->pCompositeClip->extents; int r; int x, y; GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask); if (gxPriv->stipple) GXStippleInit(gx,gxPriv->stipple); GXSetOff (gx, pDrawable->x, pDrawable->y); GXSetClip (gx, extents); while (nrect--) { gx->arecty = y = prect->y; gx->arectx = x = prect->x; gx->arecty = y + (int) prect->height; gx->arectx = x + (int) prect->width; prect++; GXDrawDone (gx, r); } GXWait (gx, r); GXResetOff (gx); GXResetClip (gx, pDrawable->pScreen); } static void sunGXPolyGlyphBlt( DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, /* array of character info */ void *pglyphBase ) { sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); int h; int w; CharInfoPtr pci; unsigned int *bits; register int r; RegionPtr clip; BoxPtr extents; BoxRec box; clip = pGC->pCompositeClip; extents = &clip->extents; if (REGION_NUM_RECTS(clip) == 1) { GXSetClip (gx, extents); } else { /* 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: cfbPolyGlyphBlt8 (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); case rgnOUT: return; } } GXDrawInit (gx, pGC->fgPixel, gx_stipple_rop_table[pGC->alu]|GX_PATTERN_ONES|POLY_N, pGC->planemask); gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1; x += pDrawable->x; y += pDrawable->y; while (nglyph--) { pci = *ppci++; gx->incx = 0; gx->incy = 1; gx->x0 = x + pci->metrics.leftSideBearing; gx->x1 = (x + pci->metrics.rightSideBearing) - 1; gx->y0 = y - pci->metrics.ascent; h = pci->metrics.ascent + pci->metrics.descent; bits = (unsigned int *) pci->bits; while (h--) { gx->font = *bits++; } x += pci->metrics.characterWidth; } GXWait (gx, r); gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8; GXResetClip (gx, pDrawable->pScreen); } static void sunGXTEGlyphBlt( DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, /* array of character info */ void *pglyphBase /* start of array of glyphs */ ) { sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); int h, hTmp; FontPtr pfont = pGC->font; register int r; unsigned int *char1, *char2, *char3, *char4; int widthGlyphs, widthGlyph; BoxRec bbox; BoxPtr extents; RegionPtr clip; unsigned long rop; widthGlyph = FONTMAXBOUNDS(pfont,characterWidth); h = FONTASCENT(pfont) + FONTDESCENT(pfont); clip = pGC->pCompositeClip; extents = &clip->extents; if (REGION_NUM_RECTS(clip) == 1) { GXSetClip (gx, extents); } else { 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) cfbPolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, NULL); else miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); case rgnOUT: return; } } rop = gx_opaque_stipple_rop_table[GXcopy] | GX_PATTERN_ONES; if (pglyphBase) rop = gx_stipple_rop_table[pGC->alu] | GX_PATTERN_ONES; GXDrawInit (gx, pGC->fgPixel, rop, pGC->planemask); gx->bg = pGC->bgPixel; gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1; y = y + pDrawable->y - FONTASCENT(pfont); x += pDrawable->x; #define LoopIt(count, w, loadup, fetch) \ while (nglyph >= count) \ { \ nglyph -= count; \ gx->incx = 0; \ gx->incy = 1; \ gx->x0 = x; \ gx->x1 = (x += w) - 1; \ gx->y0 = y; \ loadup \ hTmp = h; \ while (hTmp--) \ gx->font = fetch; \ } if (widthGlyph <= 8) { widthGlyphs = widthGlyph << 2; LoopIt(4, widthGlyphs, char1 = (unsigned int *) (*ppci++)->bits; char2 = (unsigned int *) (*ppci++)->bits; char3 = (unsigned int *) (*ppci++)->bits; char4 = (unsigned int *) (*ppci++)->bits;, (*char1++ | ((*char2++ | ((*char3++ | (*char4++ >> widthGlyph)) >> widthGlyph)) >> widthGlyph))) } else if (widthGlyph <= 10) { widthGlyphs = (widthGlyph << 1) + widthGlyph; LoopIt(3, widthGlyphs, char1 = (unsigned int *) (*ppci++)->bits; char2 = (unsigned int *) (*ppci++)->bits; char3 = (unsigned int *) (*ppci++)->bits;, (*char1++ | ((*char2++ | (*char3++ >> widthGlyph)) >> widthGlyph))) } else if (widthGlyph <= 16) { widthGlyphs = widthGlyph << 1; LoopIt(2, widthGlyphs, char1 = (unsigned int *) (*ppci++)->bits; char2 = (unsigned int *) (*ppci++)->bits;, (*char1++ | (*char2++ >> widthGlyph))) } while (nglyph--) { gx->incx = 0; gx->incy = 1; gx->x0 = x; gx->x1 = (x += widthGlyph) - 1; gx->y0 = y; char1 = (unsigned int *) (*ppci++)->bits; hTmp = h; while (hTmp--) gx->font = *char1++; } gx->incx = 0; gx->incy = 0; GXWait (gx, r); gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8; GXResetClip (gx, pDrawable->pScreen); } static void sunGXPolyTEGlyphBlt( DrawablePtr pDrawable, GCPtr pGC, int x, int y, unsigned int nglyph, CharInfoPtr *ppci, /* array of character info */ void *pglyphBase /* start of array of glyphs */ ) { sunGXTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1); } static void sunGXFillBoxSolid(DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel) { register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); register int r; GXDrawInit(gx,pixel,gx_solid_rop_table[GXcopy]|POLY_N,~0); 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); } void sunGXFillBoxStipple(DrawablePtr pDrawable, int nBox, BoxPtr pBox, sunGXStipplePtr stipple) { register sunGXPtr gx = sunGXGetScreenPrivate (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); } Bool sunGXCheckTile(PixmapPtr pPixmap, sunGXStipplePtr 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; } Bool sunGXCheckStipple(PixmapPtr pPixmap, sunGXStipplePtr stipple) { unsigned short *sbits; unsigned int *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 int *) 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 sunGXStipplePtr tmpStipple; Bool sunGXCheckFill(GCPtr pGC, DrawablePtr pDrawable) { sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); sunGXStipplePtr stipple; Uint alu; int xrot, yrot; if (pGC->fillStyle == FillSolid) { if (gxPriv->stipple) { free (gxPriv->stipple); gxPriv->stipple = 0; } return TRUE; } if (!(stipple = gxPriv->stipple)) { if (!tmpStipple) { tmpStipple = malloc (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 (!sunGXCheckTile (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 (!sunGXCheckStipple (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; } void sunGXValidateGC(GCPtr, Mask, DrawablePtr); void sunGXDestroyGC(GCPtr); GCFuncs sunGXGCFuncs = { sunGXValidateGC, miChangeGC, miCopyGC, sunGXDestroyGC, miChangeClip, miDestroyClip, miCopyClip }; GCOps sunGXTEOps1Rect = { sunGXFillSpans, cfbSetSpans, cfbPutImage, sunGXCopyArea, sunGXCopyPlane, cfbPolyPoint, sunGXPolylines1Rect, sunGXPolySeg1Rect, miPolyRectangle, cfbZeroPolyArcSS8Copy, sunGXFillPoly1Rect, sunGXPolyFillRect1Rect, sunGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, sunGXTEGlyphBlt, sunGXPolyTEGlyphBlt, cfbPushPixels8 #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps sunGXTEOps = { sunGXFillSpans, cfbSetSpans, cfbPutImage, sunGXCopyArea, sunGXCopyPlane, cfbPolyPoint, cfbLineSS, cfbSegmentSS, miPolyRectangle, cfbZeroPolyArcSS8Copy, miFillPolygon, sunGXPolyFillRect, sunGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, sunGXTEGlyphBlt, sunGXPolyTEGlyphBlt, cfbPushPixels8 #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps sunGXNonTEOps1Rect = { sunGXFillSpans, cfbSetSpans, cfbPutImage, sunGXCopyArea, sunGXCopyPlane, cfbPolyPoint, sunGXPolylines1Rect, sunGXPolySeg1Rect, miPolyRectangle, cfbZeroPolyArcSS8Copy, sunGXFillPoly1Rect, sunGXPolyFillRect1Rect, sunGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, miImageGlyphBlt, sunGXPolyGlyphBlt, cfbPushPixels8 #ifdef NEED_LINEHELPER ,NULL #endif }; GCOps sunGXNonTEOps = { sunGXFillSpans, cfbSetSpans, cfbPutImage, sunGXCopyArea, sunGXCopyPlane, cfbPolyPoint, cfbLineSS, cfbSegmentSS, miPolyRectangle, cfbZeroPolyArcSS8Copy, miFillPolygon, sunGXPolyFillRect, sunGXPolyFillArc, miPolyText8, miPolyText16, miImageText8, miImageText16, miImageGlyphBlt, sunGXPolyGlyphBlt, cfbPushPixels8 #ifdef NEED_LINEHELPER ,NULL #endif }; #define FONTWIDTH(font) (FONTMAXBOUNDS(font,rightSideBearing) - \ FONTMINBOUNDS(font,leftSideBearing)) GCOps * sunGXMatchCommon(GCPtr pGC, cfbPrivGCPtr devPriv) { 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 (!WID_OK(pGC->pScreen)) return 0; if (pGC->font && FONTWIDTH (pGC->font) <= 32 && FONTMINBOUNDS(pGC->font,characterWidth) >= 0) { if (TERMINALFONT(pGC->font)) if (devPriv->oneRect) return &sunGXTEOps1Rect; else return &sunGXTEOps; else if (devPriv->oneRect) return &sunGXNonTEOps1Rect; else return &sunGXNonTEOps; } return 0; } void sunGXValidateGC(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; sunGXPrivGCPtr gxPriv; int oneRect; int canGX; int widOK; gxPriv = sunGXGetGCPrivate (pGC); widOK = WID_OK(pGC->pScreen); if (pDrawable->type != DRAWABLE_WINDOW) { if (gxPriv->type == DRAWABLE_WINDOW) { extern GCOps cfbNonTEOps; miDestroyGCOps (pGC->ops); pGC->ops = &cfbNonTEOps; changes = (1 << (GCLastBit + 1)) - 1; pGC->stateChanges = changes; gxPriv->type = pDrawable->type; } cfbValidateGC (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); oneRect = REGION_NUM_RECTS(pGC->pCompositeClip) == 1; if (oneRect != devPriv->oneRect) { new_line = TRUE; new_fillarea = TRUE; devPriv->oneRect = oneRect; } } 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 (!sunGXCheckFill (pGC, pDrawable)) { switch (pGC->fillStyle) { case FillTiled: if (!pGC->tileIsPixel) { int width = pGC->tile.pixmap->drawable.width * PSZ; if ((width <= 32) && !(width & (width - 1))) { cfbCopyRotatePixmap(pGC->tile.pixmap, &pGC->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, &pGC->pRotatedPixmap, xrot, yrot); new_pix = TRUE; } } break; } } if (!new_pix && pGC->pRotatedPixmap) { cfbDestroyPixmap(pGC->pRotatedPixmap); pGC->pRotatedPixmap = NULL; } } if (new_rrop) { int old_rrop; 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; } } old_rrop = devPriv->rop; devPriv->rop = cfbReduceRasterOp (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 = sunGXMatchCommon (pGC, devPriv))) { 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 (devPriv->oneRect && canGX) pGC->ops->FillPolygon = sunGXFillPoly1Rect; if (pGC->lineWidth == 0) { if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)) { switch (devPriv->rop) { case GXxor: pGC->ops->PolyArc = cfbZeroPolyArcSS8Xor; break; case GXcopy: pGC->ops->PolyArc = cfbZeroPolyArcSS8Copy; break; default: pGC->ops->PolyArc = cfbZeroPolyArcSS8General; 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 (devPriv->oneRect && canGX && widOK) { pGC->ops->PolySegment = sunGXPolySeg1Rect; pGC->ops->Polylines = sunGXPolylines1Rect; } else if (pGC->fillStyle == FillSolid) { if (devPriv->oneRect) { pGC->ops->Polylines = cfb8LineSS1Rect; pGC->ops->PolySegment = cfb8SegmentSS1Rect; } else { pGC->ops->Polylines = cfbLineSS; pGC->ops->PolySegment = cfbSegmentSS; } } 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 = cfbLineSD; pGC->ops->PolySegment = cfbSegmentSD; } 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 = sunGXPolyTEGlyphBlt; else pGC->ops->PolyGlyphBlt = sunGXPolyGlyphBlt; } else pGC->ops->PolyGlyphBlt = miPolyGlyphBlt; /* special case ImageGlyphBlt for terminal emulator fonts */ if (TERMINALFONT(pGC->font)) pGC->ops->ImageGlyphBlt = sunGXTEGlyphBlt; else pGC->ops->ImageGlyphBlt = miImageGlyphBlt; } } if (new_fillspans) { if (canGX) pGC->ops->FillSpans = sunGXFillSpans; else switch (pGC->fillStyle) { case FillTiled: if (pGC->pRotatedPixmap) { if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK) pGC->ops->FillSpans = cfbTile32FSCopy; else pGC->ops->FillSpans = cfbTile32FSGeneral; } else pGC->ops->FillSpans = cfbUnnaturalTileFS; break; case FillStippled: if (pGC->pRotatedPixmap) pGC->ops->FillSpans = cfb8Stipple32FS; else pGC->ops->FillSpans = cfbUnnaturalStippleFS; break; case FillOpaqueStippled: if (pGC->pRotatedPixmap) pGC->ops->FillSpans = cfb8OpaqueStipple32FS; else pGC->ops->FillSpans = cfbUnnaturalStippleFS; break; default: FatalError("cfbValidateGC: illegal fillStyle\n"); } } /* end of new_fillspans */ if (new_fillarea) { pGC->ops->PolyFillRect = cfbPolyFillRect; pGC->ops->PolyFillArc = miPolyFillArc; if (canGX) { pGC->ops->PolyFillArc = sunGXPolyFillArc; pGC->ops->PolyFillRect = sunGXPolyFillRect; if (devPriv->oneRect) pGC->ops->PolyFillRect = sunGXPolyFillRect1Rect; } pGC->ops->PushPixels = mfbPushPixels; if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy) pGC->ops->PushPixels = cfbPushPixels8; } } void sunGXDestroyGC(GCPtr pGC) { sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); if (gxPriv->stipple) xfree (gxPriv->stipple); miDestroyGC (pGC); } Bool sunGXCreateGC(GCPtr pGC) { sunGXPrivGCPtr gxPriv; if (pGC->depth == 1) return mfbCreateGC (pGC); if (!cfbCreateGC (pGC)) return FALSE; pGC->ops = &sunGXNonTEOps; pGC->funcs = &sunGXGCFuncs; gxPriv = sunGXGetGCPrivate(pGC); gxPriv->type = DRAWABLE_WINDOW; gxPriv->stipple = 0; return TRUE; } Bool sunGXCreateWindow(WindowPtr pWin) { if (!cfbCreateWindow (pWin)) return FALSE; pWin->devPrivates[sunGXWindowPrivateIndex].ptr = 0; return TRUE; } Bool sunGXDestroyWindow(WindowPtr pWin) { sunGXStipplePtr stipple = sunGXGetWindowPrivate(pWin); xfree (stipple); return cfbDestroyWindow (pWin); } Bool sunGXChangeWindowAttributes(WindowPtr pWin, Mask mask) { sunGXStipplePtr stipple; 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)) { cfbXRotatePixmap(pPrivWin->pRotatedBorder, pWin->drawable.x - pPrivWin->oldRotate.x); cfbYRotatePixmap(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: stipple = sunGXGetWindowPrivate(pWin); if (pWin->backgroundState == None || pWin->backgroundState == ParentRelative) { pPrivWin->fastBackground = FALSE; if (stipple) { xfree (stipple); sunGXSetWindowPrivate(pWin,0); } /* Rotate border to match parent origin */ if (pWin->backgroundState == ParentRelative && pPrivWin->pRotatedBorder) { for (pBgWin = pWin->parent; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfbXRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.x - pPrivWin->oldRotate.x); cfbYRotatePixmap(pPrivWin->pRotatedBorder, pBgWin->drawable.y - pPrivWin->oldRotate.y); } break; } if (!stipple) { if (!tmpStipple) tmpStipple = malloc (sizeof *tmpStipple); stipple = tmpStipple; } if (stipple && sunGXCheckTile (pWin->background.pixmap, stipple)) { stipple->alu = gx_opaque_stipple_rop_table[GXcopy]|GX_PATTERN_MASK; pPrivWin->fastBackground = FALSE; if (stipple == tmpStipple) { sunGXSetWindowPrivate(pWin, stipple); tmpStipple = 0; } break; } if ((stipple = sunGXGetWindowPrivate(pWin))) { xfree (stipple); sunGXSetWindowPrivate(pWin,0); } if (((width = (pWin->background.pixmap->drawable.width * PSZ)) <= BITMAP_SCANLINE_UNIT) && !(width & (width - 1))) { cfbCopyRotatePixmap(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)) <= BITMAP_SCANLINE_UNIT) && !(width & (width - 1))) { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfbCopyRotatePixmap(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 sunGXPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what) { register cfbPrivWin *pPrivWin; sunGXStipplePtr stipple; WindowPtr pBgWin; pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr); switch (what) { case PW_BACKGROUND: stipple = sunGXGetWindowPrivate(pWin); 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 (stipple) { sunGXFillBoxStipple ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), stipple); } else if (pPrivWin->fastBackground) { cfbFillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBackground); } else { cfbFillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixmap, (int) pWin->drawable.x, (int) pWin->drawable.y); } return; case BackgroundPixel: sunGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->background.pixel); return; } break; case PW_BORDER: if (pWin->borderIsPixel) { sunGXFillBoxSolid((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixel); return; } else if (pPrivWin->fastBorder) { cfbFillBoxTile32 ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pPrivWin->pRotatedBorder); return; } else { for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative; pBgWin = pBgWin->parent); cfbFillBoxTileOdd ((DrawablePtr)pWin, (int)REGION_NUM_RECTS(pRegion), REGION_RECTS(pRegion), pWin->border.pixmap, (int) pBgWin->drawable.x, (int) pBgWin->drawable.y); return; } break; } } void sunGXCopyWindow(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; } sunGXDoBitblt ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, GXcopy, prgnDst, pptSrc, ~0L); DEALLOCATE_LOCAL(pptSrc); REGION_DESTROY(pWin->drawable.pScreen, prgnDst); } Bool sunGXInit(ScreenPtr pScreen, fbFd *fb) { sunGXPtr gx; Uint mode; register long r; if (serverGeneration != sunGXGeneration) { sunGXScreenPrivateIndex = AllocateScreenPrivateIndex(); if (sunGXScreenPrivateIndex == -1) return FALSE; sunGXGCPrivateIndex = AllocateGCPrivateIndex (); sunGXWindowPrivateIndex = AllocateWindowPrivateIndex (); sunGXGeneration = serverGeneration; } if (!AllocateGCPrivate(pScreen, sunGXGCPrivateIndex, sizeof (sunGXPrivGCRec))) return FALSE; if (!AllocateWindowPrivate(pScreen, sunGXWindowPrivateIndex, 0)) return FALSE; gx = (sunGXPtr) fb->fb; mode = gx->mode; GXWait(gx,r); mode &= ~( GX_BLIT_ALL | GX_MODE_ALL | GX_DRAW_ALL | GX_BWRITE0_ALL | GX_BWRITE1_ALL | GX_BREAD_ALL | GX_BDISP_ALL); mode |= GX_BLIT_SRC | GX_MODE_COLOR8 | GX_DRAW_RENDER | GX_BWRITE0_ENABLE | GX_BWRITE1_DISABLE | GX_BREAD_0 | GX_BDISP_0; gx->mode = mode; gx->clip = 0; gx->offx = 0; gx->offy = 0; gx->clipminx = 0; gx->clipminy = 0; gx->clipmaxx = fb->info.fb_width - 1; gx->clipmaxy = fb->info.fb_height - 1; pScreen->devPrivates[sunGXScreenPrivateIndex].ptr = (void *) gx; /* * Replace various screen functions */ pScreen->CreateGC = sunGXCreateGC; pScreen->CreateWindow = sunGXCreateWindow; pScreen->ChangeWindowAttributes = sunGXChangeWindowAttributes; pScreen->DestroyWindow = sunGXDestroyWindow; pScreen->PaintWindowBackground = sunGXPaintWindow; pScreen->PaintWindowBorder = sunGXPaintWindow; pScreen->CopyWindow = sunGXCopyWindow; return TRUE; }