summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/sun/sunGX.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/sun/sunGX.c')
-rw-r--r--xc/programs/Xserver/hw/sun/sunGX.c2909
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;
+}