diff options
Diffstat (limited to 'xc/programs/Xserver/hw/sun/sunGX.c')
-rw-r--r-- | xc/programs/Xserver/hw/sun/sunGX.c | 2909 |
1 files changed, 2909 insertions, 0 deletions
diff --git a/xc/programs/Xserver/hw/sun/sunGX.c b/xc/programs/Xserver/hw/sun/sunGX.c new file mode 100644 index 000000000..7e6b6f7f1 --- /dev/null +++ b/xc/programs/Xserver/hw/sun/sunGX.c @@ -0,0 +1,2909 @@ +#ifndef lint +static char *rid="$TOG: sunGX.c /main/28 1998/02/10 13:16:33 kaleb $"; +#endif /* lint */ +/* +Copyright 1991, 1998 The Open Group + +All Rights Reserved. + +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.3 1998/10/04 09:38:36 dawes Exp $ */ + +#include "sun.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 "cfb/cfb.h" +#include "cfb/cfbmskbits.h" +#include "cfb/cfb8bit.h" +#include "fastblt.h" +#include "mergerop.h" +#include "sunGX.h" +#include "migc.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 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(pSrc, pDst, alu, prgnDst, pptSrc, planemask) + DrawablePtr pSrc, 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); +} + +RegionPtr +sunGXCopyArea(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; +{ + 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 (pSrcDrawable, pDstDrawable, rop, prgnDst, pptSrc, planemask, bitPlane) + 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, *psrcLine, *psrc; + unsigned long bits, tmp, lastTmp; + register int leftShift, rightShift; + register int nl, nlMiddle; + int nbox; + BoxPtr pbox; + register int 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 = 32; + 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 >> 5); + 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--; + 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; + gx->font = *psrc++; + } + 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; +} + +RegionPtr sunGXCopyPlane(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)(); + + 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 = cfbBitBlt (pSrcDrawable, pDstDrawable, + pGC, srcx, srcy, width, height, dstx, dsty, cfbCopyPlane8to1, 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) cfbBitBlt (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; +} + +void +sunGXFillRectAll (pDrawable, pGC, nBox, pBox) + 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 + +void +sunGXPolyFillRect(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]; + 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); +} + +void +sunGXFillSpans (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; + 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(pDrawable, pGC, mode, npt, pptInit) + 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 (pDraw, gx, arc) + 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 (pDraw, pGC, gx, arc) + 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 + +void +sunGXPolyFillArc (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; + 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) & 0xf; + offy = 16 - (y + pDraw->y) & 0xf; + 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); +} + +void +sunGXFillPoly1Rect (pDrawable, pGC, shape, mode, count, ptsIn) + DrawablePtr pDrawable; + GCPtr pGC; + int count; + DDXPointPtr ptsIn; +{ + int c; + BoxPtr extents; + int *endp; + 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 (pDrawable, pGC, nseg, pSeg) + 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; + + 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 (pDrawable, pGC, mode, npt, ppt) + 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; + 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) + { + x = y = 0; + npt--; + } + if (mode == CoordModeOrigin) + { + 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 (pDrawable, pGC, nrect, prect) + 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 (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; +{ + sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); + int h; + int w; + CharInfoPtr pci; + unsigned long *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 long *) 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 (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 */ +{ + sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen); + int h, hTmp; + int w; + FontPtr pfont = pGC->font; + register int r; + unsigned long *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 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))) + } + while (nglyph--) { + gx->incx = 0; + gx->incy = 1; + gx->x0 = x; + gx->x1 = (x += widthGlyph) - 1; + gx->y0 = y; + char1 = (unsigned long *) (*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 (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 */ +{ + sunGXTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1); +} + +static void +sunGXFillBoxSolid (pDrawable, nBox, pBox, pixel) + 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 (pDrawable, nBox, pBox, stipple) + 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); +} + +sunGXCheckTile (pPixmap, stipple) + 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; +} + +sunGXCheckStipple (pPixmap, stipple) + PixmapPtr pPixmap; + sunGXStipplePtr 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 sunGXStipplePtr tmpStipple; + +sunGXCheckFill (pGC, pDrawable) + GCPtr pGC; + DrawablePtr pDrawable; +{ + sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); + sunGXStipplePtr 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 = (sunGXStipplePtr) 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 (!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 (); +void sunGXDestroyGC (); + +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 (pGC, devPriv) + 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 (pGC, changes, pDrawable) + 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 = (PixmapPtr) 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 (pGC) + GCPtr pGC; +{ + sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC); + + if (gxPriv->stipple) + xfree (gxPriv->stipple); + miDestroyGC (pGC); +} + +sunGXCreateGC (pGC) + 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 (pWin) + WindowPtr pWin; +{ + if (!cfbCreateWindow (pWin)) + return FALSE; + pWin->devPrivates[sunGXWindowPrivateIndex].ptr = 0; + return TRUE; +} + +Bool +sunGXDestroyWindow (pWin) + WindowPtr pWin; +{ + sunGXStipplePtr stipple; + if (stipple = sunGXGetWindowPrivate(pWin)) + xfree (stipple); + return cfbDestroyWindow (pWin); +} + +sunGXChangeWindowAttributes (pWin, mask) + 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 = (sunGXStipplePtr) xalloc (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)) <= 32) && + !(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)) <= 32) && + !(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(pWin, pRegion, what) + 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(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; + } + + sunGXDoBitblt ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot, + GXcopy, prgnDst, pptSrc, ~0L); + DEALLOCATE_LOCAL(pptSrc); + REGION_DESTROY(pWin->drawable.pScreen, prgnDst); +} + +#if NeedFunctionPrototypes +sunGXInit ( + ScreenPtr pScreen, + fbFd *fb) +#else +sunGXInit (pScreen, fb) + ScreenPtr pScreen; + fbFd *fb; +#endif +{ + 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 = (pointer) 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; +} |