1
2/*
3 * Copyright 1996  The XFree86 Project
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * HARM HANEMAAYER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 */
24
25/*
26 * Written by Mark Vojkovich.  Loosly based on an original version
27 * written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net) which
28 * only did solid rectangles and didn't have trapezoid support.
29 *
30 */
31
32
33#ifdef HAVE_XORG_CONFIG_H
34#include <xorg-config.h>
35#endif
36
37#include "misc.h"
38#include "xf86.h"
39#include "xf86_OSproc.h"
40
41#include <X11/X.h>
42#include "scrnintstr.h"
43#include "pixmapstr.h"
44#include "xf86str.h"
45#include "mi.h"
46#include "micoord.h"
47
48#include "xaa.h"
49#include "xaalocal.h"
50
51#define POLY_USE_MI		0
52#define POLY_FULLY_CLIPPED	1
53#define POLY_IS_EASY		2
54
55
56#define Setup(c,x,vertex,dx,dy,e,sign,step,DX) {\
57    x = intToX(vertex); \
58    if ((dy = intToY(c) - y)) { \
59    	DX = dx = intToX(c) - x; \
60	step = 0; \
61    	if (dx >= 0) \
62    	{ \
63	    e = 0; \
64	    sign = 1; \
65	    if (dx >= dy) {\
66	    	step = dx / dy; \
67	    	dx %= dy; \
68	    } \
69    	} \
70    	else \
71    	{ \
72	    e = 1 - dy; \
73	    sign = -1; \
74	    dx = -dx; \
75	    if (dx >= dy) { \
76		step = - (dx / dy); \
77		dx %= dy; \
78	    } \
79    	} \
80    } \
81    x += origin; \
82    vertex = c; \
83}
84
85#define Step(x,dx,dy,e,sign,step) {\
86    x += step; \
87    if ((e += dx) > 0) \
88    { \
89	x += sign; \
90	e -= dy; \
91    } \
92}
93
94#define FixError(x, dx, dy, e, sign, step, h)	{	\
95	   e += (h) * dx;				\
96	   x += (h) * step;				\
97	   if(e > 0) {					\
98		x += e * sign/dy;			\
99		e %= dy;				\
100	   	if(e) {					\
101		   x += sign;				\
102		   e -= dy;				\
103		}					\
104	   } 	 					\
105}
106
107
108/*
109   XAAIsEasyPoly -
110
111   Checks CoordModeOrigin one rect polygons to see if we need
112   to use Mi.
113   Returns: POLY_USE_MI, POLY_FULLY_CLIPPED or POLY_IS_EASY
114	as well as the pointer to the "top" point and the y
115	extents.
116*/
117
118int
119XAAIsEasyPolygon(
120   DDXPointPtr ptsIn,
121   int count,
122   BoxPtr extents,
123   int origin,
124   DDXPointPtr *topPoint, 	/* return */
125   int *topY, int *bottomY,	/* return */
126   int shape
127){
128    int c = 0, vertex1, vertex2;
129
130    *topY = 32767;
131    *bottomY = 0;
132
133    origin -= (origin & 0x8000) << 1;
134    vertex1 = extents->x1 - origin;
135    vertex2 = extents->x2 - origin /* - 0x00010001 */;
136                     /* I think this was an error in cfb ^ */
137
138    if (shape == Convex) {
139    	while (count--) {
140	    c = *((int*)ptsIn);
141	    if (((c - vertex1) | (vertex2 - c)) & 0x80008000)
142		return POLY_USE_MI;
143
144	    c = intToY(c);
145	    if (c < *topY) {
146	    	*topY = c;
147	    	*topPoint = ptsIn;
148	    }
149	    ptsIn++;
150	    if (c > *bottomY) *bottomY = c;
151    	}
152    } else {
153	int yFlip = 0;
154	int dx2, dx1, x1, x2;
155
156	x2 = x1 = -1;
157	dx2 = dx1 = 1;
158
159    	while (count--) {
160	    c = *((int*)ptsIn);
161	    if (((c - vertex1) | (vertex2 - c)) & 0x80008000)
162		return POLY_USE_MI;
163	    c = intToY(c);
164	    if (c < *topY) {
165	    	*topY = c;
166	    	*topPoint = ptsIn;
167	    }
168	    ptsIn++;
169	    if (c > *bottomY) *bottomY = c;
170	    if (c == x1)
171		continue;
172	    if (dx1 > 0) {
173		if (x2 < 0) x2 = c;
174		else	    dx2 = dx1 = (c - x1) >> 31;
175	    } else if ((c - x1) >> 31 != dx1) {
176		dx1 = ~dx1;
177		yFlip++;
178	    }
179	    x1 = c;
180       	}
181	x1 = (x2 - c) >> 31;
182	if (x1 != dx1) yFlip++;
183	if (x1 != dx2) yFlip++;
184	if (yFlip != 2) {
185	   if(*topY == *bottomY)
186		return POLY_FULLY_CLIPPED;
187	   else
188		return POLY_USE_MI;
189	}
190    }
191    if (*topY == *bottomY)
192	return POLY_FULLY_CLIPPED;
193
194    return POLY_IS_EASY;
195}
196
197void
198XAAFillPolygonSolid(
199    DrawablePtr	pDraw,
200    GCPtr	pGC,
201    int		shape,
202    int		mode,
203    int		count,
204    DDXPointPtr	ptsIn
205){
206    XAAInfoRecPtr   infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
207    int    	    origin, vertex1, vertex2;
208    int		    *vertex1p, *vertex2p, *endp;
209    int		    x1 = 0, x2 = 0;
210    int 	    dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
211    int		    DX1 = 0, DX2 = 0, e1 = 0, e2 = 0;
212    int		    step1 = 0, step2 = 0, sign1 = 0, sign2 = 0;
213    int		    c, y, maxy, h, yoffset;
214    DDXPointPtr	    topPoint;
215
216    if(!RegionNumRects(pGC->pCompositeClip))
217	return;
218
219    if (mode == CoordModePrevious) {
220	register DDXPointPtr ppt = ptsIn + 1;
221
222	for (origin = 1; origin < count; origin++, ppt++) {
223	    ppt->x += (ppt-1)->x;
224	    ppt->y += (ppt-1)->y;
225	}
226        mode = CoordModeOrigin;
227    }
228
229    if (RegionNumRects(pGC->pCompositeClip) != 1) {
230	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
231	return;
232    }
233
234    origin = coordToInt(pDraw->x, pDraw->y);
235
236    switch( XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents,
237		origin, &topPoint, &y, &maxy, shape) ) {
238    case POLY_USE_MI:
239	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
240    case POLY_FULLY_CLIPPED:
241	return;
242    }
243
244    endp = (int*)ptsIn + count;
245    vertex2p = vertex1p = (int *)topPoint;
246    origin = pDraw->x;
247    yoffset = pDraw->y;
248    vertex2 = vertex1 = *vertex2p++;
249    if (vertex2p == endp)
250	vertex2p = (int *) ptsIn;
251
252    (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu,
253        pGC->planemask);
254
255    while(1) {
256	if (y == intToY(vertex1)) {
257	    do {
258	    	if (vertex1p == (int *) ptsIn)
259		    vertex1p = endp;
260	    	c = *--vertex1p;
261	    	Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1,DX1)
262	    } while (y >= intToY(vertex1));
263	    h = dy1;
264	} else {
265	    Step(x1,dx1,dy1,e1,sign1,step1)
266	    h = intToY(vertex1) - y;
267	}
268	if (y == intToY(vertex2)) {
269	    do {
270	    	c = *vertex2p++;
271	    	if (vertex2p == endp)
272		    vertex2p = (int *) ptsIn;
273	    	Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2,DX2)
274	    } while (y >= intToY(vertex2));
275	    if (dy2 < h)
276		h = dy2;
277	} else {
278	    Step(x2,dx2,dy2,e2,sign2,step2)
279	    if ((c = (intToY(vertex2) - y)) < h)
280		h = c;
281	}
282
283	/* fill spans for this segment */
284        if(DX1 | DX2) {
285      	  if(infoRec->SubsequentSolidFillTrap && (h > 6)) {
286	     if(x1 == x2) {
287		while(x1 == x2) {
288	     	   y++;
289	    	   if (!--h) break;
290	    	   Step(x1,dx1,dy1,e1,sign1,step1)
291	    	   Step(x2,dx2,dy2,e2,sign2,step2)
292		}
293		if(y == maxy) break;
294    		if(!h) continue;
295	     }
296
297             if(x1 < x2)
298 	     	(*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn,
299					y + yoffset, h,
300					x1, DX1, dy1, e1,
301					x2 - 1, DX2, dy2, e2);
302	     else
303 	     	(*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn,
304					y + yoffset, h,
305					x2, DX2, dy2, e2,
306					x1 - 1, DX1, dy1, e1);
307	     y += h;
308             if(--h) {
309	     	FixError(x1,dx1,dy1,e1,sign1,step1,h);
310	     	FixError(x2,dx2,dy2,e2,sign2,step2,h);
311		h = 0;
312	     }
313	  } else {
314	     while(1) {
315	    	if (x2 > x1)
316	            (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
317	            		x1, y + yoffset, x2 - x1, 1);
318	        else if (x1 > x2)
319	            (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
320	                    x2, y + yoffset, x1 - x2, 1);
321	     	y++;
322	    	if (!--h) break;
323	    	Step(x1,dx1,dy1,e1,sign1,step1)
324	    	Step(x2,dx2,dy2,e2,sign2,step2)
325	     }
326	  }
327	} else {
328	    if (x2 > x1)
329	        (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
330	            x1, y + yoffset, x2 - x1, h);
331	    else if (x1 > x2)
332	        (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
333	                x2, y + yoffset, x1 - x2, h);
334
335	    y += h;
336	    h = 0;
337        }
338	if (y == maxy) break;
339    }
340    SET_SYNC_FLAG(infoRec);
341}
342
343
344
345
346void
347XAAFillPolygonHelper(
348    ScrnInfoPtr pScrn,
349    DDXPointPtr	ptsIn,
350    int 	count,
351    DDXPointPtr topPoint,
352    int 	y,
353    int		maxy,
354    int		origin,
355    RectFuncPtr RectFunc,
356    TrapFuncPtr TrapFunc,
357    int 	xorg,
358    int		yorg,
359    XAACacheInfoPtr pCache
360){
361    int		    *vertex1p, *vertex2p, *endp;
362    int		    vertex1, vertex2;
363    int		    x1 = 0, x2 = 0;
364    int		    dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
365    int		    DX1 = 0, DX2 = 0, e1 = 0, e2 = 0;
366    int		    step1 = 0, step2 = 0, sign1 = 0, sign2 = 0;
367    int		    c, h, yoffset;
368
369
370    endp = (int*)ptsIn + count;
371    vertex2p = vertex1p = (int *)topPoint;
372    yoffset = intToY(origin);
373    origin = intToX(origin);
374    vertex2 = vertex1 = *vertex2p++;
375    if (vertex2p == endp)
376	vertex2p = (int *)ptsIn;
377
378    while(1) {
379	if (y == intToY(vertex1)) {
380	    do {
381	    	if (vertex1p == (int *) ptsIn)
382		    vertex1p = endp;
383	    	c = *--vertex1p;
384	    	Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1,DX1)
385	    } while (y >= intToY(vertex1));
386	    h = dy1;
387	} else {
388	    Step(x1,dx1,dy1,e1,sign1,step1)
389	    h = intToY(vertex1) - y;
390	}
391	if (y == intToY(vertex2)) {
392	    do {
393	    	c = *vertex2p++;
394	    	if (vertex2p == endp)
395		    vertex2p = (int *) ptsIn;
396	    	Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2,DX2)
397	    } while (y >= intToY(vertex2));
398	    if (dy2 < h)
399		h = dy2;
400	} else {
401	    Step(x2,dx2,dy2,e2,sign2,step2)
402	    if ((c = (intToY(vertex2) - y)) < h)
403		h = c;
404	}
405
406	/* fill spans for this segment */
407        if(DX1 | DX2) {
408      	  if(TrapFunc && (h > 6)) {
409	     if(x1 == x2) {
410		while(x1 == x2) {
411	     	   y++;
412	    	   if (!--h) break;
413	    	   Step(x1,dx1,dy1,e1,sign1,step1)
414	    	   Step(x2,dx2,dy2,e2,sign2,step2)
415		}
416		if(y == maxy) break;
417    		if(!h) continue;
418	     }
419
420             if(x1 < x2)
421 	     	(*TrapFunc)(pScrn, y + yoffset, h,
422				x1, DX1, dy1, e1,
423				x2 - 1, DX2, dy2, e2, xorg, yorg, pCache);
424	     else
425 	     	(*TrapFunc)(pScrn, y + yoffset, h,
426				x2, DX2, dy2, e2,
427				x1 - 1, DX1, dy1, e1, xorg, yorg, pCache);
428	     y += h;
429             if(--h) {
430	     	FixError(x1,dx1,dy1,e1,sign1,step1,h);
431	     	FixError(x2,dx2,dy2,e2,sign2,step2,h);
432		h = 0;
433	     }
434	  } else {
435	     while(1) {
436	    	if (x2 > x1)
437	            (*RectFunc)(pScrn,
438	            	x1, y + yoffset, x2 - x1, 1, xorg, yorg, pCache);
439	        else if (x1 > x2)
440	            (*RectFunc)(pScrn,
441	                    x2, y + yoffset, x1 - x2, 1, xorg, yorg, pCache);
442	     	y++;
443	    	if (!--h) break;
444	    	Step(x1,dx1,dy1,e1,sign1,step1)
445	    	Step(x2,dx2,dy2,e2,sign2,step2)
446	     }
447	  }
448	} else {
449	    if (x2 > x1)
450	        (*RectFunc)(pScrn,
451	            x1, y + yoffset, x2 - x1, h, xorg, yorg, pCache);
452	    else if (x1 > x2)
453	        (*RectFunc)(pScrn,
454	                x2, y + yoffset, x1 - x2, h, xorg, yorg, pCache);
455
456	    y += h;
457	    h = 0;
458        }
459	if (y == maxy) break;
460    }
461}
462
463        /*****************\
464	|  Solid Helpers  |
465	\*****************/
466
467static void
468SolidTrapHelper(
469   ScrnInfoPtr pScrn,
470   int y, int h,
471   int x1, int dx1, int dy1, int e1,
472   int x2, int dx2, int dy2, int e2,
473   int xorg, int yorg,
474   XAACacheInfoPtr pCache
475){
476    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
477
478    (*infoRec->SubsequentSolidFillTrap) (pScrn,
479		y, h, x1, dx1, dy1, e1, x2, dx2, dy2, e2);
480}
481
482static void
483SolidRectHelper (
484   ScrnInfoPtr pScrn,
485   int x, int y, int w, int h,
486   int xorg, int yorg,
487   XAACacheInfoPtr pCache
488){
489    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
490
491    (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
492}
493
494
495	/*********************\
496	|  Mono 8x8 Patterns  |
497	\*********************/
498
499static void
500Mono8x8PatternTrapHelper_ScreenOrigin(
501   ScrnInfoPtr pScrn,
502   int y, int h,
503   int x1, int dx1, int dy1, int e1,
504   int x2, int dx2, int dy2, int e2,
505   int xorg, int yorg,
506   XAACacheInfoPtr pCache
507){
508    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
509
510    (*infoRec->SubsequentMono8x8PatternFillTrap) (pScrn, xorg, yorg,
511		y, h, x1, dx1, dy1, e1, x2, dx2, dy2, e2);
512}
513
514static void
515Mono8x8PatternRectHelper_ScreenOrigin (
516   ScrnInfoPtr pScrn,
517   int x, int y, int w, int h,
518   int xorg, int yorg,
519   XAACacheInfoPtr pCache
520){
521    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
522
523    (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, xorg, yorg,
524						x, y, w, h);
525}
526
527static void
528Mono8x8PatternRectHelper (
529   ScrnInfoPtr pScrn,
530   int x, int y, int w, int h,
531   int xorg, int yorg,
532   XAACacheInfoPtr pCache
533){
534    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
535
536    xorg = (x - xorg) & 0x07;
537    yorg = (y - yorg) & 0x07;
538
539    if(!(infoRec->Mono8x8PatternFillFlags &
540				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
541	if(infoRec->Mono8x8PatternFillFlags &
542				HARDWARE_PATTERN_PROGRAMMED_BITS) {
543		int patx = pCache->pat0;
544		int paty = pCache->pat1;
545		XAARotateMonoPattern(&patx, &paty, xorg, yorg,
546				(infoRec->Mono8x8PatternFillFlags &
547				BIT_ORDER_IN_BYTE_MSBFIRST));
548		xorg = patx; yorg = paty;
549	} else {
550		int slot = (yorg << 3) + xorg;
551	    	xorg = pCache->x + pCache->offsets[slot].x;
552	    	yorg = pCache->y + pCache->offsets[slot].y;
553	}
554     }
555
556
557    (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, xorg, yorg,
558						x, y, w, h);
559}
560
561
562
563	/****************\
564	|  Cache Expand  |
565	\****************/
566
567
568static void
569CacheExpandRectHelper (
570   ScrnInfoPtr pScrn,
571   int X, int Y, int Width, int Height,
572   int xorg, int yorg,
573   XAACacheInfoPtr pCache
574){
575    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
576    int x, phaseY, phaseX, skipleft, w, blit_w, blit_h;
577    int cacheWidth;
578
579    cacheWidth = (pCache->w * pScrn->bitsPerPixel) /
580	infoRec->CacheColorExpandDensity;
581
582    phaseY = (Y - yorg) % pCache->orig_h;
583    if(phaseY < 0) phaseY += pCache->orig_h;
584    phaseX = (X - xorg) % pCache->orig_w;
585    if(phaseX < 0) phaseX += pCache->orig_w;
586
587    while(1) {
588	w = Width; skipleft = phaseX; x = X;
589	blit_h = pCache->h - phaseY;
590	if(blit_h > Height) blit_h = Height;
591
592	while(1) {
593		blit_w = cacheWidth - skipleft;
594		if(blit_w > w) blit_w = w;
595		(*infoRec->SubsequentScreenToScreenColorExpandFill)(
596			pScrn, x, Y, blit_w, blit_h,
597			pCache->x, pCache->y + phaseY, skipleft);
598		w -= blit_w;
599		if(!w) break;
600		x += blit_w;
601		skipleft = (skipleft + blit_w) % pCache->orig_w;
602	}
603	Height -= blit_h;
604	if(!Height) break;
605	Y += blit_h;
606	phaseY = (phaseY + blit_h) % pCache->orig_h;
607    }
608}
609
610
611
612	/**************\
613	|  Cache Blit  |
614	\**************/
615
616
617static void
618CacheBltRectHelper (
619   ScrnInfoPtr pScrn,
620   int X, int Y, int Width, int Height,
621   int xorg, int yorg,
622   XAACacheInfoPtr pCache
623){
624     XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
625     int x, phaseY, phaseX, skipleft, w, blit_w, blit_h;
626
627     phaseY = (Y - yorg) % pCache->orig_h;
628     if(phaseY < 0) phaseY += pCache->orig_h;
629     phaseX = (X - xorg) % pCache->orig_w;
630     if(phaseX < 0) phaseX += pCache->orig_w;
631
632     while(1) {
633	w = Width; skipleft = phaseX; x = X;
634	blit_h = pCache->h - phaseY;
635	if(blit_h > Height) blit_h = Height;
636
637	while(1) {
638	    blit_w = pCache->w - skipleft;
639	    if(blit_w > w) blit_w = w;
640	    (*infoRec->SubsequentScreenToScreenCopy)(pScrn,
641			pCache->x + skipleft, pCache->y + phaseY,
642			x, Y, blit_w, blit_h);
643	    w -= blit_w;
644	    if(!w) break;
645	    x += blit_w;
646	    skipleft = (skipleft + blit_w) % pCache->orig_w;
647	}
648	Height -= blit_h;
649	if(!Height) break;
650	Y += blit_h;
651	phaseY = (phaseY + blit_h) % pCache->orig_h;
652     }
653}
654
655
656	/**********************\
657	|   Stippled Polygons  |
658	\**********************/
659
660
661void
662XAAFillPolygonStippled(
663    DrawablePtr	pDraw,
664    GCPtr	pGC,
665    int		shape,
666    int		mode,
667    int		count,
668    DDXPointPtr	ptsIn
669){
670    XAAInfoRecPtr   infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
671    XAAPixmapPtr    pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple);
672    int    	    origin, type, patx, paty, fg, bg;
673    int		    y, maxy, xorg, yorg;
674    DDXPointPtr	    topPoint;
675    XAACacheInfoPtr pCache = NULL;
676    RectFuncPtr	    RectFunc = NULL;
677    TrapFuncPtr	    TrapFunc = NULL;
678
679    if(!RegionNumRects(pGC->pCompositeClip))
680	return;
681
682    if (mode == CoordModePrevious) {
683	register DDXPointPtr ppt = ptsIn + 1;
684
685	for (origin = 1; origin < count; origin++, ppt++) {
686	    ppt->x += (ppt-1)->x;
687	    ppt->y += (ppt-1)->y;
688	}
689        mode = CoordModeOrigin;
690    }
691
692    if (RegionNumRects(pGC->pCompositeClip) != 1) {
693	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
694	return;
695    }
696
697
698    if(pGC->fillStyle == FillStippled) {
699    	type = (*infoRec->StippledFillChooser)(pGC);
700	fg = pGC->fgPixel;  bg = -1;
701    } else {
702    	type = (*infoRec->OpaqueStippledFillChooser)(pGC);
703	fg = pGC->fgPixel;  bg = pGC->bgPixel;
704    }
705
706
707    if(!type) {
708	(*XAAFallbackOps.FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn);
709	return;
710    }
711
712    if((type == DO_COLOR_EXPAND) || (type == DO_COLOR_8x8)) {
713	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
714	return;
715    }
716
717    origin = pDraw->x;
718
719    switch( XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents,
720		 origin, &topPoint, &y, &maxy, shape) ) {
721    case POLY_USE_MI:
722	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
723    case POLY_FULLY_CLIPPED:
724	return;
725    }
726
727    xorg = (pDraw->x + pGC->patOrg.x);
728    yorg = (pDraw->y + pGC->patOrg.y);
729
730
731    if((fg == bg) && (bg != -1) && infoRec->SetupForSolidFill) {
732
733	(*infoRec->SetupForSolidFill)(infoRec->pScrn, fg,
734				pGC->alu, pGC->planemask);
735
736	RectFunc = SolidRectHelper;
737        TrapFunc = infoRec->SubsequentSolidFillTrap ? SolidTrapHelper : NULL;
738    } else
739    switch(type) {
740	case DO_MONO_8x8:
741	    patx = pPriv->pattern0; paty = pPriv->pattern1;
742	    if(infoRec->Mono8x8PatternFillFlags &
743				HARDWARE_PATTERN_SCREEN_ORIGIN) {
744		xorg = (-xorg) & 0x07; yorg = (-yorg) & 0x07;
745		if(infoRec->Mono8x8PatternFillFlags &
746					HARDWARE_PATTERN_PROGRAMMED_BITS) {
747		    if(!(infoRec->Mono8x8PatternFillFlags &
748					HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
749		        XAARotateMonoPattern(&patx, &paty, xorg, yorg,
750				(infoRec->Mono8x8PatternFillFlags &
751				BIT_ORDER_IN_BYTE_MSBFIRST));
752		        xorg = patx; yorg = paty;
753		    }
754	        } else {
755		    XAACacheInfoPtr pCache = (*infoRec->CacheMono8x8Pattern)(
756					infoRec->pScrn, patx, paty);
757		    patx = pCache->x;  paty = pCache->y;
758		    if(!(infoRec->Mono8x8PatternFillFlags &
759				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
760			int slot = (yorg << 3) + xorg;
761			patx += pCache->offsets[slot].x;
762			paty += pCache->offsets[slot].y;
763			xorg = patx;  yorg = paty;
764		    }
765	        }
766		RectFunc = Mono8x8PatternRectHelper_ScreenOrigin;
767		if(infoRec->SubsequentMono8x8PatternFillTrap)
768		    TrapFunc = Mono8x8PatternTrapHelper_ScreenOrigin;
769	    } else {  /* !HARDWARE_PATTERN_SCREEN_ORIGIN */
770		if(!(infoRec->Mono8x8PatternFillFlags &
771				HARDWARE_PATTERN_PROGRAMMED_BITS)){
772		    pCache = (*infoRec->CacheMono8x8Pattern)(
773					infoRec->pScrn, patx, paty);
774		    patx = pCache->x;  paty = pCache->y;
775	    	} else {
776                    pCache = &(infoRec->ScratchCacheInfoRec);
777                    pCache->pat0 = patx;
778                    pCache->pat1 = paty;
779                }
780		RectFunc = Mono8x8PatternRectHelper;
781       	    }
782
783	    (*infoRec->SetupForMono8x8PatternFill)(infoRec->pScrn,
784				patx, paty, fg, bg, pGC->alu, pGC->planemask);
785	    break;
786	case DO_CACHE_EXPAND:
787	    pCache = (*infoRec->CacheMonoStipple)(infoRec->pScrn, pGC->stipple);
788
789	    (*infoRec->SetupForScreenToScreenColorExpandFill)(
790		infoRec->pScrn, fg, bg, pGC->alu, pGC->planemask);
791
792	    RectFunc = CacheExpandRectHelper;
793	    break;
794	case DO_CACHE_BLT:
795	    pCache = (*infoRec->CacheStipple)(infoRec->pScrn, pGC->stipple,
796							fg, bg);
797	    (*infoRec->SetupForScreenToScreenCopy)(infoRec->pScrn, 1, 1,
798		pGC->alu, pGC->planemask, pCache->trans_color);
799
800	    RectFunc = CacheBltRectHelper;
801	    break;
802	default:
803	    return;
804    }
805
806
807    XAAFillPolygonHelper(infoRec->pScrn, ptsIn, count, topPoint,
808		y, maxy, origin, RectFunc, TrapFunc, xorg, yorg, pCache);
809
810    SET_SYNC_FLAG(infoRec);
811}
812
813
814
815
816	/*******************\
817	|   Tiled Polygons  |
818	\*******************/
819
820
821void
822XAAFillPolygonTiled(
823    DrawablePtr	pDraw,
824    GCPtr	pGC,
825    int		shape,
826    int		mode,
827    int		count,
828    DDXPointPtr	ptsIn
829){
830    XAAInfoRecPtr   infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
831    XAAPixmapPtr    pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap);
832    int    	    origin, type, patx, paty;
833    int		    y, maxy, xorg, yorg;
834    DDXPointPtr	    topPoint;
835    XAACacheInfoPtr pCache = NULL;
836    RectFuncPtr	    RectFunc = NULL;
837    TrapFuncPtr	    TrapFunc = NULL;
838
839    if(!RegionNumRects(pGC->pCompositeClip))
840	return;
841
842    if (mode == CoordModePrevious) {
843	register DDXPointPtr ppt = ptsIn + 1;
844
845	for (origin = 1; origin < count; origin++, ppt++) {
846	    ppt->x += (ppt-1)->x;
847	    ppt->y += (ppt-1)->y;
848	}
849        mode = CoordModeOrigin;
850    }
851
852    if (RegionNumRects(pGC->pCompositeClip) != 1) {
853	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
854	return;
855    }
856
857
858    type = (*infoRec->TiledFillChooser)(pGC);
859
860    if(!type || (type == DO_IMAGE_WRITE)) {
861	(*XAAFallbackOps.FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn);
862	return;
863    }
864
865    if(type == DO_COLOR_8x8) {
866	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
867	return;
868    }
869
870    origin = pDraw->x;
871
872    switch( XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents,
873		 origin, &topPoint, &y, &maxy, shape) ) {
874    case POLY_USE_MI:
875	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
876    case POLY_FULLY_CLIPPED:
877	return;
878    }
879
880    xorg = (pDraw->x + pGC->patOrg.x);
881    yorg = (pDraw->y + pGC->patOrg.y);
882
883    switch(type) {
884	case DO_MONO_8x8:
885	    patx = pPriv->pattern0; paty = pPriv->pattern1;
886	    if(infoRec->Mono8x8PatternFillFlags &
887				HARDWARE_PATTERN_SCREEN_ORIGIN) {
888		xorg = (-xorg) & 0x07; yorg = (-yorg) & 0x07;
889		if(infoRec->Mono8x8PatternFillFlags &
890					HARDWARE_PATTERN_PROGRAMMED_BITS) {
891		    if(!(infoRec->Mono8x8PatternFillFlags &
892					HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
893		        XAARotateMonoPattern(&patx, &paty, xorg, yorg,
894				(infoRec->Mono8x8PatternFillFlags &
895				BIT_ORDER_IN_BYTE_MSBFIRST));
896		        xorg = patx; yorg = paty;
897		    }
898	        } else {
899		    XAACacheInfoPtr pCache = (*infoRec->CacheMono8x8Pattern)(
900					infoRec->pScrn, patx, paty);
901		    patx = pCache->x;  paty = pCache->y;
902		    if(!(infoRec->Mono8x8PatternFillFlags &
903				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
904			int slot = (yorg << 3) + xorg;
905			patx += pCache->offsets[slot].x;
906			paty += pCache->offsets[slot].y;
907			xorg = patx;  yorg = paty;
908		    }
909	        }
910		RectFunc = Mono8x8PatternRectHelper_ScreenOrigin;
911		if(infoRec->SubsequentMono8x8PatternFillTrap)
912		    TrapFunc = Mono8x8PatternTrapHelper_ScreenOrigin;
913	    } else {  /* !HARDWARE_PATTERN_SCREEN_ORIGIN */
914		if(!(infoRec->Mono8x8PatternFillFlags &
915				HARDWARE_PATTERN_PROGRAMMED_BITS)){
916		    pCache = (*infoRec->CacheMono8x8Pattern)(
917					infoRec->pScrn, patx, paty);
918		    patx = pCache->x;  paty = pCache->y;
919	    	}
920		else {
921		  pCache = &(infoRec->ScratchCacheInfoRec);
922		  pCache->pat0 = patx;
923		  pCache->pat1 = paty;
924		}
925		RectFunc = Mono8x8PatternRectHelper;
926       	    }
927
928	    (*infoRec->SetupForMono8x8PatternFill)(infoRec->pScrn,
929		 patx, paty, pPriv->fg, pPriv->bg, pGC->alu, pGC->planemask);
930	    break;
931	case DO_CACHE_BLT:
932            pCache = (*infoRec->CacheTile)(infoRec->pScrn, pGC->tile.pixmap);
933	    (*infoRec->SetupForScreenToScreenCopy)(infoRec->pScrn, 1, 1,
934		pGC->alu, pGC->planemask, -1);
935
936	    RectFunc = CacheBltRectHelper;
937	    break;
938	case DO_PIXMAP_COPY:
939	    pCache = &(infoRec->ScratchCacheInfoRec);
940	    pCache->x = pPriv->offscreenArea->box.x1;
941	    pCache->y = pPriv->offscreenArea->box.y1;
942	    pCache->w = pCache->orig_w =
943		pPriv->offscreenArea->box.x2 - pCache->x;
944	    pCache->h = pCache->orig_h =
945		pPriv->offscreenArea->box.y2 - pCache->y;
946
947	    (*infoRec->SetupForScreenToScreenCopy)(infoRec->pScrn, 1, 1,
948		pGC->alu, pGC->planemask, -1);
949
950	    RectFunc = CacheBltRectHelper;
951	    break;
952	default:
953	    return;
954    }
955
956    XAAFillPolygonHelper(infoRec->pScrn, ptsIn, count, topPoint,
957		y, maxy, origin, RectFunc, TrapFunc, xorg, yorg, pCache);
958
959    SET_SYNC_FLAG(infoRec);
960}
961
962
963