sunGX.c revision ee7c6486
1/*
2static char *rid="$Xorg: sunGX.c,v 1.5 2001/02/09 02:04:44 xorgcvs Exp $";
3 */
4/*
5Copyright 1991, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall not be
24used in advertising or otherwise to promote the sale, use or other dealings
25in this Software without prior written authorization from The Open Group.
26 *
27 * Author:  Keith Packard, MIT X Consortium
28 */
29
30/* $XFree86: xc/programs/Xserver/hw/sun/sunGX.c,v 1.9 2003/11/17 22:20:36 dawes Exp $ */
31
32#include	"sun.h"
33
34#include	<X11/Xmd.h>
35#include	"gcstruct.h"
36#include	"pixmapstr.h"
37#include	"regionstr.h"
38#include	"mistruct.h"
39#include	<X11/fonts/fontstruct.h>
40#include	"dixfontstr.h"
41#include	"fb.h"
42#include	"sunGX.h"
43#include	"migc.h"
44#include	"mispans.h"
45
46#define sunGXFillSpan(gx,y,x1,x2,r) {\
47    (gx)->apointy = (y); \
48    (gx)->apointx = (x1); \
49    (gx)->arectx = (x2); \
50    GXDrawDone(gx,r); \
51}
52
53#define GXSetClip(gx,pbox) {\
54    (gx)->clipminx = (pbox)->x1; \
55    (gx)->clipminy = (pbox)->y1; \
56    (gx)->clipmaxx = (pbox)->x2 - 1; \
57    (gx)->clipmaxy = (pbox)->y2 - 1; \
58}
59
60#define GXSetOff(gx,x,y) {\
61    (gx)->offx = (x); \
62    (gx)->offy = (y); \
63}
64
65#define GXResetClip(gx,pScreen) { \
66    (gx)->clipminx = 0; \
67    (gx)->clipminy = 0; \
68    (gx)->clipmaxx = (pScreen)->width - 1; \
69    (gx)->clipmaxy = (pScreen)->height - 1; \
70}
71
72#define GXResetOff(gx) {\
73    (gx)->offx = 0; \
74    (gx)->offy = 0; \
75}
76
77#define sunGXGetAddrRange(pDrawable,extents,base,lo,hi) {\
78    int	__x__; \
79    cfbGetWindowByteWidthAndPointer((WindowPtr)pDrawable,__x__,base); \
80    lo = (base) + WIDTH_MUL((extents)->y1) + (extents)->x1; \
81    hi = (base) + WIDTH_MUL((extents)->y2 - 1) + (extents)->x2 - 1; \
82    (base) = (base) + WIDTH_MUL(pDrawable->y) + pDrawable->x; \
83}
84
85/*
86   rop_tables
87   ==========
88   lookup tables for GX raster ops, with the plane_mask,pixel_mask,pattern_mask
89   ,attrib_sel, polygon_draw,raster_mode encoded into the top half.
90   There is a lookup table for each commonly used combination.
91*/
92
93/* rops for bit blit / copy area
94   with:
95       Plane Mask - use plane mask reg.
96       Pixel Mask - use all ones.
97       Patt  Mask - use all ones.
98*/
99
100#define POLY_O		GX_POLYG_OVERLAP
101#define POLY_N		GX_POLYG_NONOVERLAP
102
103#define ROP_STANDARD	(GX_PLANE_MASK |\
104			GX_PIXEL_ONES |\
105			GX_ATTR_SUPP |\
106			GX_RAST_BOOL |\
107			GX_PLOT_PLOT)
108
109/* fg = don't care  bg = don't care */
110
111#define ROP_BLIT(O,I)	(ROP_STANDARD | \
112			GX_PATTERN_ONES |\
113			GX_ROP_11_1(I) |\
114			GX_ROP_11_0(O) |\
115			GX_ROP_10_1(I) |\
116			GX_ROP_10_0(O) |\
117			GX_ROP_01_1(I) |\
118			GX_ROP_01_0(O) |\
119			GX_ROP_00_1(I) |\
120			GX_ROP_00_0(O))
121
122/* fg = fgPixel	    bg = don't care */
123
124#define ROP_FILL(O,I)	(ROP_STANDARD | \
125			GX_PATTERN_ONES |\
126			GX_ROP_11_1(I) |\
127			GX_ROP_11_0(I) |\
128			GX_ROP_10_1(I) |\
129			GX_ROP_10_0(I) | \
130			GX_ROP_01_1(O) |\
131			GX_ROP_01_0(O) |\
132			GX_ROP_00_1(O) |\
133			GX_ROP_00_0(O))
134
135/* fg = fgPixel	    bg = don't care */
136
137#define ROP_STIP(O,I)   (ROP_STANDARD |\
138			GX_ROP_11_1(I) |\
139			GX_ROP_11_0(GX_ROP_NOOP) |\
140			GX_ROP_10_1(I) |\
141			GX_ROP_10_0(GX_ROP_NOOP) | \
142			GX_ROP_01_1(O) |\
143			GX_ROP_01_0(GX_ROP_NOOP) |\
144			GX_ROP_00_1(O) |\
145			GX_ROP_00_0(GX_ROP_NOOP))
146
147/* fg = fgPixel	    bg = bgPixel */
148
149#define ROP_OSTP(O,I)   (ROP_STANDARD |\
150			GX_ROP_11_1(I) |\
151			GX_ROP_11_0(I) |\
152			GX_ROP_10_1(I) |\
153			GX_ROP_10_0(O) |\
154			GX_ROP_01_1(O) |\
155			GX_ROP_01_0(I) |\
156			GX_ROP_00_1(O) |\
157			GX_ROP_00_0(O))
158
159#define ROP_ITXT(O,I)   (ROP_STANDARD |\
160			GX_PATTERN_ONES |\
161			GX_ROP_11_1(I) |\
162			GX_ROP_11_0(I) |\
163			GX_ROP_10_1(I) |\
164			GX_ROP_10_0(O) |\
165			GX_ROP_01_1(O) |\
166			GX_ROP_01_0(I) |\
167			GX_ROP_00_1(O) |\
168			GX_ROP_00_0(O))
169
170#define ROP_PTXT(O,I)   (ROP_STANDARD |\
171			GX_PATTERN_ONES |\
172			GX_ROP_11_1(I) |\
173			GX_ROP_11_0(GX_ROP_NOOP) |\
174			GX_ROP_10_1(I) |\
175			GX_ROP_10_0(GX_ROP_NOOP) | \
176			GX_ROP_01_1(O) |\
177			GX_ROP_01_0(GX_ROP_NOOP) |\
178			GX_ROP_00_1(O) |\
179			GX_ROP_00_0(GX_ROP_NOOP))
180
181static void sunGXDoBitblt(DrawablePtr, DrawablePtr, int, RegionPtr, DDXPointPtr, unsigned long);
182static RegionPtr sunGXCopyArea(DrawablePtr, DrawablePtr, GC *, int, int, int, int, int, int);
183static void sunGXCopyPlane1to8(DrawablePtr, DrawablePtr, int, RegionPtr, DDXPointPtr, unsigned long, unsigned long);
184static RegionPtr sunGXCopyPlane(DrawablePtr, DrawablePtr, GCPtr, int, int, int, int, int, int, unsigned long);
185static void sunGXFillRectAll(DrawablePtr, GCPtr, int, BoxPtr);
186static void sunGXPolyFillRect(DrawablePtr, GCPtr, int, xRectangle *);
187static void sunGXFillSpans(DrawablePtr, GCPtr, int, DDXPointPtr, int *, int);
188static void sunGXFillEllipse(DrawablePtr, sunGXPtr, xArc *);
189static void sunGXFillArcSlice(DrawablePtr, GCPtr, sunGXPtr, xArc *);
190static void sunGXPolyFillArc(DrawablePtr, GCPtr, int, xArc *);
191static void sunGXFillPoly1Rect(DrawablePtr, GCPtr, int, int, int, DDXPointPtr);
192
193static Uint gx_blit_rop_table[16]={
194    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
195    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
196    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
197    ROP_BLIT(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
198    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
199    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
200    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
201    ROP_BLIT(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
202    ROP_BLIT(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
203    ROP_BLIT(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
204    ROP_BLIT(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
205    ROP_BLIT(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
206    ROP_BLIT(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
207    ROP_BLIT(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
208    ROP_BLIT(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
209    ROP_BLIT(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
210};
211
212/* rops for solid drawing
213   with:
214       Plane Mask - use plane mask reg.
215       Pixel Mask - use all ones.
216       Patt  Mask - use all ones.
217*/
218
219static Uint gx_solid_rop_table[16]={
220    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
221    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
222    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
223    ROP_FILL(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
224    ROP_FILL(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
225    ROP_FILL(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
226    ROP_FILL(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
227    ROP_FILL(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
228    ROP_FILL(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
229    ROP_FILL(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
230    ROP_FILL(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
231    ROP_FILL(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
232    ROP_FILL(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
233    ROP_FILL(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
234    ROP_FILL(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
235    ROP_FILL(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
236};
237
238static Uint gx_stipple_rop_table[16]={
239    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
240    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
241    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
242    ROP_STIP(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
243    ROP_STIP(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
244    ROP_STIP(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
245    ROP_STIP(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
246    ROP_STIP(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
247    ROP_STIP(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
248    ROP_STIP(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
249    ROP_STIP(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
250    ROP_STIP(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
251    ROP_STIP(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
252    ROP_STIP(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
253    ROP_STIP(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
254    ROP_STIP(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
255};
256
257static Uint gx_opaque_stipple_rop_table[16]={
258    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_CLEAR),	/* GXclear */
259    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_NOOP),	/* GXand */
260    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_INVERT),	/* GXandReverse */
261    ROP_OSTP(GX_ROP_CLEAR,  GX_ROP_SET),	/* GXcopy */
262    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_CLEAR),	/* GXandInverted */
263    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_NOOP),	/* GXnoop */
264    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_INVERT),	/* GXxor */
265    ROP_OSTP(GX_ROP_NOOP,   GX_ROP_SET),	/* GXor */
266    ROP_OSTP(GX_ROP_INVERT, GX_ROP_CLEAR),	/* GXnor */
267    ROP_OSTP(GX_ROP_INVERT, GX_ROP_NOOP),	/* GXequiv */
268    ROP_OSTP(GX_ROP_INVERT, GX_ROP_INVERT),	/* GXinvert */
269    ROP_OSTP(GX_ROP_INVERT, GX_ROP_SET),	/* GXorReverse */
270    ROP_OSTP(GX_ROP_SET,    GX_ROP_CLEAR),	/* GXcopyInverted */
271    ROP_OSTP(GX_ROP_SET,    GX_ROP_NOOP),	/* GXorInverted */
272    ROP_OSTP(GX_ROP_SET,    GX_ROP_INVERT),	/* GXnand */
273    ROP_OSTP(GX_ROP_SET,    GX_ROP_SET),	/* GXset */
274};
275
276int	sunGXScreenPrivateIndex;
277int	sunGXGCPrivateIndex;
278int	sunGXWindowPrivateIndex;
279int	sunGXGeneration;
280
281/*
282  sunGXDoBitBlt
283  =============
284  Bit Blit for all window to window blits.
285*/
286static void
287sunGXDoBitblt(DrawablePtr pSrc, DrawablePtr pDst, int alu, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask)
288{
289    register sunGXPtr	gx = sunGXGetScreenPrivate (pSrc->pScreen);
290    register long r;
291    register BoxPtr pboxTmp;
292    register DDXPointPtr pptTmp;
293    register int nbox;
294    BoxPtr pboxNext,pboxBase,pbox;
295
296    /* setup GX ( need fg of 0xff for blits ) */
297    GXBlitInit(gx,gx_blit_rop_table[alu]|POLY_O,planemask);
298
299    pbox = REGION_RECTS(prgnDst);
300    nbox = REGION_NUM_RECTS(prgnDst);
301
302    /* need to blit rectangles in different orders, depending on the direction of copy
303       so that an area isnt overwritten before it is blitted */
304    if( (pptSrc->y < pbox->y1) && (nbox > 1) ){
305
306	if( (pptSrc->x < pbox->x1) && (nbox > 1) ){
307
308	    /* reverse order of bands and rects in each band */
309	    pboxTmp=pbox+nbox;
310	    pptTmp=pptSrc+nbox;
311
312	    while (nbox--){
313		pboxTmp--;
314		pptTmp--;
315		gx->x0=pptTmp->x;
316		gx->y0=pptTmp->y;
317		gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
318		gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
319		gx->x2=pboxTmp->x1;
320		gx->y2=pboxTmp->y1;
321		gx->x3=pboxTmp->x2-1;
322		gx->y3=pboxTmp->y2-1;
323		GXBlitDone(gx,r);
324	    }
325	}
326	else{
327
328	    /* keep ordering in each band, reverse order of bands */
329	    pboxBase = pboxNext = pbox+nbox-1;
330
331	    while (pboxBase >= pbox){ /* for each band */
332
333		/* find first box in band */
334		while ((pboxNext >= pbox) &&
335		       (pboxBase->y1 == pboxNext->y1))
336		    pboxNext--;
337
338		pboxTmp = pboxNext+1;			/* first box in band */
339		pptTmp = pptSrc + (pboxTmp - pbox);	/* first point in band */
340
341		while (pboxTmp <= pboxBase){ /* for each box in band */
342		    gx->x0=pptTmp->x;
343		    gx->y0=pptTmp->y;
344		    gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
345		    gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
346		    gx->x2=pboxTmp->x1;
347		    gx->y2=pboxTmp->y1;
348		    gx->x3=pboxTmp->x2-1;
349		    gx->y3=pboxTmp->y2-1;
350		    ++pboxTmp;
351		    ++pptTmp;
352		    GXBlitDone(gx,r);
353		}
354		pboxBase = pboxNext;
355	    }
356	}
357    }
358    else{
359
360	if( (pptSrc->x < pbox->x1) && (nbox > 1) ){
361
362	    /* reverse order of rects in each band */
363	    pboxBase = pboxNext = pbox;
364
365	    while (pboxBase < pbox+nbox){ /* for each band */
366
367		/* find last box in band */
368		while ((pboxNext < pbox+nbox) &&
369		       (pboxNext->y1 == pboxBase->y1))
370		    pboxNext++;
371
372		pboxTmp = pboxNext;			/* last box in band */
373		pptTmp = pptSrc + (pboxTmp - pbox);	/* last point in band */
374
375		while (pboxTmp != pboxBase){ /* for each box in band */
376		    --pboxTmp;
377		    --pptTmp;
378		    gx->x0=pptTmp->x;
379		    gx->y0=pptTmp->y;
380		    gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
381		    gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
382		    gx->x2=pboxTmp->x1;
383		    gx->y2=pboxTmp->y1;
384		    gx->x3=pboxTmp->x2-1;
385		    gx->y3=pboxTmp->y2-1;
386		    GXBlitDone(gx,r);
387		}
388		pboxBase = pboxNext;
389	    }
390	}
391	else{
392
393	    /* dont need to change order of anything */
394	    pptTmp=pptSrc;
395	    pboxTmp=pbox;
396
397	    while(nbox--){
398		gx->x0=pptTmp->x;
399		gx->y0=pptTmp->y;
400		gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
401		gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
402		gx->x2=pboxTmp->x1;
403		gx->y2=pboxTmp->y1;
404		gx->x3=pboxTmp->x2-1;
405		gx->y3=pboxTmp->y2-1;
406		pboxTmp++;
407		pptTmp++;
408		GXBlitDone(gx,r);
409	    }
410	}
411    }
412    GXWait(gx,r);
413}
414
415static RegionPtr
416sunGXCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty)
417{
418    if (pSrcDrawable->type != DRAWABLE_WINDOW)
419	return cfbCopyArea (pSrcDrawable, pDstDrawable,
420            pGC, srcx, srcy, width, height, dstx, dsty);
421    return cfbBitBlt (pSrcDrawable, pDstDrawable,
422            pGC, srcx, srcy, width, height, dstx, dsty, sunGXDoBitblt, 0);
423}
424
425static unsigned long	copyPlaneFG, copyPlaneBG;
426
427static void
428sunGXCopyPlane1to8(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, int rop, RegionPtr prgnDst, DDXPointPtr pptSrc, unsigned long planemask, unsigned long bitPlane)
429{
430    register sunGXPtr	gx = sunGXGetScreenPrivate (pDstDrawable->pScreen);
431    int			srcx, srcy, dstx, dsty, width, height;
432    int			dstLastx, dstRightx;
433    int			xoffSrc, widthSrc, widthRest;
434    int			widthLast;
435    unsigned long	*psrcBase, *psrc;
436    unsigned long	bits, tmp;
437    register int	leftShift, rightShift;
438    register int	nl, nlMiddle;
439    int			nbox;
440    BoxPtr		pbox;
441    register long	r;
442
443    GXDrawInit (gx, copyPlaneFG,
444		gx_opaque_stipple_rop_table[rop]|GX_PATTERN_ONES,
445 		planemask);
446    gx->bg = copyPlaneBG;
447    gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
448
449    cfbGetLongWidthAndPointer (pSrcDrawable, widthSrc, psrcBase)
450
451    nbox = REGION_NUM_RECTS(prgnDst);
452    pbox = REGION_RECTS(prgnDst);
453    gx->incx = BITMAP_SCANLINE_UNIT;
454    gx->incy = 0;
455    while (nbox--)
456    {
457	dstx = pbox->x1;
458	dsty = pbox->y1;
459	srcx = pptSrc->x;
460	srcy = pptSrc->y;
461	dstLastx = pbox->x2;
462	width = dstLastx - dstx;
463	height = pbox->y2 - dsty;
464	pbox++;
465	pptSrc++;
466	if (!width)
467	    continue;
468	psrc = psrcBase + srcy * widthSrc + (srcx >> LOG2_BITMAP_PAD);
469	dstLastx--;
470	dstRightx = dstx + BITMAP_SCANLINE_UNIT - 1;
471	nlMiddle = (width + BITMAP_SCANLINE_UNIT - 1) >> LOG2_BITMAP_PAD;
472	widthLast = width & (BITMAP_SCANLINE_UNIT - 1);
473	xoffSrc = srcx & ((1 << LOG2_BITMAP_PAD) - 1);
474	leftShift = xoffSrc;
475	rightShift = BITMAP_SCANLINE_UNIT - leftShift;
476	widthRest = widthSrc - nlMiddle;
477	if (widthLast)
478	    nlMiddle--;
479	if (leftShift == 0)
480	{
481	    while (height--)
482	    {
483	    	gx->x0 = dstx;
484	    	gx->x1 = dstRightx;
485	    	gx->y0 = dsty++;
486	    	nl = nlMiddle;
487	    	while (nl--)
488		    gx->font = *psrc++;
489	    	if (widthLast)
490	    	{
491		    gx->x1 = dstLastx;
492#if BITMAP_SCANLINE_UNIT == 64
493		    gx->font = (int)((*psrc++)>>32);
494#else
495		    gx->font = *psrc++;
496#endif
497	    	}
498		psrc += widthRest;
499	    }
500	}
501	else
502	{
503	    widthRest--;
504	    while (height--)
505	    {
506	    	gx->x0 = dstx;
507	    	gx->x1 = dstRightx;
508	    	gx->y0 = dsty++;
509	    	bits = *psrc++;
510	    	nl = nlMiddle;
511	    	while (nl--)
512	    	{
513		    tmp = BitLeft(bits, leftShift);
514		    bits = *psrc++;
515		    tmp |= BitRight(bits, rightShift);
516		    gx->font = tmp;
517	    	}
518	    	if (widthLast)
519	    	{
520		    tmp = BitLeft(bits, leftShift);
521		    bits = *psrc++;
522		    tmp |= BitRight(bits, rightShift);
523		    gx->x1 = dstLastx;
524		    gx->font = tmp;
525	    	}
526		psrc += widthRest;
527	    }
528	}
529    }
530    GXWait (gx, r);
531    gx->incx = 0;
532    gx->incy = 0;
533    gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8;
534}
535
536static RegionPtr
537sunGXCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty, unsigned long bitPlane)
538{
539    RegionPtr		ret;
540
541    if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 8)
542    {
543    	if (bitPlane == 1)
544	{
545	    copyPlaneFG = pGC->fgPixel;
546	    copyPlaneBG = pGC->bgPixel;
547    	    ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
548	    	    pGC, srcx, srcy, width, height, dstx, dsty, sunGXCopyPlane1to8, bitPlane);
549	}
550	else
551	    ret = miHandleExposures (pSrcDrawable, pDstDrawable,
552	    	pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
553    }
554    else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 1)
555    {
556	extern	int InverseAlu[16];
557	int oldalu;
558
559	oldalu = pGC->alu;
560    	if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1)
561	    pGC->alu = InverseAlu[pGC->alu];
562    	else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
563	    pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
564	ret = cfbCopyPlaneReduce (pSrcDrawable, pDstDrawable,
565		    pGC, srcx, srcy, width, height, dstx, dsty, cfbCopyPlane8to1, bitPlane);
566	pGC->alu = oldalu;
567    }
568    else
569    {
570	PixmapPtr	pBitmap;
571	ScreenPtr	pScreen = pSrcDrawable->pScreen;
572	GCPtr		pGC1;
573
574	pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1);
575	if (!pBitmap)
576	    return NULL;
577	pGC1 = GetScratchGC (1, pScreen);
578	if (!pGC1)
579	{
580	    (*pScreen->DestroyPixmap) (pBitmap);
581	    return NULL;
582	}
583	/*
584	 * don't need to set pGC->fgPixel,bgPixel as copyPlane8to1
585	 * ignores pixel values, expecting the rop to "do the
586	 * right thing", which GXcopy will.
587	 */
588	ValidateGC ((DrawablePtr) pBitmap, pGC1);
589	/* no exposures here, scratch GC's don't get graphics expose */
590	(void) cfbCopyPlaneReduce (pSrcDrawable, (DrawablePtr) pBitmap,
591			    pGC1, srcx, srcy, width, height, 0, 0, cfbCopyPlane8to1, bitPlane);
592	copyPlaneFG = pGC->fgPixel;
593	copyPlaneBG = pGC->bgPixel;
594	(void) cfbBitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC,
595			    0, 0, width, height, dstx, dsty, sunGXCopyPlane1to8, 1);
596	FreeScratchGC (pGC1);
597	(*pScreen->DestroyPixmap) (pBitmap);
598	/* compute resultant exposures */
599	ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC,
600				 srcx, srcy, width, height,
601				 dstx, dsty, bitPlane);
602    }
603    return ret;
604}
605
606static void
607sunGXFillRectAll(DrawablePtr pDrawable, GCPtr pGC, int nBox, BoxPtr pBox)
608{
609    register sunGXPtr	gx = sunGXGetScreenPrivate (pDrawable->pScreen);
610    register sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
611    register int	r;
612
613    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask);
614    if (gxPriv->stipple)
615	GXStippleInit(gx,gxPriv->stipple);
616    while (nBox--) {
617	gx->arecty = pBox->y1;
618	gx->arectx = pBox->x1;
619	gx->arecty = pBox->y2;
620	gx->arectx = pBox->x2;
621	pBox++;
622	GXDrawDone(gx,r);
623    }
624    GXWait(gx,r);
625}
626
627#define NUM_STACK_RECTS	1024
628
629static void
630sunGXPolyFillRect(
631    DrawablePtr	pDrawable,
632    GCPtr	pGC,
633    int		nrectFill, 	/* number of rectangles to fill */
634    xRectangle	*prectInit  	/* Pointer to first rectangle to fill */
635)
636{
637    xRectangle	    *prect;
638    RegionPtr	    prgnClip;
639    register BoxPtr pbox;
640    register BoxPtr pboxClipped;
641    BoxPtr	    pboxClippedBase;
642    BoxPtr	    pextent;
643    BoxRec	    stackRects[NUM_STACK_RECTS];
644    int		    numRects;
645    int		    n;
646    int		    xorg, yorg;
647
648    prgnClip = pGC->pCompositeClip;
649    prect = prectInit;
650    xorg = pDrawable->x;
651    yorg = pDrawable->y;
652    if (xorg || yorg)
653    {
654	prect = prectInit;
655	n = nrectFill;
656	while(n--)
657	{
658	    prect->x += xorg;
659	    prect->y += yorg;
660	    prect++;
661	}
662    }
663
664    prect = prectInit;
665
666    numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
667    if (numRects > NUM_STACK_RECTS)
668    {
669	pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
670	if (!pboxClippedBase)
671	    return;
672    }
673    else
674	pboxClippedBase = stackRects;
675
676    pboxClipped = pboxClippedBase;
677
678    if (REGION_NUM_RECTS(prgnClip) == 1)
679    {
680	int x1, y1, x2, y2, bx2, by2;
681
682	pextent = REGION_RECTS(prgnClip);
683	x1 = pextent->x1;
684	y1 = pextent->y1;
685	x2 = pextent->x2;
686	y2 = pextent->y2;
687    	while (nrectFill--)
688    	{
689	    if ((pboxClipped->x1 = prect->x) < x1)
690		pboxClipped->x1 = x1;
691
692	    if ((pboxClipped->y1 = prect->y) < y1)
693		pboxClipped->y1 = y1;
694
695	    bx2 = (int) prect->x + (int) prect->width;
696	    if (bx2 > x2)
697		bx2 = x2;
698	    pboxClipped->x2 = bx2;
699
700	    by2 = (int) prect->y + (int) prect->height;
701	    if (by2 > y2)
702		by2 = y2;
703	    pboxClipped->y2 = by2;
704
705	    prect++;
706	    if ((pboxClipped->x1 < pboxClipped->x2) &&
707		(pboxClipped->y1 < pboxClipped->y2))
708	    {
709		pboxClipped++;
710	    }
711    	}
712    }
713    else
714    {
715	int x1, y1, x2, y2, bx2, by2;
716
717	pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
718	x1 = pextent->x1;
719	y1 = pextent->y1;
720	x2 = pextent->x2;
721	y2 = pextent->y2;
722    	while (nrectFill--)
723    	{
724	    BoxRec box;
725
726	    if ((box.x1 = prect->x) < x1)
727		box.x1 = x1;
728
729	    if ((box.y1 = prect->y) < y1)
730		box.y1 = y1;
731
732	    bx2 = (int) prect->x + (int) prect->width;
733	    if (bx2 > x2)
734		bx2 = x2;
735	    box.x2 = bx2;
736
737	    by2 = (int) prect->y + (int) prect->height;
738	    if (by2 > y2)
739		by2 = y2;
740	    box.y2 = by2;
741
742	    prect++;
743
744	    if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
745	    	continue;
746
747	    n = REGION_NUM_RECTS (prgnClip);
748	    pbox = REGION_RECTS(prgnClip);
749
750	    /* clip the rectangle to each box in the clip region
751	       this is logically equivalent to calling Intersect()
752	    */
753	    while(n--)
754	    {
755		pboxClipped->x1 = max(box.x1, pbox->x1);
756		pboxClipped->y1 = max(box.y1, pbox->y1);
757		pboxClipped->x2 = min(box.x2, pbox->x2);
758		pboxClipped->y2 = min(box.y2, pbox->y2);
759		pbox++;
760
761		/* see if clipping left anything */
762		if(pboxClipped->x1 < pboxClipped->x2 &&
763		   pboxClipped->y1 < pboxClipped->y2)
764		{
765		    pboxClipped++;
766		}
767	    }
768    	}
769    }
770    if (pboxClipped != pboxClippedBase)
771	sunGXFillRectAll(pDrawable, pGC,
772		    pboxClipped-pboxClippedBase, pboxClippedBase);
773    if (pboxClippedBase != stackRects)
774    	DEALLOCATE_LOCAL(pboxClippedBase);
775}
776
777static void
778sunGXFillSpans(
779    DrawablePtr pDrawable,
780    GCPtr	pGC,
781    int		n,			/* number of spans to fill */
782    DDXPointPtr ppt,			/* pointer to list of start points */
783    int		*pwidth,		/* pointer to list of n widths */
784    int 	fSorted
785)
786{
787    int		    x, y;
788    int		    width;
789				/* next three parameters are post-clip */
790    int		    nTmp;
791    int		    *pwidthFree;/* copies of the pointers to free */
792    DDXPointPtr	    pptFree;
793    register sunGXPtr	gx = sunGXGetScreenPrivate (pDrawable->pScreen);
794    cfbPrivGCPtr    devPriv = cfbGetGCPrivate(pGC);
795    register sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
796    register int    r;
797    BoxPtr	    extents;
798
799    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask)
800    if (gxPriv->stipple)
801	GXStippleInit(gx,gxPriv->stipple);
802    if (devPriv->oneRect)
803    {
804	extents = &pGC->pCompositeClip->extents;
805	GXSetClip (gx, extents);
806    }
807    else
808    {
809    	nTmp = n * miFindMaxBand(pGC->pCompositeClip);
810    	pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
811    	pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
812    	if(!pptFree || !pwidthFree)
813    	{
814	    if (pptFree) DEALLOCATE_LOCAL(pptFree);
815	    if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
816	    return;
817    	}
818    	n = miClipSpans(pGC->pCompositeClip, ppt, pwidth, n,
819		     	 pptFree, pwidthFree, fSorted);
820    	pwidth = pwidthFree;
821    	ppt = pptFree;
822    }
823    while (n--)
824    {
825	x = ppt->x;
826	y = ppt->y;
827	ppt++;
828	width = *pwidth++;
829	if (width)
830	{
831	    sunGXFillSpan(gx,y,x,x + width - 1,r);
832	}
833    }
834    GXWait(gx,r);
835    if (devPriv->oneRect)
836    {
837	GXResetClip (gx, pDrawable->pScreen);
838    }
839    else
840    {
841	DEALLOCATE_LOCAL(pptFree);
842	DEALLOCATE_LOCAL(pwidthFree);
843    }
844}
845
846#ifdef NOTDEF
847/* cfb is faster for dots */
848void
849sunGXPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, xPoint *pptInit)
850{
851    register sunGXPtr	gx = sunGXGetScreenPrivate (pDrawable->pScreen);
852    RegionPtr	    cclip;
853    int		    nbox;
854    register int    i;
855    register BoxPtr pbox;
856    cfbPrivGCPtr    devPriv;
857    xPoint	    *ppt;
858    int		    x, y;
859    int		    r;
860    int		    off;
861
862    devPriv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr);
863    if (devPriv->rop == GXnoop)
864	return;
865    cclip = pGC->pCompositeClip;
866    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu],pGC->planemask);
867    gx->offx = pDrawable->x;
868    gx->offy = pDrawable->y;
869    for (nbox = REGION_NUM_RECTS(cclip), pbox = REGION_RECTS(cclip);
870	 --nbox >= 0;
871	 pbox++)
872    {
873	sunGXSetClip(gx,pbox);
874	if (mode != CoordModeOrigin)
875	{
876	    x = 0;
877	    y = 0;
878	    for (ppt = pptInit, i = npt; --i >= 0;)
879	    {
880	    	gx->apointy = y += ppt->y;
881	    	gx->apointx = x += ppt->x;
882	    	++ppt;
883	    	GXDrawDone(gx,r);
884	    }
885	}
886	else
887	{
888	    for (ppt = pptInit, i = npt; --i >= 0;)
889	    {
890	    	gx->apointy = ppt->y;
891	    	gx->apointx = ppt->x;
892	    	++ppt;
893	    	GXDrawDone(gx,r);
894	    }
895	}
896    }
897    GXWait(gx,r);
898    GXResetOff (gx);
899    GXResetClip(gx,pDrawable->pScreen);
900}
901#endif
902
903#include "mifillarc.h"
904
905#define FILLSPAN(gx,y,x1,x2,r) {\
906    if (x2 >= x1) {\
907	sunGXFillSpan(gx,y,x1,x2,r) \
908    } \
909}
910
911#define FILLSLICESPANS(flip,y) \
912    if (!flip) \
913    { \
914	FILLSPAN(gx,y,xl,xr,r) \
915    } \
916    else \
917    { \
918	xc = xorg - x; \
919	FILLSPAN(gx, y, xc, xr, r) \
920	xc += slw - 1; \
921	FILLSPAN(gx, y, xl, xc, r) \
922    }
923
924static void
925sunGXFillEllipse(DrawablePtr pDraw, sunGXPtr gx, xArc *arc)
926{
927    int x, y, e;
928    int yk, xk, ym, xm, dx, dy, xorg, yorg;
929    int	y_top, y_bot;
930    miFillArcRec info;
931    register int xpos;
932    int	r;
933    int	slw;
934
935    miFillArcSetup(arc, &info);
936    MIFILLARCSETUP();
937    y_top = yorg - y;
938    y_bot = yorg + y + dy;
939    while (y)
940    {
941	y_top++;
942	y_bot--;
943	MIFILLARCSTEP(slw);
944	if (!slw)
945	    continue;
946	xpos = xorg - x;
947	sunGXFillSpan (gx,y_top,xpos,xpos+slw - 1,r);
948	if (miFillArcLower(slw))
949	    sunGXFillSpan (gx,y_bot,xpos,xpos+slw - 1,r);
950    }
951}
952
953
954static void
955sunGXFillArcSlice(DrawablePtr pDraw, GCPtr pGC, sunGXPtr gx, xArc *arc)
956{
957    int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
958    register int x, y, e;
959    miFillArcRec info;
960    miArcSliceRec slice;
961    int xl, xr, xc;
962    int	y_top, y_bot;
963    int	r;
964
965    miFillArcSetup(arc, &info);
966    miFillArcSliceSetup(arc, &slice, pGC);
967    MIFILLARCSETUP();
968    y_top = yorg - y;
969    y_bot = yorg + y + dy;
970    while (y > 0)
971    {
972	y_top++;
973	y_bot--;
974	MIFILLARCSTEP(slw);
975	MIARCSLICESTEP(slice.edge1);
976	MIARCSLICESTEP(slice.edge2);
977	if (miFillSliceUpper(slice))
978	{
979	    MIARCSLICEUPPER(xl, xr, slice, slw);
980	    FILLSLICESPANS(slice.flip_top, y_top);
981	}
982	if (miFillSliceLower(slice))
983	{
984	    MIARCSLICELOWER(xl, xr, slice, slw);
985	    FILLSLICESPANS(slice.flip_bot, y_bot);
986	}
987    }
988}
989
990#define FAST_CIRCLES
991#ifdef FAST_CIRCLES
992#if     (BITMAP_BIT_ORDER == MSBFirst)
993#define Bits32(v)   (v)
994#define Bits16(v)   (v)
995#define Bits8(v)    (v)
996#else
997#define FlipBits2(a)     ((((a) & 0x1) << 1) | (((a) & 0x2) >> 1))
998#define FlipBits4(a)     ((FlipBits2(a) << 2) | FlipBits2(a >> 2))
999#define FlipBits8(a)     ((FlipBits4(a) << 4) | FlipBits4(a >> 4))
1000#define FlipBits16(a)    ((FlipBits8(a) << 8) | FlipBits8(a >> 8))
1001#define FlipBits32(a)    ((FlipBits16(a) << 16) | FlipBits16(a >> 16))
1002#define Bits32(v)   FlipBits32(v)
1003#define Bits16(v)   FlipBits16(v)
1004#define Bits8(v)    FlipBits8(v)
1005#endif
1006
1007#define B(x)	Bits16(x)
1008#define DO_FILLED_ARCS
1009#include    "circleset.h"
1010#undef B
1011#undef Bits8
1012#undef Bits16
1013#undef Bits32
1014#define UNSET_CIRCLE	if (old_width) \
1015			{ \
1016			    gx->alu = gx_solid_rop_table[pGC->alu]; \
1017			    old_width = -old_width; \
1018			}
1019
1020#else
1021#define UNSET_CIRCLE
1022#endif
1023
1024static void
1025sunGXPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
1026{
1027    register xArc *arc;
1028    register int i;
1029    int		x, y;
1030    BoxRec box;
1031    BoxPtr	extents = NULL;
1032    RegionPtr cclip;
1033    register sunGXPtr	gx = sunGXGetScreenPrivate (pDraw->pScreen);
1034    sunGXPrivGCPtr	gxPriv = sunGXGetGCPrivate (pGC);
1035    cfbPrivGCPtr    devPriv;
1036    register int	r;
1037#ifdef FAST_CIRCLES
1038    int			old_width = 0;
1039#endif
1040
1041    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask);
1042    if (gxPriv->stipple)
1043	GXStippleInit(gx,gxPriv->stipple);
1044    devPriv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr);
1045    cclip = pGC->pCompositeClip;
1046    GXSetOff(gx,pDraw->x,pDraw->y)
1047    if (devPriv->oneRect) {
1048	extents = &cclip->extents;
1049	GXSetClip(gx,extents);
1050    }
1051    for (arc = parcs, i = narcs; --i >= 0; arc++)
1052    {
1053	if (miFillArcEmpty(arc))
1054	    continue;
1055	if (miCanFillArc(arc))
1056	{
1057	    x = arc->x;
1058	    y = arc->y;
1059	    if (!devPriv->oneRect)
1060	    {
1061	    	box.x1 = x + pDraw->x;
1062	    	box.y1 = y + pDraw->y;
1063	    	box.x2 = box.x1 + (int)arc->width + 1;
1064	    	box.y2 = box.y1 + (int)arc->height + 1;
1065	    }
1066	    if (devPriv->oneRect ||
1067		RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN)
1068	    {
1069		if ((arc->angle2 >= FULLCIRCLE) ||
1070		    (arc->angle2 <= -FULLCIRCLE))
1071		{
1072#ifdef FAST_CIRCLES
1073/* who really needs fast filled circles? */
1074		    if (arc->width == arc->height && arc->width <= 16 &&
1075			!gxPriv->stipple)
1076		    {
1077			int offx, offy;
1078			if (arc->width != old_width)
1079			{
1080			    int	    i;
1081			    Uint    *sp;
1082			    VUint   *dp;
1083
1084			    if (old_width != -arc->width)
1085			    {
1086			    	sp = (Uint *) filled_arcs[arc->width-1];
1087			    	dp = gx->pattern;
1088			    	i = 8;
1089			    	while (i--)
1090				    dp[i] = sp[i];
1091			    }
1092			    gx->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
1093			    old_width = arc->width;
1094			}
1095			offx = 16 - ((x + pDraw->x) & 0x0f);
1096			offy = 16 - ((y + pDraw->y) & 0x0f);
1097			gx->patalign = (offx << 16) | offy;
1098			gx->arecty = y;
1099			gx->arectx = x;
1100			gx->arecty = y + old_width-1;
1101			gx->arectx = x + old_width-1;
1102			GXDrawDone (gx, r);
1103		    }
1104		    else
1105#endif
1106		    {
1107			UNSET_CIRCLE
1108			sunGXFillEllipse (pDraw, gx, arc);
1109		    }
1110		}
1111		else
1112		{
1113		    UNSET_CIRCLE
1114		    sunGXFillArcSlice (pDraw, pGC, gx, arc);
1115		}
1116		continue;
1117	    }
1118	}
1119	UNSET_CIRCLE
1120	GXWait (gx,r);
1121	GXResetOff (gx);
1122	if (devPriv->oneRect)
1123	    GXResetClip (gx, pDraw->pScreen);
1124	miPolyFillArc(pDraw, pGC, 1, arc);
1125	GXSetOff (gx, pDraw->x, pDraw->y);
1126	if (devPriv->oneRect)
1127	    GXSetClip (gx, extents);
1128    }
1129    GXWait (gx, r);
1130    GXResetOff (gx);
1131    if (devPriv->oneRect)
1132	GXResetClip (gx, pDraw->pScreen);
1133}
1134
1135static void
1136sunGXFillPoly1Rect(DrawablePtr pDrawable, GCPtr pGC, int shape, int mode, int count, DDXPointPtr ptsIn)
1137{
1138    BoxPtr	    extents;
1139    int		    x1, x2, x3, x4;
1140    int		    y1, y2, y3, y4;
1141    sunGXPtr	    gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1142    sunGXPrivGCPtr  gxPriv = sunGXGetGCPrivate (pGC);
1143    int		    r;
1144    typedef struct {
1145	Uint	    x;
1146	Uint	    y;
1147	Uint	    z;
1148    } GXPointRec, *GXPointPtr;
1149    GXPointPtr	    tri, qua;
1150
1151    if (count < 3)
1152	return;
1153    if (shape != Convex && count > 4)
1154    {
1155	miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn);
1156	return;
1157    }
1158    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask);
1159    if (gxPriv->stipple)
1160	GXStippleInit(gx,gxPriv->stipple);
1161    extents = &pGC->pCompositeClip->extents;
1162    GXSetOff(gx,pDrawable->x, pDrawable->y);
1163    GXSetClip(gx,extents);
1164    if (mode == CoordModeOrigin)
1165    {
1166	tri = (GXPointPtr) &gx->atrix;
1167	qua = (GXPointPtr) &gx->aquadx;
1168    }
1169    else
1170    {
1171	tri = (GXPointPtr) &gx->rtrix;
1172	qua = (GXPointPtr) &gx->rquadx;
1173    }
1174    if (count == 3) {
1175	gx->apointy = ptsIn[0].y;
1176	gx->apointx = ptsIn[0].x;
1177	tri->y = ptsIn[1].y;
1178	tri->x = ptsIn[1].x;
1179	tri->y = ptsIn[2].y;
1180	tri->x = ptsIn[2].x;
1181	GXDrawDone (gx, r);
1182    }
1183    else if (count == 4)
1184    {
1185	gx->apointy = ptsIn[0].y;
1186	gx->apointx = ptsIn[0].x;
1187	qua->y = ptsIn[1].y;
1188	qua->x = ptsIn[1].x;
1189	qua->y = ptsIn[2].y;
1190	qua->x = ptsIn[2].x;
1191	qua->y = ptsIn[3].y;
1192	qua->x = ptsIn[3].x;
1193	GXDrawDone (gx, r);
1194	if (r < 0 && shape != Convex)
1195	{
1196	    GXWait(gx,r);
1197	    GXResetOff(gx);
1198	    GXResetClip(gx,pDrawable->pScreen);
1199	    miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn);
1200	    return;
1201	}
1202    }
1203    else
1204    {
1205	y1 = ptsIn[0].y;
1206	x1 = ptsIn[0].x;
1207	y2 = ptsIn[1].y;
1208	x2 = ptsIn[1].x;
1209	count -= 2;
1210	ptsIn += 2;
1211    	while (count) {
1212	    x3 = ptsIn->x;
1213	    y3 = ptsIn->y;
1214	    ptsIn++;
1215	    count--;
1216	    gx->apointy = y1;
1217	    gx->apointx = x1;
1218	    if (count == 0) {
1219		tri->y = y2;
1220		tri->x = x2;
1221		tri->y = y3;
1222		tri->x = x3;
1223	    }
1224	    else
1225	    {
1226		y4 = ptsIn->y;
1227		x4 = ptsIn->x;
1228		ptsIn++;
1229		count--;
1230		qua->y = y2;
1231		qua->x = x2;
1232		qua->y = y3;
1233		qua->x = x3;
1234		qua->y = y4;
1235		qua->x = x4;
1236		if (mode == CoordModeOrigin)
1237		{
1238		    x2 = x4;
1239		    y2 = y4;
1240		}
1241		else
1242		{
1243		    x2 = x2 + x3 + x4;
1244		    y2 = y2 + y3 + y4;
1245		}
1246	    }
1247	    GXDrawDone (gx, r);
1248    	}
1249    }
1250    GXWait(gx,r);
1251    GXResetOff(gx);
1252    GXResetClip(gx,pDrawable->pScreen);
1253}
1254
1255/*
1256 * Note that the GX does not allow CapNotLast, so the code fakes it.  This is
1257 * expensive to do as the GX is asynchronous and must be synced with GXWait
1258 * before fetching and storing the final line point.  If only the hardware was
1259 * designed for X.
1260 */
1261
1262/* hard code the screen width; otherwise we'd have to check or mul */
1263
1264#define WIDTH_MUL(y)	(((y) << 10) + ((y) << 7))
1265#define GX_WIDTH	1152
1266#define WID_OK(s)	((s)->width == GX_WIDTH)
1267
1268void
1269sunGXPolySeg1Rect(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment *pSeg)
1270{
1271    sunGXPtr	    gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1272    sunGXPrivGCPtr  gxPriv = sunGXGetGCPrivate (pGC);
1273    BoxPtr	    extents;
1274    int		    x, y;
1275    int		    r;
1276    unsigned char   *baseAddr, *loAddr, *hiAddr, *saveAddr = 0, save = 0;
1277
1278    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask);
1279    if (gxPriv->stipple)
1280	GXStippleInit(gx,gxPriv->stipple);
1281    GXSetOff (gx, pDrawable->x, pDrawable->y);
1282
1283    extents = &pGC->pCompositeClip->extents;
1284    GXSetClip (gx, extents);
1285    if (pGC->capStyle == CapNotLast)
1286    {
1287	sunGXGetAddrRange(pDrawable,extents,baseAddr,loAddr,hiAddr);
1288    	while (nseg--)
1289    	{
1290	    gx->aliney = pSeg->y1;
1291	    gx->alinex = pSeg->x1;
1292	    y = pSeg->y2;
1293	    x = pSeg->x2;
1294	    saveAddr = baseAddr + WIDTH_MUL(y) + x;
1295	    if (saveAddr < loAddr || hiAddr < saveAddr)
1296		saveAddr = 0;
1297	    else
1298		save = *saveAddr;
1299	    gx->aliney = y;
1300	    gx->alinex = x;
1301	    GXDrawDone (gx, r);
1302	    if (saveAddr)
1303	    {
1304		GXWait(gx,r);
1305		*saveAddr = save;
1306	    }
1307	    pSeg++;
1308    	}
1309    }
1310    else
1311    {
1312    	while (nseg--)
1313    	{
1314	    gx->aliney = pSeg->y1;
1315	    gx->alinex = pSeg->x1;
1316	    gx->aliney = pSeg->y2;
1317	    gx->alinex = pSeg->x2;
1318	    pSeg++;
1319	    GXDrawDone (gx, r);
1320    	}
1321    }
1322    GXWait (gx, r);
1323    GXResetOff (gx);
1324    GXResetClip (gx, pDrawable->pScreen);
1325}
1326
1327void
1328sunGXPolylines1Rect(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, DDXPointPtr ppt)
1329{
1330    sunGXPtr	    gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1331    sunGXPrivGCPtr  gxPriv = sunGXGetGCPrivate (pGC);
1332    BoxPtr	    extents;
1333    unsigned char   *baseAddr, *loAddr, *hiAddr, *saveAddr, save = 0;
1334    int		    r;
1335    Bool	    careful;
1336    Bool	    capNotLast;
1337
1338    if (!--npt)
1339	return;
1340    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask);
1341    if (gxPriv->stipple)
1342	GXStippleInit(gx,gxPriv->stipple);
1343    careful = ((pGC->alu & 0xc) == 0x8 || (pGC->alu & 0x3) == 0x2);
1344    capNotLast = pGC->capStyle == CapNotLast;
1345
1346    extents = &pGC->pCompositeClip->extents;
1347    GXSetOff (gx, pDrawable->x, pDrawable->y);
1348    GXSetClip (gx, extents);
1349    if (careful)
1350    {
1351	int	x, y;
1352	sunGXGetAddrRange (pDrawable, extents, baseAddr, loAddr, hiAddr);
1353	gx->apointy = y = ppt->y;
1354	gx->apointx = x = ppt->x;
1355	ppt++;
1356    	while (npt--)
1357    	{
1358	    if (mode == CoordModeOrigin)
1359	    {
1360		y = ppt->y;
1361		x = ppt->x;
1362	    }
1363	    else
1364	    {
1365	    	y += ppt->y;
1366	    	x += ppt->x;
1367	    }
1368	    ppt++;
1369	    saveAddr = baseAddr + WIDTH_MUL(y) + x;
1370	    if (saveAddr < loAddr || hiAddr < saveAddr)
1371		saveAddr = 0;
1372	    else
1373		save = *saveAddr;
1374	    gx->aliney = y;
1375	    gx->alinex = x;
1376	    GXDrawDone (gx, r);
1377	    if (saveAddr)
1378	    {
1379		GXWait(gx,r);
1380	    	*saveAddr = save;
1381	    }
1382    	}
1383	GXWait(gx,r);
1384    }
1385    else
1386    {
1387	int	x, y;
1388	if (capNotLast)
1389	    npt--;
1390	if (mode == CoordModeOrigin)
1391	{
1392	    x = y = 0;
1393	    gx->apointy = ppt->y;
1394	    gx->apointx = ppt->x;
1395	    ppt++;
1396	    while (npt--)
1397	    {
1398		gx->aliney = ppt->y;
1399		gx->alinex = ppt->x;
1400		++ppt;
1401		GXDrawDone(gx,r);
1402	    }
1403	}
1404	else
1405	{
1406	    y = gx->apointy = ppt->y;
1407	    x = gx->apointx = ppt->x;
1408	    ppt++;
1409	    while (npt--)
1410	    {
1411		y += gx->rliney = ppt->y;
1412		x += gx->rlinex = ppt->x;
1413		++ppt;
1414		GXDrawDone(gx,r);
1415	    }
1416	}
1417	if (capNotLast)
1418	{
1419	    sunGXGetAddrRange (pDrawable, extents, baseAddr, loAddr, hiAddr);
1420	    x += ppt->x;
1421	    y += ppt->y;
1422	    saveAddr = baseAddr + WIDTH_MUL(y) + x;
1423	    if (saveAddr < loAddr || hiAddr < saveAddr)
1424		saveAddr = 0;
1425	    else
1426		save = *saveAddr;
1427	    gx->aliney = y;
1428	    gx->alinex = x;
1429	    GXDrawDone(gx,r);
1430	    GXWait(gx,r);
1431	    if (saveAddr)
1432		*saveAddr = save;
1433	}
1434	else
1435	{
1436	    GXWait(gx,r);
1437	}
1438    }
1439    GXResetOff (gx);
1440    GXResetClip (gx, pDrawable->pScreen);
1441}
1442
1443void
1444sunGXPolyFillRect1Rect(DrawablePtr pDrawable, GCPtr pGC, int nrect, xRectangle *prect)
1445{
1446    sunGXPtr	    gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1447    sunGXPrivGCPtr  gxPriv = sunGXGetGCPrivate (pGC);
1448    BoxPtr	    extents = &pGC->pCompositeClip->extents;
1449    int		    r;
1450    int		    x, y;
1451
1452    GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask);
1453    if (gxPriv->stipple)
1454	GXStippleInit(gx,gxPriv->stipple);
1455    GXSetOff (gx, pDrawable->x, pDrawable->y);
1456    GXSetClip (gx, extents);
1457    while (nrect--)
1458    {
1459	gx->arecty = y = prect->y;
1460	gx->arectx = x = prect->x;
1461	gx->arecty = y + (int) prect->height;
1462	gx->arectx = x + (int) prect->width;
1463	prect++;
1464	GXDrawDone (gx, r);
1465    }
1466    GXWait (gx, r);
1467    GXResetOff (gx);
1468    GXResetClip (gx, pDrawable->pScreen);
1469}
1470
1471static void
1472sunGXPolyGlyphBlt(
1473    DrawablePtr	    pDrawable,
1474    GCPtr	    pGC,
1475    int		    x,
1476    int		    y,
1477    unsigned int    nglyph,
1478    CharInfoPtr	    *ppci,		/* array of character info */
1479    void            *pglyphBase
1480)
1481{
1482    sunGXPtr	    gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1483    int		    h;
1484    int		    w;
1485    CharInfoPtr	    pci;
1486    unsigned int    *bits;
1487    register int    r;
1488    RegionPtr	    clip;
1489    BoxPtr	    extents;
1490    BoxRec	    box;
1491
1492    clip = pGC->pCompositeClip;
1493    extents = &clip->extents;
1494
1495    if (REGION_NUM_RECTS(clip) == 1)
1496    {
1497	GXSetClip (gx, extents);
1498    }
1499    else
1500    {
1501    	/* compute an approximate (but covering) bounding box */
1502    	box.x1 = 0;
1503    	if ((ppci[0]->metrics.leftSideBearing < 0))
1504	    box.x1 = ppci[0]->metrics.leftSideBearing;
1505    	h = nglyph - 1;
1506    	w = ppci[h]->metrics.rightSideBearing;
1507    	while (--h >= 0)
1508	    w += ppci[h]->metrics.characterWidth;
1509    	box.x2 = w;
1510    	box.y1 = -FONTMAXBOUNDS(pGC->font,ascent);
1511    	box.y2 = FONTMAXBOUNDS(pGC->font,descent);
1512
1513    	box.x1 += pDrawable->x + x;
1514    	box.x2 += pDrawable->x + x;
1515    	box.y1 += pDrawable->y + y;
1516    	box.y2 += pDrawable->y + y;
1517
1518    	switch (RECT_IN_REGION(pGC->pScreen, clip, &box))
1519	{
1520	case rgnPART:
1521	    cfbPolyGlyphBlt8 (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
1522	case rgnOUT:
1523	    return;
1524	}
1525    }
1526
1527    GXDrawInit (gx, pGC->fgPixel,
1528		gx_stipple_rop_table[pGC->alu]|GX_PATTERN_ONES|POLY_N,
1529 		pGC->planemask);
1530    gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
1531    x += pDrawable->x;
1532    y += pDrawable->y;
1533
1534    while (nglyph--)
1535    {
1536	pci = *ppci++;
1537	gx->incx = 0;
1538	gx->incy = 1;
1539	gx->x0 = x + pci->metrics.leftSideBearing;
1540	gx->x1 = (x + pci->metrics.rightSideBearing) - 1;
1541	gx->y0 = y - pci->metrics.ascent;
1542	h = pci->metrics.ascent + pci->metrics.descent;
1543	bits = (unsigned int *) pci->bits;
1544	while (h--) {
1545	    gx->font = *bits++;
1546	}
1547	x += pci->metrics.characterWidth;
1548    }
1549    GXWait (gx, r);
1550    gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8;
1551    GXResetClip (gx, pDrawable->pScreen);
1552}
1553
1554static void
1555sunGXTEGlyphBlt(
1556    DrawablePtr	pDrawable,
1557    GCPtr	pGC,
1558    int 	x,
1559    int 	y,
1560    unsigned int nglyph,
1561    CharInfoPtr *ppci,		/* array of character info */
1562    void	*pglyphBase	/* start of array of glyphs */
1563)
1564{
1565    sunGXPtr	    gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1566    int		    h, hTmp;
1567    FontPtr	    pfont = pGC->font;
1568    register int    r;
1569    unsigned int   *char1, *char2, *char3, *char4;
1570    int		    widthGlyphs, widthGlyph;
1571    BoxRec	    bbox;
1572    BoxPtr	    extents;
1573    RegionPtr	    clip;
1574    unsigned long   rop;
1575
1576    widthGlyph = FONTMAXBOUNDS(pfont,characterWidth);
1577    h = FONTASCENT(pfont) + FONTDESCENT(pfont);
1578    clip = pGC->pCompositeClip;
1579    extents = &clip->extents;
1580
1581    if (REGION_NUM_RECTS(clip) == 1)
1582    {
1583	GXSetClip (gx, extents);
1584    }
1585    else
1586    {
1587    	bbox.x1 = x + pDrawable->x;
1588    	bbox.x2 = bbox.x1 + (widthGlyph * nglyph);
1589    	bbox.y1 = y + pDrawable->y - FONTASCENT(pfont);
1590    	bbox.y2 = bbox.y1 + h;
1591
1592    	switch (RECT_IN_REGION(pGC->pScreen, clip, &bbox))
1593    	{
1594	case rgnPART:
1595	    if (pglyphBase)
1596		cfbPolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, NULL);
1597	    else
1598		miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
1599	case rgnOUT:
1600	    return;
1601    	}
1602    }
1603
1604    rop = gx_opaque_stipple_rop_table[GXcopy] | GX_PATTERN_ONES;
1605    if (pglyphBase)
1606	rop = gx_stipple_rop_table[pGC->alu] | GX_PATTERN_ONES;
1607    GXDrawInit (gx, pGC->fgPixel, rop, pGC->planemask);
1608    gx->bg = pGC->bgPixel;
1609    gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
1610
1611    y = y + pDrawable->y - FONTASCENT(pfont);
1612    x += pDrawable->x;
1613
1614#define LoopIt(count, w, loadup, fetch) \
1615    	while (nglyph >= count) \
1616    	{ \
1617	    nglyph -= count; \
1618	    gx->incx = 0; \
1619	    gx->incy = 1; \
1620	    gx->x0 = x; \
1621	    gx->x1 = (x += w) - 1; \
1622	    gx->y0 = y; \
1623	    loadup \
1624	    hTmp = h; \
1625	    while (hTmp--) \
1626	    	gx->font = fetch; \
1627    	}
1628
1629    if (widthGlyph <= 8)
1630    {
1631	widthGlyphs = widthGlyph << 2;
1632	LoopIt(4, widthGlyphs,
1633	    char1 = (unsigned int *) (*ppci++)->bits;
1634	    char2 = (unsigned int *) (*ppci++)->bits;
1635	    char3 = (unsigned int *) (*ppci++)->bits;
1636	    char4 = (unsigned int *) (*ppci++)->bits;,
1637	    (*char1++ | ((*char2++ | ((*char3++ | (*char4++
1638		    >> widthGlyph))
1639		    >> widthGlyph))
1640		    >> widthGlyph)))
1641    }
1642    else if (widthGlyph <= 10)
1643    {
1644	widthGlyphs = (widthGlyph << 1) + widthGlyph;
1645	LoopIt(3, widthGlyphs,
1646	    char1 = (unsigned int *) (*ppci++)->bits;
1647	    char2 = (unsigned int *) (*ppci++)->bits;
1648	    char3 = (unsigned int *) (*ppci++)->bits;,
1649	    (*char1++ | ((*char2++ | (*char3++ >> widthGlyph)) >> widthGlyph)))
1650    }
1651    else if (widthGlyph <= 16)
1652    {
1653	widthGlyphs = widthGlyph << 1;
1654	LoopIt(2, widthGlyphs,
1655	    char1 = (unsigned int *) (*ppci++)->bits;
1656	    char2 = (unsigned int *) (*ppci++)->bits;,
1657	    (*char1++ | (*char2++ >> widthGlyph)))
1658    }
1659    while (nglyph--) {
1660	gx->incx = 0;
1661	gx->incy = 1;
1662	gx->x0 = x;
1663	gx->x1 = (x += widthGlyph) - 1;
1664	gx->y0 = y;
1665	char1 = (unsigned int *) (*ppci++)->bits;
1666	hTmp = h;
1667	while (hTmp--)
1668	    gx->font = *char1++;
1669    }
1670    gx->incx = 0;
1671    gx->incy = 0;
1672    GXWait (gx, r);
1673    gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8;
1674    GXResetClip (gx, pDrawable->pScreen);
1675}
1676
1677static void
1678sunGXPolyTEGlyphBlt(
1679    DrawablePtr	pDrawable,
1680    GCPtr	pGC,
1681    int 	x,
1682    int 	y,
1683    unsigned int nglyph,
1684    CharInfoPtr *ppci,		/* array of character info */
1685    void	*pglyphBase	/* start of array of glyphs */
1686)
1687{
1688    sunGXTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1);
1689}
1690
1691static void
1692sunGXFillBoxSolid(DrawablePtr pDrawable, int nBox, BoxPtr pBox, unsigned long pixel)
1693{
1694    register sunGXPtr	gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1695    register int	r;
1696
1697    GXDrawInit(gx,pixel,gx_solid_rop_table[GXcopy]|POLY_N,~0);
1698    while (nBox--) {
1699	gx->arecty = pBox->y1;
1700	gx->arectx = pBox->x1;
1701	gx->arecty = pBox->y2;
1702	gx->arectx = pBox->x2;
1703	pBox++;
1704	GXDrawDone(gx,r);
1705    }
1706    GXWait(gx,r);
1707}
1708
1709void
1710sunGXFillBoxStipple(DrawablePtr pDrawable, int nBox, BoxPtr pBox, sunGXStipplePtr stipple)
1711{
1712    register sunGXPtr	gx = sunGXGetScreenPrivate (pDrawable->pScreen);
1713    register int	r;
1714    int			patx, paty;
1715
1716    patx = 16 - (pDrawable->x & 0xf);
1717    paty = 16 - (pDrawable->y & 0xf);
1718    stipple->patalign = (patx <<  16) | paty;
1719    GXDrawInit(gx,0,gx_solid_rop_table[GXcopy]|POLY_N,~0);
1720    GXStippleInit(gx, stipple);
1721    while (nBox--) {
1722	gx->arecty = pBox->y1;
1723	gx->arectx = pBox->x1;
1724	gx->arecty = pBox->y2;
1725	gx->arectx = pBox->x2;
1726	pBox++;
1727	GXDrawDone(gx,r);
1728    }
1729    GXWait(gx,r);
1730}
1731
1732Bool
1733sunGXCheckTile(PixmapPtr pPixmap, sunGXStipplePtr stipple)
1734{
1735    unsigned short  *sbits;
1736    unsigned int    fg = (unsigned int)~0, bg = (unsigned int)~0;
1737    unsigned char   *tilebitsLine, *tilebits, tilebit;
1738    unsigned short  sbit, mask;
1739    int		    nbwidth;
1740    int		    h, w;
1741    int		    x, y;
1742    int		    s_y, s_x;
1743
1744    h = pPixmap->drawable.height;
1745    if (h > 16 || (h & (h - 1)))
1746	return FALSE;
1747    w = pPixmap->drawable.width;
1748    if (w > 16 || (w & (w - 1)))
1749	return FALSE;
1750    sbits = (unsigned short *) stipple->bits;
1751    tilebitsLine = (unsigned char *) pPixmap->devPrivate.ptr;
1752    nbwidth = pPixmap->devKind;
1753    for (y = 0; y < h; y++) {
1754	tilebits = tilebitsLine;
1755	tilebitsLine += nbwidth;
1756	sbit = 0;
1757	mask = 1 << 15;
1758	for (x = 0; x < w; x++)
1759	{
1760	    tilebit = *tilebits++;
1761	    if (tilebit == fg)
1762		sbit |=  mask;
1763	    else if (tilebit != bg)
1764	    {
1765		if (fg == ~0)
1766		{
1767		    fg = tilebit;
1768		    sbit |= mask;
1769		}
1770		else if (bg == ~0)
1771		{
1772		    bg = tilebit;
1773		}
1774		else
1775		{
1776		    return FALSE;
1777		}
1778	    }
1779	    mask >>= 1;
1780	}
1781	for (s_x = w; s_x < 16; s_x <<= 1)
1782	    sbit = sbit | (sbit >> s_x);
1783	for (s_y = y; s_y < 16; s_y += h)
1784	    sbits[s_y] = sbit;
1785    }
1786    stipple->fore = fg;
1787    stipple->back = bg;
1788    return TRUE;
1789}
1790
1791Bool
1792sunGXCheckStipple(PixmapPtr pPixmap, sunGXStipplePtr stipple)
1793{
1794    unsigned short  *sbits;
1795    unsigned int   *stippleBits;
1796    unsigned long   sbit, mask;
1797    int		    h, w;
1798    int		    y;
1799    int		    s_y, s_x;
1800
1801    h = pPixmap->drawable.height;
1802    if (h > 16 || (h & (h - 1)))
1803	return FALSE;
1804    w = pPixmap->drawable.width;
1805    if (w > 16 || (w & (w - 1)))
1806	return FALSE;
1807    sbits = (unsigned short *) stipple->bits;
1808    stippleBits = (unsigned int *) pPixmap->devPrivate.ptr;
1809    mask = ((1 << w) - 1) << (16 - w);
1810    for (y = 0; y < h; y++) {
1811	sbit = (*stippleBits++ >> 16) & mask;
1812	for (s_x = w; s_x < 16; s_x <<= 1)
1813	    sbit = sbit | (sbit >> s_x);
1814	for (s_y = y; s_y < 16; s_y += h)
1815	    sbits[s_y] = sbit;
1816    }
1817    return TRUE;
1818}
1819
1820/* cache one stipple; figuring out if we can use the stipple is as hard as
1821 * computing it, so we just use this one and leave it here if it
1822 * can't be used this time
1823 */
1824
1825static  sunGXStipplePtr tmpStipple;
1826
1827Bool
1828sunGXCheckFill(GCPtr pGC, DrawablePtr pDrawable)
1829{
1830    sunGXPrivGCPtr	    gxPriv = sunGXGetGCPrivate (pGC);
1831    sunGXStipplePtr	    stipple;
1832    Uint		    alu;
1833    int			    xrot, yrot;
1834
1835    if (pGC->fillStyle == FillSolid)
1836    {
1837	if (gxPriv->stipple)
1838	{
1839	    free (gxPriv->stipple);
1840	    gxPriv->stipple = 0;
1841	}
1842	return TRUE;
1843    }
1844    if (!(stipple = gxPriv->stipple))
1845    {
1846	if (!tmpStipple)
1847	{
1848	    tmpStipple = malloc (sizeof *tmpStipple);
1849	    if (!tmpStipple)
1850		return FALSE;
1851	}
1852	stipple = tmpStipple;
1853    }
1854    alu =  gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
1855    switch (pGC->fillStyle) {
1856    case FillTiled:
1857	if (!sunGXCheckTile (pGC->tile.pixmap, stipple))
1858	{
1859	    if (gxPriv->stipple)
1860	    {
1861		xfree (gxPriv->stipple);
1862		gxPriv->stipple = 0;
1863	    }
1864	    return FALSE;
1865	}
1866	break;
1867    case FillStippled:
1868	alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
1869    case FillOpaqueStippled:
1870	if (!sunGXCheckStipple (pGC->stipple, stipple))
1871	{
1872	    if (gxPriv->stipple)
1873	    {
1874	    	xfree (gxPriv->stipple);
1875	    	gxPriv->stipple = 0;
1876	    }
1877	    return FALSE;
1878	}
1879	stipple->fore = pGC->fgPixel;
1880	stipple->back = pGC->bgPixel;
1881	break;
1882    }
1883    xrot = (pGC->patOrg.x + pDrawable->x) & 0xf;
1884    yrot = (pGC->patOrg.y + pDrawable->y) & 0xf;
1885/*
1886    stipple->patalign = ((16 - (xrot & 0xf)) << 16) | (16 - (yrot & 0xf));
1887*/
1888    xrot = 16 - xrot;
1889    yrot = 16 - yrot;
1890    stipple->patalign = (xrot << 16) | yrot;
1891    stipple->alu = alu;
1892    gxPriv->stipple = stipple;
1893    if (stipple == tmpStipple)
1894	tmpStipple = 0;
1895    return TRUE;
1896}
1897
1898void sunGXValidateGC(GCPtr, Mask, DrawablePtr);
1899void sunGXDestroyGC(GCPtr);
1900
1901GCFuncs	sunGXGCFuncs = {
1902    sunGXValidateGC,
1903    miChangeGC,
1904    miCopyGC,
1905    sunGXDestroyGC,
1906    miChangeClip,
1907    miDestroyClip,
1908    miCopyClip
1909};
1910
1911GCOps	sunGXTEOps1Rect = {
1912    sunGXFillSpans,
1913    cfbSetSpans,
1914    cfbPutImage,
1915    sunGXCopyArea,
1916    sunGXCopyPlane,
1917    cfbPolyPoint,
1918    sunGXPolylines1Rect,
1919    sunGXPolySeg1Rect,
1920    miPolyRectangle,
1921    cfbZeroPolyArcSS8Copy,
1922    sunGXFillPoly1Rect,
1923    sunGXPolyFillRect1Rect,
1924    sunGXPolyFillArc,
1925    miPolyText8,
1926    miPolyText16,
1927    miImageText8,
1928    miImageText16,
1929    sunGXTEGlyphBlt,
1930    sunGXPolyTEGlyphBlt,
1931    cfbPushPixels8
1932#ifdef NEED_LINEHELPER
1933    ,NULL
1934#endif
1935};
1936
1937GCOps	sunGXTEOps = {
1938    sunGXFillSpans,
1939    cfbSetSpans,
1940    cfbPutImage,
1941    sunGXCopyArea,
1942    sunGXCopyPlane,
1943    cfbPolyPoint,
1944    cfbLineSS,
1945    cfbSegmentSS,
1946    miPolyRectangle,
1947    cfbZeroPolyArcSS8Copy,
1948    miFillPolygon,
1949    sunGXPolyFillRect,
1950    sunGXPolyFillArc,
1951    miPolyText8,
1952    miPolyText16,
1953    miImageText8,
1954    miImageText16,
1955    sunGXTEGlyphBlt,
1956    sunGXPolyTEGlyphBlt,
1957    cfbPushPixels8
1958#ifdef NEED_LINEHELPER
1959    ,NULL
1960#endif
1961};
1962
1963GCOps	sunGXNonTEOps1Rect = {
1964    sunGXFillSpans,
1965    cfbSetSpans,
1966    cfbPutImage,
1967    sunGXCopyArea,
1968    sunGXCopyPlane,
1969    cfbPolyPoint,
1970    sunGXPolylines1Rect,
1971    sunGXPolySeg1Rect,
1972    miPolyRectangle,
1973    cfbZeroPolyArcSS8Copy,
1974    sunGXFillPoly1Rect,
1975    sunGXPolyFillRect1Rect,
1976    sunGXPolyFillArc,
1977    miPolyText8,
1978    miPolyText16,
1979    miImageText8,
1980    miImageText16,
1981    miImageGlyphBlt,
1982    sunGXPolyGlyphBlt,
1983    cfbPushPixels8
1984#ifdef NEED_LINEHELPER
1985    ,NULL
1986#endif
1987};
1988
1989GCOps	sunGXNonTEOps = {
1990    sunGXFillSpans,
1991    cfbSetSpans,
1992    cfbPutImage,
1993    sunGXCopyArea,
1994    sunGXCopyPlane,
1995    cfbPolyPoint,
1996    cfbLineSS,
1997    cfbSegmentSS,
1998    miPolyRectangle,
1999    cfbZeroPolyArcSS8Copy,
2000    miFillPolygon,
2001    sunGXPolyFillRect,
2002    sunGXPolyFillArc,
2003    miPolyText8,
2004    miPolyText16,
2005    miImageText8,
2006    miImageText16,
2007    miImageGlyphBlt,
2008    sunGXPolyGlyphBlt,
2009    cfbPushPixels8
2010#ifdef NEED_LINEHELPER
2011    ,NULL
2012#endif
2013};
2014
2015#define FONTWIDTH(font)	(FONTMAXBOUNDS(font,rightSideBearing) - \
2016			 FONTMINBOUNDS(font,leftSideBearing))
2017
2018GCOps *
2019sunGXMatchCommon(GCPtr pGC, cfbPrivGCPtr devPriv)
2020{
2021    if (pGC->lineWidth != 0)
2022	return 0;
2023    if (pGC->lineStyle != LineSolid)
2024	return 0;
2025    if (pGC->fillStyle != FillSolid)
2026	return 0;
2027    if (devPriv->rop != GXcopy)
2028	return 0;
2029    if (!WID_OK(pGC->pScreen))
2030	return 0;
2031    if (pGC->font &&
2032        FONTWIDTH (pGC->font) <= 32 &&
2033	FONTMINBOUNDS(pGC->font,characterWidth) >= 0)
2034    {
2035	if (TERMINALFONT(pGC->font))
2036	    if (devPriv->oneRect)
2037		return &sunGXTEOps1Rect;
2038	    else
2039		return &sunGXTEOps;
2040	else
2041	    if (devPriv->oneRect)
2042		return &sunGXNonTEOps1Rect;
2043	    else
2044		return &sunGXNonTEOps;
2045    }
2046    return 0;
2047}
2048
2049void
2050sunGXValidateGC(GCPtr pGC, Mask changes, DrawablePtr pDrawable)
2051{
2052    int         mask;		/* stateChanges */
2053    int         index;		/* used for stepping through bitfields */
2054    int		new_rrop;
2055    int         new_line, new_text, new_fillspans, new_fillarea;
2056    int		new_rotate;
2057    int		xrot, yrot;
2058    /* flags for changing the proc vector */
2059    cfbPrivGCPtr devPriv;
2060    sunGXPrivGCPtr  gxPriv;
2061    int		oneRect;
2062    int		canGX;
2063    int		widOK;
2064
2065    gxPriv = sunGXGetGCPrivate (pGC);
2066    widOK = WID_OK(pGC->pScreen);
2067    if (pDrawable->type != DRAWABLE_WINDOW)
2068    {
2069	if (gxPriv->type == DRAWABLE_WINDOW)
2070	{
2071	    extern GCOps    cfbNonTEOps;
2072
2073	    miDestroyGCOps (pGC->ops);
2074	    pGC->ops = &cfbNonTEOps;
2075	    changes = (1 << (GCLastBit + 1)) - 1;
2076	    pGC->stateChanges = changes;
2077	    gxPriv->type = pDrawable->type;
2078	}
2079	cfbValidateGC (pGC, changes, pDrawable);
2080	return;
2081    }
2082    if (gxPriv->type != DRAWABLE_WINDOW)
2083    {
2084	changes = (1 << (GCLastBit + 1)) - 1;
2085	gxPriv->type = DRAWABLE_WINDOW;
2086    }
2087
2088    new_rotate = pGC->lastWinOrg.x != pDrawable->x ||
2089		 pGC->lastWinOrg.y != pDrawable->y;
2090
2091    pGC->lastWinOrg.x = pDrawable->x;
2092    pGC->lastWinOrg.y = pDrawable->y;
2093
2094    devPriv = ((cfbPrivGCPtr) (pGC->devPrivates[cfbGCPrivateIndex].ptr));
2095
2096    new_rrop = FALSE;
2097    new_line = FALSE;
2098    new_text = FALSE;
2099    new_fillspans = FALSE;
2100    new_fillarea = FALSE;
2101
2102    /*
2103     * if the client clip is different or moved OR the subwindowMode has
2104     * changed OR the window's clip has changed since the last validation
2105     * we need to recompute the composite clip
2106     */
2107
2108    if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
2109	(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
2110	)
2111    {
2112	miComputeCompositeClip(pGC, pDrawable);
2113	oneRect = REGION_NUM_RECTS(pGC->pCompositeClip) == 1;
2114	if (oneRect != devPriv->oneRect)
2115	{
2116	    new_line = TRUE;
2117	    new_fillarea = TRUE;
2118	    devPriv->oneRect = oneRect;
2119	}
2120    }
2121
2122    mask = changes;
2123    while (mask) {
2124	index = lowbit (mask);
2125	mask &= ~index;
2126
2127	/*
2128	 * this switch acculmulates a list of which procedures might have
2129	 * to change due to changes in the GC.  in some cases (e.g.
2130	 * changing one 16 bit tile for another) we might not really need
2131	 * a change, but the code is being paranoid. this sort of batching
2132	 * wins if, for example, the alu and the font have been changed,
2133	 * or any other pair of items that both change the same thing.
2134	 */
2135	switch (index) {
2136	case GCFunction:
2137	case GCForeground:
2138	    new_rrop = TRUE;
2139	    break;
2140	case GCPlaneMask:
2141	    new_rrop = TRUE;
2142	    new_text = TRUE;
2143	    break;
2144	case GCBackground:
2145	    break;
2146	case GCLineStyle:
2147	case GCLineWidth:
2148	    new_line = TRUE;
2149	    break;
2150	case GCCapStyle:
2151	    break;
2152	case GCJoinStyle:
2153	    break;
2154	case GCFillStyle:
2155	    new_text = TRUE;
2156	    new_fillspans = TRUE;
2157	    new_line = TRUE;
2158	    new_fillarea = TRUE;
2159	    break;
2160	case GCFillRule:
2161	    break;
2162	case GCTile:
2163	    new_fillspans = TRUE;
2164	    new_fillarea = TRUE;
2165	    break;
2166
2167	case GCStipple:
2168	    new_fillspans = TRUE;
2169	    new_fillarea = TRUE;
2170	    break;
2171
2172	case GCTileStipXOrigin:
2173	    new_rotate = TRUE;
2174	    break;
2175
2176	case GCTileStipYOrigin:
2177	    new_rotate = TRUE;
2178	    break;
2179
2180	case GCFont:
2181	    new_text = TRUE;
2182	    break;
2183	case GCSubwindowMode:
2184	    break;
2185	case GCGraphicsExposures:
2186	    break;
2187	case GCClipXOrigin:
2188	    break;
2189	case GCClipYOrigin:
2190	    break;
2191	case GCClipMask:
2192	    break;
2193	case GCDashOffset:
2194	    break;
2195	case GCDashList:
2196	    break;
2197	case GCArcMode:
2198	    break;
2199	default:
2200	    break;
2201	}
2202    }
2203
2204    /*
2205     * If the drawable has changed,  check its depth & ensure suitable
2206     * entries are in the proc vector.
2207     */
2208    if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) {
2209	new_fillspans = TRUE;	/* deal with FillSpans later */
2210    }
2211
2212    if ((new_rotate || new_fillspans))
2213    {
2214	Bool new_pix = FALSE;
2215	xrot = pGC->patOrg.x + pDrawable->x;
2216	yrot = pGC->patOrg.y + pDrawable->y;
2217
2218	if (!sunGXCheckFill (pGC, pDrawable))
2219	{
2220	    switch (pGC->fillStyle)
2221	    {
2222	    case FillTiled:
2223	    	if (!pGC->tileIsPixel)
2224	    	{
2225		    int width = pGC->tile.pixmap->drawable.width * PSZ;
2226
2227		    if ((width <= 32) && !(width & (width - 1)))
2228		    {
2229		    	cfbCopyRotatePixmap(pGC->tile.pixmap,
2230					    &pGC->pRotatedPixmap,
2231					    xrot, yrot);
2232		    	new_pix = TRUE;
2233		    }
2234	    	}
2235	    	break;
2236	    case FillStippled:
2237	    case FillOpaqueStippled:
2238	    	{
2239		    int width = pGC->stipple->drawable.width;
2240
2241		    if ((width <= 32) && !(width & (width - 1)))
2242		    {
2243		    	mfbCopyRotatePixmap(pGC->stipple,
2244					    &pGC->pRotatedPixmap, xrot, yrot);
2245		    	new_pix = TRUE;
2246		    }
2247	    	}
2248	    	break;
2249	    }
2250	}
2251	if (!new_pix && pGC->pRotatedPixmap)
2252	{
2253	    cfbDestroyPixmap(pGC->pRotatedPixmap);
2254	    pGC->pRotatedPixmap = NULL;
2255	}
2256    }
2257
2258    if (new_rrop)
2259    {
2260	int old_rrop;
2261
2262	if (gxPriv->stipple)
2263	{
2264	    if (pGC->fillStyle == FillStippled)
2265		gxPriv->stipple->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
2266	    else
2267		gxPriv->stipple->alu = gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
2268	    if (pGC->fillStyle != FillTiled)
2269	    {
2270		gxPriv->stipple->fore = pGC->fgPixel;
2271		gxPriv->stipple->back = pGC->bgPixel;
2272	    }
2273	}
2274	old_rrop = devPriv->rop;
2275	devPriv->rop = cfbReduceRasterOp (pGC->alu, pGC->fgPixel,
2276					   pGC->planemask,
2277					   &devPriv->and, &devPriv->xor);
2278	if (old_rrop == devPriv->rop)
2279	    new_rrop = FALSE;
2280	else
2281	{
2282	    new_line = TRUE;
2283	    new_text = TRUE;
2284	    new_fillspans = TRUE;
2285	    new_fillarea = TRUE;
2286	}
2287    }
2288
2289    if (new_rrop || new_fillspans || new_text || new_fillarea || new_line)
2290    {
2291	GCOps	*newops;
2292
2293	if ((newops = sunGXMatchCommon (pGC, devPriv)))
2294 	{
2295	    if (pGC->ops->devPrivate.val)
2296		miDestroyGCOps (pGC->ops);
2297	    pGC->ops = newops;
2298	    new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0;
2299	}
2300 	else
2301 	{
2302	    if (!pGC->ops->devPrivate.val)
2303	    {
2304		pGC->ops = miCreateGCOps (pGC->ops);
2305		pGC->ops->devPrivate.val = 1;
2306	    }
2307	}
2308    }
2309
2310    canGX = pGC->fillStyle == FillSolid || gxPriv->stipple;
2311
2312    /* deal with the changes we've collected */
2313    if (new_line)
2314    {
2315	pGC->ops->FillPolygon = miFillPolygon;
2316	if (devPriv->oneRect && canGX)
2317	    pGC->ops->FillPolygon = sunGXFillPoly1Rect;
2318	if (pGC->lineWidth == 0)
2319	{
2320	    if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid))
2321	    {
2322		switch (devPriv->rop)
2323		{
2324		case GXxor:
2325		    pGC->ops->PolyArc = cfbZeroPolyArcSS8Xor;
2326		    break;
2327		case GXcopy:
2328		    pGC->ops->PolyArc = cfbZeroPolyArcSS8Copy;
2329		    break;
2330		default:
2331		    pGC->ops->PolyArc = cfbZeroPolyArcSS8General;
2332		    break;
2333		}
2334	    }
2335	    else
2336		pGC->ops->PolyArc = miZeroPolyArc;
2337	}
2338	else
2339	    pGC->ops->PolyArc = miPolyArc;
2340	pGC->ops->PolySegment = miPolySegment;
2341	switch (pGC->lineStyle)
2342	{
2343	case LineSolid:
2344	    if(pGC->lineWidth == 0)
2345	    {
2346		if (devPriv->oneRect && canGX && widOK)
2347		{
2348		    pGC->ops->PolySegment = sunGXPolySeg1Rect;
2349		    pGC->ops->Polylines = sunGXPolylines1Rect;
2350		}
2351		else if (pGC->fillStyle == FillSolid)
2352		{
2353		    if (devPriv->oneRect)
2354		    {
2355			pGC->ops->Polylines = cfb8LineSS1Rect;
2356			pGC->ops->PolySegment = cfb8SegmentSS1Rect;
2357		    }
2358		    else
2359		    {
2360		    	pGC->ops->Polylines = cfbLineSS;
2361		    	pGC->ops->PolySegment = cfbSegmentSS;
2362		    }
2363		}
2364		else
2365		    pGC->ops->Polylines = miZeroLine;
2366	    }
2367	    else
2368		pGC->ops->Polylines = miWideLine;
2369	    break;
2370	case LineOnOffDash:
2371	case LineDoubleDash:
2372	    if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid)
2373	    {
2374		pGC->ops->Polylines = cfbLineSD;
2375		pGC->ops->PolySegment = cfbSegmentSD;
2376	    } else
2377		pGC->ops->Polylines = miWideDash;
2378	    break;
2379	}
2380    }
2381
2382    if (new_text && (pGC->font))
2383    {
2384        if (FONTWIDTH(pGC->font) > 32 ||
2385	    FONTMINBOUNDS(pGC->font,characterWidth) < 0)
2386        {
2387            pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
2388            pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
2389        }
2390        else
2391        {
2392	    if (pGC->fillStyle == FillSolid)
2393	    {
2394		if (TERMINALFONT (pGC->font))
2395		    pGC->ops->PolyGlyphBlt = sunGXPolyTEGlyphBlt;
2396		else
2397		    pGC->ops->PolyGlyphBlt = sunGXPolyGlyphBlt;
2398	    }
2399	    else
2400		pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
2401            /* special case ImageGlyphBlt for terminal emulator fonts */
2402            if (TERMINALFONT(pGC->font))
2403		pGC->ops->ImageGlyphBlt = sunGXTEGlyphBlt;
2404            else
2405                pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
2406        }
2407    }
2408
2409
2410    if (new_fillspans) {
2411	if (canGX)
2412	    pGC->ops->FillSpans = sunGXFillSpans;
2413	else switch (pGC->fillStyle) {
2414	case FillTiled:
2415	    if (pGC->pRotatedPixmap)
2416	    {
2417		if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK)
2418		    pGC->ops->FillSpans = cfbTile32FSCopy;
2419		else
2420		    pGC->ops->FillSpans = cfbTile32FSGeneral;
2421	    }
2422	    else
2423		pGC->ops->FillSpans = cfbUnnaturalTileFS;
2424	    break;
2425	case FillStippled:
2426	    if (pGC->pRotatedPixmap)
2427		pGC->ops->FillSpans = cfb8Stipple32FS;
2428	    else
2429		pGC->ops->FillSpans = cfbUnnaturalStippleFS;
2430	    break;
2431	case FillOpaqueStippled:
2432	    if (pGC->pRotatedPixmap)
2433		pGC->ops->FillSpans = cfb8OpaqueStipple32FS;
2434	    else
2435		pGC->ops->FillSpans = cfbUnnaturalStippleFS;
2436	    break;
2437	default:
2438	    FatalError("cfbValidateGC: illegal fillStyle\n");
2439	}
2440    } /* end of new_fillspans */
2441
2442    if (new_fillarea) {
2443	pGC->ops->PolyFillRect = cfbPolyFillRect;
2444	pGC->ops->PolyFillArc = miPolyFillArc;
2445	if (canGX)
2446	{
2447	    pGC->ops->PolyFillArc = sunGXPolyFillArc;
2448	    pGC->ops->PolyFillRect = sunGXPolyFillRect;
2449	    if (devPriv->oneRect)
2450		pGC->ops->PolyFillRect = sunGXPolyFillRect1Rect;
2451	}
2452	pGC->ops->PushPixels = mfbPushPixels;
2453	if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy)
2454	    pGC->ops->PushPixels = cfbPushPixels8;
2455    }
2456}
2457
2458void
2459sunGXDestroyGC(GCPtr pGC)
2460{
2461    sunGXPrivGCPtr	    gxPriv = sunGXGetGCPrivate (pGC);
2462
2463    if (gxPriv->stipple)
2464	xfree (gxPriv->stipple);
2465    miDestroyGC (pGC);
2466}
2467
2468Bool
2469sunGXCreateGC(GCPtr pGC)
2470{
2471    sunGXPrivGCPtr  gxPriv;
2472    if (pGC->depth == 1)
2473	return mfbCreateGC (pGC);
2474    if (!cfbCreateGC (pGC))
2475	return FALSE;
2476    pGC->ops = &sunGXNonTEOps;
2477    pGC->funcs = &sunGXGCFuncs;
2478    gxPriv = sunGXGetGCPrivate(pGC);
2479    gxPriv->type = DRAWABLE_WINDOW;
2480    gxPriv->stipple = 0;
2481    return TRUE;
2482}
2483
2484Bool
2485sunGXCreateWindow(WindowPtr pWin)
2486{
2487    if (!cfbCreateWindow (pWin))
2488	return FALSE;
2489    pWin->devPrivates[sunGXWindowPrivateIndex].ptr = 0;
2490    return TRUE;
2491}
2492
2493Bool
2494sunGXDestroyWindow(WindowPtr pWin)
2495{
2496    sunGXStipplePtr stipple = sunGXGetWindowPrivate(pWin);
2497    xfree (stipple);
2498    return cfbDestroyWindow (pWin);
2499}
2500
2501Bool
2502sunGXChangeWindowAttributes(WindowPtr pWin, Mask mask)
2503{
2504    sunGXStipplePtr stipple;
2505    Mask	    index;
2506    WindowPtr	pBgWin;
2507    register cfbPrivWin *pPrivWin;
2508    int		    width;
2509
2510    pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr);
2511    /*
2512     * When background state changes from ParentRelative and
2513     * we had previously rotated the fast border pixmap to match
2514     * the parent relative origin, rerotate to match window
2515     */
2516    if (mask & (CWBackPixmap | CWBackPixel) &&
2517	pWin->backgroundState != ParentRelative &&
2518	pPrivWin->fastBorder &&
2519	(pPrivWin->oldRotate.x != pWin->drawable.x ||
2520	 pPrivWin->oldRotate.y != pWin->drawable.y))
2521    {
2522	cfbXRotatePixmap(pPrivWin->pRotatedBorder,
2523		      pWin->drawable.x - pPrivWin->oldRotate.x);
2524	cfbYRotatePixmap(pPrivWin->pRotatedBorder,
2525		      pWin->drawable.y - pPrivWin->oldRotate.y);
2526	pPrivWin->oldRotate.x = pWin->drawable.x;
2527	pPrivWin->oldRotate.y = pWin->drawable.y;
2528    }
2529    while (mask)
2530    {
2531	index = lowbit(mask);
2532	mask &= ~index;
2533	switch (index)
2534	{
2535	case CWBackPixmap:
2536	    stipple = sunGXGetWindowPrivate(pWin);
2537	    if (pWin->backgroundState == None ||
2538		pWin->backgroundState == ParentRelative)
2539	    {
2540		pPrivWin->fastBackground = FALSE;
2541		if (stipple)
2542		{
2543		    xfree (stipple);
2544		    sunGXSetWindowPrivate(pWin,0);
2545		}
2546		/* Rotate border to match parent origin */
2547		if (pWin->backgroundState == ParentRelative &&
2548		    pPrivWin->pRotatedBorder)
2549		{
2550		    for (pBgWin = pWin->parent;
2551			 pBgWin->backgroundState == ParentRelative;
2552			 pBgWin = pBgWin->parent);
2553		    cfbXRotatePixmap(pPrivWin->pRotatedBorder,
2554				  pBgWin->drawable.x - pPrivWin->oldRotate.x);
2555		    cfbYRotatePixmap(pPrivWin->pRotatedBorder,
2556				  pBgWin->drawable.y - pPrivWin->oldRotate.y);
2557		}
2558
2559		break;
2560	    }
2561	    if (!stipple)
2562	    {
2563		if (!tmpStipple)
2564		    tmpStipple = malloc (sizeof *tmpStipple);
2565		stipple = tmpStipple;
2566	    }
2567 	    if (stipple && sunGXCheckTile (pWin->background.pixmap, stipple))
2568	    {
2569		stipple->alu = gx_opaque_stipple_rop_table[GXcopy]|GX_PATTERN_MASK;
2570		pPrivWin->fastBackground = FALSE;
2571		if (stipple == tmpStipple)
2572		{
2573		    sunGXSetWindowPrivate(pWin, stipple);
2574		    tmpStipple = 0;
2575		}
2576		break;
2577	    }
2578	    if ((stipple = sunGXGetWindowPrivate(pWin)))
2579	    {
2580		xfree (stipple);
2581		sunGXSetWindowPrivate(pWin,0);
2582	    }
2583 	    if (((width = (pWin->background.pixmap->drawable.width * PSZ)) <= BITMAP_SCANLINE_UNIT) &&
2584		       !(width & (width - 1)))
2585	    {
2586		cfbCopyRotatePixmap(pWin->background.pixmap,
2587				  &pPrivWin->pRotatedBackground,
2588				  pWin->drawable.x,
2589				  pWin->drawable.y);
2590		if (pPrivWin->pRotatedBackground)
2591		{
2592    	    	    pPrivWin->fastBackground = TRUE;
2593    	    	    pPrivWin->oldRotate.x = pWin->drawable.x;
2594    	    	    pPrivWin->oldRotate.y = pWin->drawable.y;
2595		}
2596		else
2597		{
2598		    pPrivWin->fastBackground = FALSE;
2599		}
2600		break;
2601	    }
2602	    pPrivWin->fastBackground = FALSE;
2603	    break;
2604
2605	case CWBackPixel:
2606	    pPrivWin->fastBackground = FALSE;
2607	    break;
2608
2609	case CWBorderPixmap:
2610	    /* don't bother with accelerator for border tiles (just lazy) */
2611	    if (((width = (pWin->border.pixmap->drawable.width * PSZ)) <= BITMAP_SCANLINE_UNIT) &&
2612		!(width & (width - 1)))
2613	    {
2614		for (pBgWin = pWin;
2615		     pBgWin->backgroundState == ParentRelative;
2616		     pBgWin = pBgWin->parent);
2617		cfbCopyRotatePixmap(pWin->border.pixmap,
2618				    &pPrivWin->pRotatedBorder,
2619				    pBgWin->drawable.x,
2620				    pBgWin->drawable.y);
2621		if (pPrivWin->pRotatedBorder)
2622		{
2623		    pPrivWin->fastBorder = TRUE;
2624		    pPrivWin->oldRotate.x = pBgWin->drawable.x;
2625		    pPrivWin->oldRotate.y = pBgWin->drawable.y;
2626		}
2627		else
2628		{
2629		    pPrivWin->fastBorder = TRUE;
2630		}
2631	    }
2632	    else
2633	    {
2634		pPrivWin->fastBorder = FALSE;
2635	    }
2636	    break;
2637	case CWBorderPixel:
2638	    pPrivWin->fastBorder = FALSE;
2639	    break;
2640	}
2641    }
2642    return (TRUE);
2643}
2644
2645void
2646sunGXPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
2647{
2648    register cfbPrivWin	*pPrivWin;
2649    sunGXStipplePtr stipple;
2650    WindowPtr	pBgWin;
2651    pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr);
2652
2653    switch (what) {
2654    case PW_BACKGROUND:
2655	stipple = sunGXGetWindowPrivate(pWin);
2656	switch (pWin->backgroundState) {
2657	case None:
2658	    return;
2659	case ParentRelative:
2660	    do {
2661		pWin = pWin->parent;
2662	    } while (pWin->backgroundState == ParentRelative);
2663	    (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
2664							     what);
2665	    return;
2666	case BackgroundPixmap:
2667	    if (stipple)
2668	    {
2669		sunGXFillBoxStipple ((DrawablePtr)pWin,
2670				  (int)REGION_NUM_RECTS(pRegion),
2671				  REGION_RECTS(pRegion),
2672				  stipple);
2673	    }
2674	    else if (pPrivWin->fastBackground)
2675	    {
2676		cfbFillBoxTile32 ((DrawablePtr)pWin,
2677				  (int)REGION_NUM_RECTS(pRegion),
2678				  REGION_RECTS(pRegion),
2679				  pPrivWin->pRotatedBackground);
2680	    }
2681	    else
2682	    {
2683		cfbFillBoxTileOdd ((DrawablePtr)pWin,
2684				   (int)REGION_NUM_RECTS(pRegion),
2685				   REGION_RECTS(pRegion),
2686				   pWin->background.pixmap,
2687				   (int) pWin->drawable.x, (int) pWin->drawable.y);
2688	    }
2689	    return;
2690	case BackgroundPixel:
2691	    sunGXFillBoxSolid((DrawablePtr)pWin,
2692			     (int)REGION_NUM_RECTS(pRegion),
2693			     REGION_RECTS(pRegion),
2694			     pWin->background.pixel);
2695	    return;
2696    	}
2697    	break;
2698    case PW_BORDER:
2699	if (pWin->borderIsPixel)
2700	{
2701	    sunGXFillBoxSolid((DrawablePtr)pWin,
2702			     (int)REGION_NUM_RECTS(pRegion),
2703			     REGION_RECTS(pRegion),
2704			     pWin->border.pixel);
2705	    return;
2706	}
2707	else if (pPrivWin->fastBorder)
2708	{
2709	    cfbFillBoxTile32 ((DrawablePtr)pWin,
2710			      (int)REGION_NUM_RECTS(pRegion),
2711			      REGION_RECTS(pRegion),
2712			      pPrivWin->pRotatedBorder);
2713	    return;
2714	}
2715	else
2716	{
2717	    for (pBgWin = pWin;
2718		 pBgWin->backgroundState == ParentRelative;
2719		 pBgWin = pBgWin->parent);
2720
2721	    cfbFillBoxTileOdd ((DrawablePtr)pWin,
2722			       (int)REGION_NUM_RECTS(pRegion),
2723			       REGION_RECTS(pRegion),
2724			       pWin->border.pixmap,
2725			       (int) pBgWin->drawable.x,
2726 			       (int) pBgWin->drawable.y);
2727	    return;
2728	}
2729	break;
2730    }
2731}
2732
2733void
2734sunGXCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
2735{
2736    DDXPointPtr pptSrc;
2737    register DDXPointPtr ppt;
2738    RegionPtr prgnDst;
2739    register BoxPtr pbox;
2740    register int dx, dy;
2741    register int i, nbox;
2742    WindowPtr pwinRoot;
2743    extern WindowPtr *WindowTable;
2744
2745    pwinRoot = WindowTable[pWin->drawable.pScreen->myNum];
2746
2747    prgnDst = REGION_CREATE(pWin->drawable.pScreen, NULL, 1);
2748
2749    dx = ptOldOrg.x - pWin->drawable.x;
2750    dy = ptOldOrg.y - pWin->drawable.y;
2751    REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
2752    REGION_INTERSECT(pWin->drawable.pScreen, prgnDst, &pWin->borderClip, prgnSrc);
2753
2754    pbox = REGION_RECTS(prgnDst);
2755    nbox = REGION_NUM_RECTS(prgnDst);
2756    if(!(pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec))))
2757	return;
2758    ppt = pptSrc;
2759
2760    for (i = nbox; --i >= 0; ppt++, pbox++)
2761    {
2762	ppt->x = pbox->x1 + dx;
2763	ppt->y = pbox->y1 + dy;
2764    }
2765
2766    sunGXDoBitblt ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
2767		    GXcopy, prgnDst, pptSrc, ~0L);
2768    DEALLOCATE_LOCAL(pptSrc);
2769    REGION_DESTROY(pWin->drawable.pScreen, prgnDst);
2770}
2771
2772Bool
2773sunGXInit(ScreenPtr pScreen, fbFd *fb)
2774{
2775    sunGXPtr	    gx;
2776    Uint	    mode;
2777    register long   r;
2778
2779    if (serverGeneration != sunGXGeneration)
2780    {
2781	sunGXScreenPrivateIndex = AllocateScreenPrivateIndex();
2782	if (sunGXScreenPrivateIndex == -1)
2783	    return FALSE;
2784	sunGXGCPrivateIndex = AllocateGCPrivateIndex ();
2785	sunGXWindowPrivateIndex = AllocateWindowPrivateIndex ();
2786	sunGXGeneration = serverGeneration;
2787    }
2788    if (!AllocateGCPrivate(pScreen, sunGXGCPrivateIndex, sizeof (sunGXPrivGCRec)))
2789	return FALSE;
2790    if (!AllocateWindowPrivate(pScreen, sunGXWindowPrivateIndex, 0))
2791	return FALSE;
2792    gx = (sunGXPtr) fb->fb;
2793    mode = gx->mode;
2794    GXWait(gx,r);
2795    mode &= ~(	GX_BLIT_ALL |
2796		GX_MODE_ALL |
2797		GX_DRAW_ALL |
2798 		GX_BWRITE0_ALL |
2799		GX_BWRITE1_ALL |
2800 		GX_BREAD_ALL |
2801 		GX_BDISP_ALL);
2802    mode |=	GX_BLIT_SRC |
2803		GX_MODE_COLOR8 |
2804		GX_DRAW_RENDER |
2805		GX_BWRITE0_ENABLE |
2806		GX_BWRITE1_DISABLE |
2807		GX_BREAD_0 |
2808		GX_BDISP_0;
2809    gx->mode = mode;
2810    gx->clip = 0;
2811    gx->offx = 0;
2812    gx->offy = 0;
2813    gx->clipminx = 0;
2814    gx->clipminy = 0;
2815    gx->clipmaxx = fb->info.fb_width - 1;
2816    gx->clipmaxy = fb->info.fb_height - 1;
2817    pScreen->devPrivates[sunGXScreenPrivateIndex].ptr = (void *) gx;
2818    /*
2819     * Replace various screen functions
2820     */
2821    pScreen->CreateGC = sunGXCreateGC;
2822    pScreen->CreateWindow = sunGXCreateWindow;
2823    pScreen->ChangeWindowAttributes = sunGXChangeWindowAttributes;
2824    pScreen->DestroyWindow = sunGXDestroyWindow;
2825    pScreen->PaintWindowBackground = sunGXPaintWindow;
2826    pScreen->PaintWindowBorder = sunGXPaintWindow;
2827    pScreen->CopyWindow = sunGXCopyWindow;
2828    return TRUE;
2829}
2830