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