Home | History | Annotate | Line # | Download | only in xaa
      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 (at) 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 
    118 int
    119 XAAIsEasyPolygon(
    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 
    197 void
    198 XAAFillPolygonSolid(
    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 
    346 void
    347 XAAFillPolygonHelper(
    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 
    467 static void
    468 SolidTrapHelper(
    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 
    482 static void
    483 SolidRectHelper (
    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 
    499 static void
    500 Mono8x8PatternTrapHelper_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 
    514 static void
    515 Mono8x8PatternRectHelper_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 
    527 static void
    528 Mono8x8PatternRectHelper (
    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 
    568 static void
    569 CacheExpandRectHelper (
    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 
    617 static void
    618 CacheBltRectHelper (
    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 
    661 void
    662 XAAFillPolygonStippled(
    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 
    821 void
    822 XAAFillPolygonTiled(
    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