964 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			964 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $XFree86: xc/programs/Xserver/hw/xfree86/xaa/xaaFillPoly.c,v 1.15 2001/10/28 03:34:04 tsi Exp $ */
 | |
| 
 | |
| /*
 | |
|  * Copyright 1996  The XFree86 Project
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a 
 | |
|  * copy of this software and associated documentation files (the "Software"), 
 | |
|  * to deal in the Software without restriction, including without limitation 
 | |
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, 
 | |
|  * and/or sell copies of the Software, and to permit persons to whom the 
 | |
|  * Software is furnished to do so, subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  * 
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
 | |
|  * HARM HANEMAAYER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
 | |
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 
 | |
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 | |
|  * SOFTWARE.
 | |
|  * 
 | |
|  */
 | |
|  
 | |
| /*
 | |
|  * Written by Mark Vojkovich.  Loosly based on an original version
 | |
|  * written by Harm Hanemaayer (H.Hanemaayer@inter.nl.net) which
 | |
|  * only did solid rectangles and didn't have trapezoid support.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| 
 | |
| #ifdef HAVE_XORG_CONFIG_H
 | |
| #include <xorg-config.h>
 | |
| #endif
 | |
| 
 | |
| #include "misc.h"
 | |
| #include "xf86.h"
 | |
| #include "xf86_OSproc.h"
 | |
| 
 | |
| #include <X11/X.h>
 | |
| #include "scrnintstr.h"
 | |
| #include "pixmapstr.h"
 | |
| #include "xf86str.h"
 | |
| #include "mi.h"
 | |
| #include "micoord.h"
 | |
| 
 | |
| #include "xaa.h"
 | |
| #include "xaalocal.h"
 | |
| 
 | |
| #define POLY_USE_MI		0
 | |
| #define POLY_FULLY_CLIPPED	1
 | |
| #define POLY_IS_EASY		2
 | |
| 
 | |
| 
 | |
| #define Setup(c,x,vertex,dx,dy,e,sign,step,DX) {\
 | |
|     x = intToX(vertex); \
 | |
|     if ((dy = intToY(c) - y)) { \
 | |
|     	DX = dx = intToX(c) - x; \
 | |
| 	step = 0; \
 | |
|     	if (dx >= 0) \
 | |
|     	{ \
 | |
| 	    e = 0; \
 | |
| 	    sign = 1; \
 | |
| 	    if (dx >= dy) {\
 | |
| 	    	step = dx / dy; \
 | |
| 	    	dx %= dy; \
 | |
| 	    } \
 | |
|     	} \
 | |
|     	else \
 | |
|     	{ \
 | |
| 	    e = 1 - dy; \
 | |
| 	    sign = -1; \
 | |
| 	    dx = -dx; \
 | |
| 	    if (dx >= dy) { \
 | |
| 		step = - (dx / dy); \
 | |
| 		dx %= dy; \
 | |
| 	    } \
 | |
|     	} \
 | |
|     } \
 | |
|     x += origin; \
 | |
|     vertex = c; \
 | |
| }
 | |
| 
 | |
| #define Step(x,dx,dy,e,sign,step) {\
 | |
|     x += step; \
 | |
|     if ((e += dx) > 0) \
 | |
|     { \
 | |
| 	x += sign; \
 | |
| 	e -= dy; \
 | |
|     } \
 | |
| }
 | |
| 
 | |
| #define FixError(x, dx, dy, e, sign, step, h)	{	\
 | |
| 	   e += (h) * dx;				\
 | |
| 	   x += (h) * step;				\
 | |
| 	   if(e > 0) {					\
 | |
| 		x += e * sign/dy;			\
 | |
| 		e %= dy;				\
 | |
| 	   	if(e) {					\
 | |
| 		   x += sign;				\
 | |
| 		   e -= dy;				\
 | |
| 		}					\
 | |
| 	   } 	 					\
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|    XAAIsEasyPoly -
 | |
| 
 | |
|    Checks CoordModeOrigin one rect polygons to see if we need
 | |
|    to use Mi.
 | |
|    Returns: POLY_USE_MI, POLY_FULLY_CLIPPED or POLY_IS_EASY
 | |
| 	as well as the pointer to the "top" point and the y
 | |
| 	extents.
 | |
| */
 | |
| 
 | |
| int
 | |
| XAAIsEasyPolygon(
 | |
|    DDXPointPtr ptsIn,
 | |
|    int count, 
 | |
|    BoxPtr extents,
 | |
|    int origin,		
 | |
|    DDXPointPtr *topPoint, 	/* return */
 | |
|    int *topY, int *bottomY,	/* return */
 | |
|    int shape
 | |
| ){
 | |
|     int c = 0, vertex1, vertex2;
 | |
| 
 | |
|     *topY = 32767;
 | |
|     *bottomY = 0;
 | |
| 
 | |
|     origin -= (origin & 0x8000) << 1;
 | |
|     vertex1 = *((int *) &extents->x1) - origin;
 | |
|     vertex2 = *((int *) &extents->x2) - origin /* - 0x00010001 */;
 | |
|                      /* I think this was an error in cfb ^ */
 | |
| 
 | |
|     if (shape == Convex) {
 | |
|     	while (count--) {
 | |
| 	    c = *((int*)ptsIn);
 | |
| 	    if (((c - vertex1) | (vertex2 - c)) & 0x80008000)
 | |
| 		return POLY_USE_MI;
 | |
| 
 | |
| 	    c = intToY(c);
 | |
| 	    if (c < *topY) {
 | |
| 	    	*topY = c;
 | |
| 	    	*topPoint = ptsIn;
 | |
| 	    }
 | |
| 	    ptsIn++;
 | |
| 	    if (c > *bottomY) *bottomY = c;
 | |
|     	}
 | |
|     } else {
 | |
| 	int yFlip = 0;
 | |
| 	int dx2, dx1, x1, x2;
 | |
| 
 | |
| 	x2 = x1 = -1;
 | |
| 	dx2 = dx1 = 1;
 | |
| 
 | |
|     	while (count--) {
 | |
| 	    c = *((int*)ptsIn);
 | |
| 	    if (((c - vertex1) | (vertex2 - c)) & 0x80008000)
 | |
| 		return POLY_USE_MI;
 | |
| 	    c = intToY(c);
 | |
| 	    if (c < *topY) {
 | |
| 	    	*topY = c;
 | |
| 	    	*topPoint = ptsIn;
 | |
| 	    }
 | |
| 	    ptsIn++;
 | |
| 	    if (c > *bottomY) *bottomY = c;
 | |
| 	    if (c == x1)
 | |
| 		continue;
 | |
| 	    if (dx1 > 0) {
 | |
| 		if (x2 < 0) x2 = c;
 | |
| 		else	    dx2 = dx1 = (c - x1) >> 31;
 | |
| 	    } else if ((c - x1) >> 31 != dx1) {
 | |
| 		dx1 = ~dx1;
 | |
| 		yFlip++;
 | |
| 	    }
 | |
| 	    x1 = c;
 | |
|        	}
 | |
| 	x1 = (x2 - c) >> 31;
 | |
| 	if (x1 != dx1) yFlip++;
 | |
| 	if (x1 != dx2) yFlip++;
 | |
| 	if (yFlip != 2) {
 | |
| 	   if(*topY == *bottomY)
 | |
| 		return POLY_FULLY_CLIPPED;
 | |
| 	   else
 | |
| 		return POLY_USE_MI;
 | |
| 	}
 | |
|     }
 | |
|     if (*topY == *bottomY)
 | |
| 	return POLY_FULLY_CLIPPED;
 | |
| 
 | |
|     return POLY_IS_EASY;
 | |
| }
 | |
| 
 | |
| void
 | |
| XAAFillPolygonSolid(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		shape,
 | |
|     int		mode,
 | |
|     int		count,
 | |
|     DDXPointPtr	ptsIn 
 | |
| ){
 | |
|     XAAInfoRecPtr   infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
 | |
|     int    	    origin, vertex1, vertex2;
 | |
|     int		    *vertex1p, *vertex2p, *endp;
 | |
|     int		    x1 = 0, x2 = 0;
 | |
|     int 	    dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
 | |
|     int		    DX1 = 0, DX2 = 0, e1 = 0, e2 = 0;
 | |
|     int		    step1 = 0, step2 = 0, sign1 = 0, sign2 = 0;
 | |
|     int		    c, y, maxy, h, yoffset;
 | |
|     DDXPointPtr	    topPoint;
 | |
| 
 | |
|     if(!REGION_NUM_RECTS(pGC->pCompositeClip))
 | |
| 	return;
 | |
| 
 | |
|     if (mode == CoordModePrevious) {
 | |
| 	register DDXPointPtr ppt = ptsIn + 1;
 | |
| 
 | |
| 	for (origin = 1; origin < count; origin++, ppt++) {
 | |
| 	    ppt->x += (ppt-1)->x;
 | |
| 	    ppt->y += (ppt-1)->y;
 | |
| 	}
 | |
|         mode = CoordModeOrigin;
 | |
|     }
 | |
|     
 | |
|     if (REGION_NUM_RECTS(pGC->pCompositeClip) != 1) {
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     origin = coordToInt(pDraw->x, pDraw->y);
 | |
| 
 | |
|     switch( XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents, 
 | |
| 		origin, &topPoint, &y, &maxy, shape) ) {
 | |
|     case POLY_USE_MI: 
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
|     case POLY_FULLY_CLIPPED: 
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     endp = (int*)ptsIn + count;
 | |
|     vertex2p = vertex1p = (int *)topPoint;
 | |
|     origin = pDraw->x;
 | |
|     yoffset = pDraw->y;
 | |
|     vertex2 = vertex1 = *vertex2p++;
 | |
|     if (vertex2p == endp)
 | |
| 	vertex2p = (int *) ptsIn;
 | |
| 
 | |
|     (*infoRec->SetupForSolidFill)(infoRec->pScrn, pGC->fgPixel, pGC->alu,
 | |
|         pGC->planemask);
 | |
| 
 | |
|     while(1) {
 | |
| 	if (y == intToY(vertex1)) {
 | |
| 	    do {
 | |
| 	    	if (vertex1p == (int *) ptsIn)
 | |
| 		    vertex1p = endp;
 | |
| 	    	c = *--vertex1p;
 | |
| 	    	Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1,DX1)
 | |
| 	    } while (y >= intToY(vertex1));
 | |
| 	    h = dy1;
 | |
| 	} else {
 | |
| 	    Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    h = intToY(vertex1) - y;
 | |
| 	}
 | |
| 	if (y == intToY(vertex2)) {
 | |
| 	    do {
 | |
| 	    	c = *vertex2p++;
 | |
| 	    	if (vertex2p == endp)
 | |
| 		    vertex2p = (int *) ptsIn;
 | |
| 	    	Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2,DX2)
 | |
| 	    } while (y >= intToY(vertex2));
 | |
| 	    if (dy2 < h)
 | |
| 		h = dy2;
 | |
| 	} else {
 | |
| 	    Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 	    if ((c = (intToY(vertex2) - y)) < h)
 | |
| 		h = c;
 | |
| 	}
 | |
| 
 | |
| 	/* fill spans for this segment */
 | |
|         if(DX1 | DX2) {
 | |
|       	  if(infoRec->SubsequentSolidFillTrap && (h > 6)) {
 | |
| 	     if(x1 == x2) {
 | |
| 		while(x1 == x2) {
 | |
| 	     	   y++;
 | |
| 	    	   if (!--h) break;
 | |
| 	    	   Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    	   Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 		}
 | |
| 		if(y == maxy) break;
 | |
|     		if(!h) continue;
 | |
| 	     }
 | |
| 
 | |
|              if(x1 < x2)
 | |
|  	     	(*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn,
 | |
| 					y + yoffset, h,
 | |
| 					x1, DX1, dy1, e1, 
 | |
| 					x2 - 1, DX2, dy2, e2);
 | |
| 	     else
 | |
|  	     	(*infoRec->SubsequentSolidFillTrap)(infoRec->pScrn,
 | |
| 					y + yoffset, h,
 | |
| 					x2, DX2, dy2, e2, 
 | |
| 					x1 - 1, DX1, dy1, e1);
 | |
| 	     y += h;	
 | |
|              if(--h) {
 | |
| 	     	FixError(x1,dx1,dy1,e1,sign1,step1,h);
 | |
| 	     	FixError(x2,dx2,dy2,e2,sign2,step2,h);
 | |
| 		h = 0;
 | |
| 	     }  	
 | |
| 	  } else {
 | |
| 	     while(1) {
 | |
| 	    	if (x2 > x1)
 | |
| 	            (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
 | |
| 	            		x1, y + yoffset, x2 - x1, 1);
 | |
| 	        else if (x1 > x2)
 | |
| 	            (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
 | |
| 	                    x2, y + yoffset, x1 - x2, 1);
 | |
| 	     	y++;
 | |
| 	    	if (!--h) break;
 | |
| 	    	Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    	Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 	     }
 | |
| 	  }
 | |
| 	} else {
 | |
| 	    if (x2 > x1)
 | |
| 	        (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
 | |
| 	            x1, y + yoffset, x2 - x1, h);
 | |
| 	    else if (x1 > x2)
 | |
| 	        (*infoRec->SubsequentSolidFillRect)(infoRec->pScrn,
 | |
| 	                x2, y + yoffset, x1 - x2, h);
 | |
| 
 | |
| 	    y += h;
 | |
| 	    h = 0;
 | |
|         } 
 | |
| 	if (y == maxy) break;
 | |
|     }
 | |
|     SET_SYNC_FLAG(infoRec);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| void
 | |
| XAAFillPolygonHelper(
 | |
|     ScrnInfoPtr pScrn,
 | |
|     DDXPointPtr	ptsIn,
 | |
|     int 	count,
 | |
|     DDXPointPtr topPoint,
 | |
|     int 	y,
 | |
|     int		maxy,
 | |
|     int		origin,
 | |
|     RectFuncPtr RectFunc,
 | |
|     TrapFuncPtr TrapFunc,
 | |
|     int 	xorg,
 | |
|     int		yorg,
 | |
|     XAACacheInfoPtr pCache
 | |
| ){
 | |
|     int		    *vertex1p, *vertex2p, *endp;
 | |
|     int		    vertex1, vertex2;
 | |
|     int		    x1 = 0, x2 = 0;
 | |
|     int		    dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
 | |
|     int		    DX1 = 0, DX2 = 0, e1 = 0, e2 = 0;
 | |
|     int		    step1 = 0, step2 = 0, sign1 = 0, sign2 = 0;
 | |
|     int		    c, h, yoffset;
 | |
| 
 | |
| 
 | |
|     endp = (int*)ptsIn + count;
 | |
|     vertex2p = vertex1p = (int *)topPoint;
 | |
|     yoffset = intToY(origin);
 | |
|     origin = intToX(origin);
 | |
|     vertex2 = vertex1 = *vertex2p++;
 | |
|     if (vertex2p == endp)
 | |
| 	vertex2p = (int *)ptsIn;
 | |
| 
 | |
|     while(1) {
 | |
| 	if (y == intToY(vertex1)) {
 | |
| 	    do {
 | |
| 	    	if (vertex1p == (int *) ptsIn)
 | |
| 		    vertex1p = endp;
 | |
| 	    	c = *--vertex1p;
 | |
| 	    	Setup (c,x1,vertex1,dx1,dy1,e1,sign1,step1,DX1)
 | |
| 	    } while (y >= intToY(vertex1));
 | |
| 	    h = dy1;
 | |
| 	} else {
 | |
| 	    Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    h = intToY(vertex1) - y;
 | |
| 	}
 | |
| 	if (y == intToY(vertex2)) {
 | |
| 	    do {
 | |
| 	    	c = *vertex2p++;
 | |
| 	    	if (vertex2p == endp)
 | |
| 		    vertex2p = (int *) ptsIn;
 | |
| 	    	Setup (c,x2,vertex2,dx2,dy2,e2,sign2,step2,DX2)
 | |
| 	    } while (y >= intToY(vertex2));
 | |
| 	    if (dy2 < h)
 | |
| 		h = dy2;
 | |
| 	} else {
 | |
| 	    Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 	    if ((c = (intToY(vertex2) - y)) < h)
 | |
| 		h = c;
 | |
| 	}
 | |
| 
 | |
| 	/* fill spans for this segment */
 | |
|         if(DX1 | DX2) {
 | |
|       	  if(TrapFunc && (h > 6)) {
 | |
| 	     if(x1 == x2) {
 | |
| 		while(x1 == x2) {
 | |
| 	     	   y++;
 | |
| 	    	   if (!--h) break;
 | |
| 	    	   Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    	   Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 		}
 | |
| 		if(y == maxy) break;
 | |
|     		if(!h) continue;
 | |
| 	     }
 | |
| 
 | |
|              if(x1 < x2)
 | |
|  	     	(*TrapFunc)(pScrn, y + yoffset, h,
 | |
| 				x1, DX1, dy1, e1, 
 | |
| 				x2 - 1, DX2, dy2, e2, xorg, yorg, pCache);
 | |
| 	     else
 | |
|  	     	(*TrapFunc)(pScrn, y + yoffset, h,
 | |
| 				x2, DX2, dy2, e2, 
 | |
| 				x1 - 1, DX1, dy1, e1, xorg, yorg, pCache);
 | |
| 	     y += h;	
 | |
|              if(--h) {
 | |
| 	     	FixError(x1,dx1,dy1,e1,sign1,step1,h);
 | |
| 	     	FixError(x2,dx2,dy2,e2,sign2,step2,h);
 | |
| 		h = 0;
 | |
| 	     }  	
 | |
| 	  } else {
 | |
| 	     while(1) {
 | |
| 	    	if (x2 > x1)
 | |
| 	            (*RectFunc)(pScrn,
 | |
| 	            	x1, y + yoffset, x2 - x1, 1, xorg, yorg, pCache);
 | |
| 	        else if (x1 > x2)
 | |
| 	            (*RectFunc)(pScrn,
 | |
| 	                    x2, y + yoffset, x1 - x2, 1, xorg, yorg, pCache);
 | |
| 	     	y++;
 | |
| 	    	if (!--h) break;
 | |
| 	    	Step(x1,dx1,dy1,e1,sign1,step1)
 | |
| 	    	Step(x2,dx2,dy2,e2,sign2,step2)
 | |
| 	     }
 | |
| 	  }
 | |
| 	} else {
 | |
| 	    if (x2 > x1)
 | |
| 	        (*RectFunc)(pScrn,
 | |
| 	            x1, y + yoffset, x2 - x1, h, xorg, yorg, pCache);
 | |
| 	    else if (x1 > x2)
 | |
| 	        (*RectFunc)(pScrn,
 | |
| 	                x2, y + yoffset, x1 - x2, h, xorg, yorg, pCache);
 | |
| 
 | |
| 	    y += h;
 | |
| 	    h = 0;
 | |
|         } 
 | |
| 	if (y == maxy) break;
 | |
|     }
 | |
| }
 | |
| 
 | |
|         /*****************\
 | |
| 	|  Solid Helpers  |
 | |
| 	\*****************/
 | |
| 
 | |
| static void
 | |
| SolidTrapHelper(
 | |
|    ScrnInfoPtr pScrn,
 | |
|    int y, int h,
 | |
|    int x1, int dx1, int dy1, int e1,
 | |
|    int x2, int dx2, int dy2, int e2,
 | |
|    int xorg, int yorg,
 | |
|    XAACacheInfoPtr pCache
 | |
| ){
 | |
|     XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
 | |
| 
 | |
|     (*infoRec->SubsequentSolidFillTrap) (pScrn, 
 | |
| 		y, h, x1, dx1, dy1, e1, x2, dx2, dy2, e2);
 | |
| }
 | |
| 
 | |
| static void
 | |
| SolidRectHelper (
 | |
|    ScrnInfoPtr pScrn,
 | |
|    int x, int y, int w, int h,
 | |
|    int xorg, int yorg,   
 | |
|    XAACacheInfoPtr pCache
 | |
| ){
 | |
|     XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
 | |
| 
 | |
|     (*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
 | |
| }
 | |
| 
 | |
| 
 | |
| 	/*********************\
 | |
| 	|  Mono 8x8 Patterns  |
 | |
| 	\*********************/
 | |
| 
 | |
| static void
 | |
| Mono8x8PatternTrapHelper_ScreenOrigin(
 | |
|    ScrnInfoPtr pScrn,
 | |
|    int y, int h,
 | |
|    int x1, int dx1, int dy1, int e1,
 | |
|    int x2, int dx2, int dy2, int e2,
 | |
|    int xorg, int yorg,
 | |
|    XAACacheInfoPtr pCache
 | |
| ){
 | |
|     XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
 | |
| 
 | |
|     (*infoRec->SubsequentMono8x8PatternFillTrap) (pScrn, xorg, yorg,
 | |
| 		y, h, x1, dx1, dy1, e1, x2, dx2, dy2, e2);
 | |
| }
 | |
| 
 | |
| static void
 | |
| Mono8x8PatternRectHelper_ScreenOrigin (
 | |
|    ScrnInfoPtr pScrn,
 | |
|    int x, int y, int w, int h,
 | |
|    int xorg, int yorg,   
 | |
|    XAACacheInfoPtr pCache
 | |
| ){
 | |
|     XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
 | |
| 
 | |
|     (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, xorg, yorg,
 | |
| 						x, y, w, h);
 | |
| }
 | |
| 
 | |
| static void
 | |
| Mono8x8PatternRectHelper (
 | |
|    ScrnInfoPtr pScrn,
 | |
|    int x, int y, int w, int h,
 | |
|    int xorg, int yorg,   
 | |
|    XAACacheInfoPtr pCache
 | |
| ){
 | |
|     XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
 | |
| 
 | |
|     xorg = (x - xorg) & 0x07;
 | |
|     yorg = (y - yorg) & 0x07;
 | |
| 
 | |
|     if(!(infoRec->Mono8x8PatternFillFlags & 		
 | |
| 				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
 | |
| 	if(infoRec->Mono8x8PatternFillFlags & 
 | |
| 				HARDWARE_PATTERN_PROGRAMMED_BITS) {
 | |
| 		int patx = pCache->pat0; 
 | |
| 		int paty = pCache->pat1;
 | |
| 		XAARotateMonoPattern(&patx, &paty, xorg, yorg,
 | |
| 				(infoRec->Mono8x8PatternFillFlags & 		
 | |
| 				BIT_ORDER_IN_BYTE_MSBFIRST));
 | |
| 		xorg = patx; yorg = paty;
 | |
| 	} else {
 | |
| 		int slot = (yorg << 3) + xorg;
 | |
| 	    	xorg = pCache->x + pCache->offsets[slot].x;
 | |
| 	    	yorg = pCache->y + pCache->offsets[slot].y;
 | |
| 	}
 | |
|      }
 | |
| 
 | |
| 
 | |
|     (*infoRec->SubsequentMono8x8PatternFillRect) (pScrn, xorg, yorg,
 | |
| 						x, y, w, h);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 	/****************\
 | |
| 	|  Cache Expand  |
 | |
| 	\****************/
 | |
| 
 | |
| 
 | |
| static void
 | |
| CacheExpandRectHelper (
 | |
|    ScrnInfoPtr pScrn,
 | |
|    int X, int Y, int Width, int Height,
 | |
|    int xorg, int yorg,   
 | |
|    XAACacheInfoPtr pCache
 | |
| ){
 | |
|     XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
 | |
|     int x, phaseY, phaseX, skipleft, w, blit_w, blit_h;
 | |
|     int cacheWidth;
 | |
| 
 | |
|     cacheWidth = (pCache->w * pScrn->bitsPerPixel) / 
 | |
| 	infoRec->CacheColorExpandDensity;
 | |
| 
 | |
|     phaseY = (Y - yorg) % pCache->orig_h;
 | |
|     if(phaseY < 0) phaseY += pCache->orig_h;
 | |
|     phaseX = (X - xorg) % pCache->orig_w;
 | |
|     if(phaseX < 0) phaseX += pCache->orig_w;
 | |
| 	
 | |
|     while(1) {
 | |
| 	w = Width; skipleft = phaseX; x = X;
 | |
| 	blit_h = pCache->h - phaseY;
 | |
| 	if(blit_h > Height) blit_h = Height;
 | |
| 	
 | |
| 	while(1) {
 | |
| 		blit_w = cacheWidth - skipleft;
 | |
| 		if(blit_w > w) blit_w = w;
 | |
| 		(*infoRec->SubsequentScreenToScreenColorExpandFill)(
 | |
| 			pScrn, x, Y, blit_w, blit_h,
 | |
| 			pCache->x, pCache->y + phaseY, skipleft);
 | |
| 		w -= blit_w;
 | |
| 		if(!w) break;
 | |
| 		x += blit_w;
 | |
| 		skipleft = (skipleft + blit_w) % pCache->orig_w;
 | |
| 	}
 | |
| 	Height -= blit_h;
 | |
| 	if(!Height) break;
 | |
| 	Y += blit_h;
 | |
| 	phaseY = (phaseY + blit_h) % pCache->orig_h;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 	/**************\
 | |
| 	|  Cache Blit  |
 | |
| 	\**************/
 | |
| 
 | |
| 
 | |
| static void
 | |
| CacheBltRectHelper (
 | |
|    ScrnInfoPtr pScrn,
 | |
|    int X, int Y, int Width, int Height,
 | |
|    int xorg, int yorg,   
 | |
|    XAACacheInfoPtr pCache
 | |
| ){
 | |
|      XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
 | |
|      int x, phaseY, phaseX, skipleft, w, blit_w, blit_h;
 | |
| 
 | |
|      phaseY = (Y - yorg) % pCache->orig_h;
 | |
|      if(phaseY < 0) phaseY += pCache->orig_h;
 | |
|      phaseX = (X - xorg) % pCache->orig_w;
 | |
|      if(phaseX < 0) phaseX += pCache->orig_w;
 | |
| 
 | |
|      while(1) {
 | |
| 	w = Width; skipleft = phaseX; x = X;
 | |
| 	blit_h = pCache->h - phaseY;
 | |
| 	if(blit_h > Height) blit_h = Height;
 | |
| 	
 | |
| 	while(1) {
 | |
| 	    blit_w = pCache->w - skipleft;
 | |
| 	    if(blit_w > w) blit_w = w;
 | |
| 	    (*infoRec->SubsequentScreenToScreenCopy)(pScrn,
 | |
| 			pCache->x + skipleft, pCache->y + phaseY,
 | |
| 			x, Y, blit_w, blit_h);
 | |
| 	    w -= blit_w;
 | |
| 	    if(!w) break;
 | |
| 	    x += blit_w;
 | |
| 	    skipleft = (skipleft + blit_w) % pCache->orig_w;
 | |
| 	}
 | |
| 	Height -= blit_h;
 | |
| 	if(!Height) break;
 | |
| 	Y += blit_h;
 | |
| 	phaseY = (phaseY + blit_h) % pCache->orig_h;
 | |
|      }	
 | |
| }
 | |
| 
 | |
| 
 | |
| 	/**********************\
 | |
| 	|   Stippled Polygons  |
 | |
| 	\**********************/
 | |
| 
 | |
| 
 | |
| void
 | |
| XAAFillPolygonStippled(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		shape,
 | |
|     int		mode,
 | |
|     int		count,
 | |
|     DDXPointPtr	ptsIn 
 | |
| ){
 | |
|     XAAInfoRecPtr   infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
 | |
|     XAAPixmapPtr    pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple);
 | |
|     int    	    origin, type, patx, paty, fg, bg;
 | |
|     int		    y, maxy, xorg, yorg;
 | |
|     DDXPointPtr	    topPoint;
 | |
|     XAACacheInfoPtr pCache = NULL;
 | |
|     RectFuncPtr	    RectFunc = NULL;
 | |
|     TrapFuncPtr	    TrapFunc = NULL;
 | |
| 
 | |
|     if(!REGION_NUM_RECTS(pGC->pCompositeClip))
 | |
| 	return;
 | |
| 
 | |
|     if (mode == CoordModePrevious) {
 | |
| 	register DDXPointPtr ppt = ptsIn + 1;
 | |
| 
 | |
| 	for (origin = 1; origin < count; origin++, ppt++) {
 | |
| 	    ppt->x += (ppt-1)->x;
 | |
| 	    ppt->y += (ppt-1)->y;
 | |
| 	}
 | |
|         mode = CoordModeOrigin;
 | |
|     }
 | |
|     
 | |
|     if (REGION_NUM_RECTS(pGC->pCompositeClip) != 1) {
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if(pGC->fillStyle == FillStippled) {
 | |
|     	type = (*infoRec->StippledFillChooser)(pGC);
 | |
| 	fg = pGC->fgPixel;  bg = -1;
 | |
|     } else {
 | |
|     	type = (*infoRec->OpaqueStippledFillChooser)(pGC);
 | |
| 	fg = pGC->fgPixel;  bg = pGC->bgPixel;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     if(!type) {
 | |
| 	(*XAAFallbackOps.FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
| 	
 | |
|     if((type == DO_COLOR_EXPAND) || (type == DO_COLOR_8x8)) {
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     origin = *((int *)&pDraw->x);
 | |
| 
 | |
|     switch( XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents,
 | |
| 		 origin, &topPoint, &y, &maxy, shape) ) {
 | |
|     case POLY_USE_MI: 
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
|     case POLY_FULLY_CLIPPED: 
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     xorg = (pDraw->x + pGC->patOrg.x);
 | |
|     yorg = (pDraw->y + pGC->patOrg.y);
 | |
| 
 | |
| 
 | |
|     if((fg == bg) && (bg != -1) && infoRec->SetupForSolidFill) {
 | |
| 
 | |
| 	(*infoRec->SetupForSolidFill)(infoRec->pScrn, fg,
 | |
| 				pGC->alu, pGC->planemask);
 | |
| 
 | |
| 	RectFunc = SolidRectHelper;
 | |
|         TrapFunc = infoRec->SubsequentSolidFillTrap ? SolidTrapHelper : NULL;
 | |
|     } else
 | |
|     switch(type) {
 | |
| 	case DO_MONO_8x8:
 | |
| 	    patx = pPriv->pattern0; paty = pPriv->pattern1;
 | |
| 	    if(infoRec->Mono8x8PatternFillFlags & 
 | |
| 				HARDWARE_PATTERN_SCREEN_ORIGIN) {
 | |
| 		xorg = (-xorg) & 0x07; yorg = (-yorg) & 0x07;
 | |
| 		if(infoRec->Mono8x8PatternFillFlags & 
 | |
| 					HARDWARE_PATTERN_PROGRAMMED_BITS) {
 | |
| 		    if(!(infoRec->Mono8x8PatternFillFlags & 		
 | |
| 					HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
 | |
| 		        XAARotateMonoPattern(&patx, &paty, xorg, yorg,
 | |
| 				(infoRec->Mono8x8PatternFillFlags & 		
 | |
| 				BIT_ORDER_IN_BYTE_MSBFIRST));
 | |
| 		        xorg = patx; yorg = paty;
 | |
| 		    }
 | |
| 	        } else {
 | |
| 		    XAACacheInfoPtr pCache = (*infoRec->CacheMono8x8Pattern)(
 | |
| 					infoRec->pScrn, patx, paty);
 | |
| 		    patx = pCache->x;  paty = pCache->y;
 | |
| 		    if(!(infoRec->Mono8x8PatternFillFlags & 
 | |
| 				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
 | |
| 			int slot = (yorg << 3) + xorg;
 | |
| 			patx += pCache->offsets[slot].x;
 | |
| 			paty += pCache->offsets[slot].y;
 | |
| 			xorg = patx;  yorg = paty;
 | |
| 		    }
 | |
| 	        }	
 | |
| 		RectFunc = Mono8x8PatternRectHelper_ScreenOrigin;
 | |
| 		if(infoRec->SubsequentMono8x8PatternFillTrap)
 | |
| 		    TrapFunc = Mono8x8PatternTrapHelper_ScreenOrigin;
 | |
| 	    } else {  /* !HARDWARE_PATTERN_SCREEN_ORIGIN */
 | |
| 		if(!(infoRec->Mono8x8PatternFillFlags & 
 | |
| 				HARDWARE_PATTERN_PROGRAMMED_BITS)){
 | |
| 		    pCache = (*infoRec->CacheMono8x8Pattern)(
 | |
| 					infoRec->pScrn, patx, paty);
 | |
| 		    patx = pCache->x;  paty = pCache->y;
 | |
| 	    	} else {
 | |
|                     pCache = &(infoRec->ScratchCacheInfoRec);
 | |
|                     pCache->pat0 = patx;
 | |
|                     pCache->pat1 = paty;
 | |
|                 }
 | |
| 		RectFunc = Mono8x8PatternRectHelper;
 | |
|        	    }
 | |
| 
 | |
| 	    (*infoRec->SetupForMono8x8PatternFill)(infoRec->pScrn, 
 | |
| 				patx, paty, fg, bg, pGC->alu, pGC->planemask);
 | |
| 	    break;
 | |
| 	case DO_CACHE_EXPAND:
 | |
| 	    pCache = (*infoRec->CacheMonoStipple)(infoRec->pScrn, pGC->stipple);
 | |
| 
 | |
| 	    (*infoRec->SetupForScreenToScreenColorExpandFill)(
 | |
| 		infoRec->pScrn, fg, bg, pGC->alu, pGC->planemask);
 | |
| 
 | |
| 	    RectFunc = CacheExpandRectHelper;
 | |
| 	    break;
 | |
| 	case DO_CACHE_BLT:
 | |
| 	    pCache = (*infoRec->CacheStipple)(infoRec->pScrn, pGC->stipple, 
 | |
| 							fg, bg);
 | |
| 	    (*infoRec->SetupForScreenToScreenCopy)(infoRec->pScrn, 1, 1, 
 | |
| 		pGC->alu, pGC->planemask, pCache->trans_color);
 | |
| 
 | |
| 	    RectFunc = CacheBltRectHelper;
 | |
| 	    break;
 | |
| 	default:
 | |
| 	    return;
 | |
|     }
 | |
|         
 | |
| 
 | |
|     XAAFillPolygonHelper(infoRec->pScrn, ptsIn, count, topPoint, 
 | |
| 		y, maxy, origin, RectFunc, TrapFunc, xorg, yorg, pCache);
 | |
| 
 | |
|     SET_SYNC_FLAG(infoRec);	
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 	/*******************\
 | |
| 	|   Tiled Polygons  |
 | |
| 	\*******************/
 | |
| 
 | |
| 
 | |
| void
 | |
| XAAFillPolygonTiled(
 | |
|     DrawablePtr	pDraw,
 | |
|     GCPtr	pGC,
 | |
|     int		shape,
 | |
|     int		mode,
 | |
|     int		count,
 | |
|     DDXPointPtr	ptsIn 
 | |
| ){
 | |
|     XAAInfoRecPtr   infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
 | |
|     XAAPixmapPtr    pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap);
 | |
|     int    	    origin, type, patx, paty;
 | |
|     int		    y, maxy, xorg, yorg;
 | |
|     DDXPointPtr	    topPoint;
 | |
|     XAACacheInfoPtr pCache = NULL;
 | |
|     RectFuncPtr	    RectFunc = NULL;
 | |
|     TrapFuncPtr	    TrapFunc = NULL;
 | |
| 
 | |
|     if(!REGION_NUM_RECTS(pGC->pCompositeClip))
 | |
| 	return;
 | |
| 
 | |
|     if (mode == CoordModePrevious) {
 | |
| 	register DDXPointPtr ppt = ptsIn + 1;
 | |
| 
 | |
| 	for (origin = 1; origin < count; origin++, ppt++) {
 | |
| 	    ppt->x += (ppt-1)->x;
 | |
| 	    ppt->y += (ppt-1)->y;
 | |
| 	}
 | |
|         mode = CoordModeOrigin;
 | |
|     }
 | |
|     
 | |
|     if (REGION_NUM_RECTS(pGC->pCompositeClip) != 1) {
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     type = (*infoRec->TiledFillChooser)(pGC);
 | |
| 
 | |
|     if(!type || (type == DO_IMAGE_WRITE)) {
 | |
| 	(*XAAFallbackOps.FillPolygon)(pDraw, pGC, shape, mode, count, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
| 	
 | |
|     if(type == DO_COLOR_8x8) {
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     origin = *((int *)&pDraw->x);
 | |
| 
 | |
|     switch( XAAIsEasyPolygon(ptsIn, count, &pGC->pCompositeClip->extents,
 | |
| 		 origin, &topPoint, &y, &maxy, shape) ) {
 | |
|     case POLY_USE_MI: 
 | |
| 	miFillPolygon (pDraw, pGC, shape, mode, count, ptsIn);
 | |
|     case POLY_FULLY_CLIPPED: 
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     xorg = (pDraw->x + pGC->patOrg.x);
 | |
|     yorg = (pDraw->y + pGC->patOrg.y);
 | |
| 
 | |
|     switch(type) {
 | |
| 	case DO_MONO_8x8:
 | |
| 	    patx = pPriv->pattern0; paty = pPriv->pattern1;
 | |
| 	    if(infoRec->Mono8x8PatternFillFlags & 
 | |
| 				HARDWARE_PATTERN_SCREEN_ORIGIN) {
 | |
| 		xorg = (-xorg) & 0x07; yorg = (-yorg) & 0x07;
 | |
| 		if(infoRec->Mono8x8PatternFillFlags & 
 | |
| 					HARDWARE_PATTERN_PROGRAMMED_BITS) {
 | |
| 		    if(!(infoRec->Mono8x8PatternFillFlags & 		
 | |
| 					HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
 | |
| 		        XAARotateMonoPattern(&patx, &paty, xorg, yorg,
 | |
| 				(infoRec->Mono8x8PatternFillFlags & 		
 | |
| 				BIT_ORDER_IN_BYTE_MSBFIRST));
 | |
| 		        xorg = patx; yorg = paty;
 | |
| 		    }
 | |
| 	        } else {
 | |
| 		    XAACacheInfoPtr pCache = (*infoRec->CacheMono8x8Pattern)(
 | |
| 					infoRec->pScrn, patx, paty);
 | |
| 		    patx = pCache->x;  paty = pCache->y;
 | |
| 		    if(!(infoRec->Mono8x8PatternFillFlags & 
 | |
| 				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
 | |
| 			int slot = (yorg << 3) + xorg;
 | |
| 			patx += pCache->offsets[slot].x;
 | |
| 			paty += pCache->offsets[slot].y;
 | |
| 			xorg = patx;  yorg = paty;
 | |
| 		    }
 | |
| 	        }	
 | |
| 		RectFunc = Mono8x8PatternRectHelper_ScreenOrigin;
 | |
| 		if(infoRec->SubsequentMono8x8PatternFillTrap)
 | |
| 		    TrapFunc = Mono8x8PatternTrapHelper_ScreenOrigin;
 | |
| 	    } else {  /* !HARDWARE_PATTERN_SCREEN_ORIGIN */
 | |
| 		if(!(infoRec->Mono8x8PatternFillFlags & 
 | |
| 				HARDWARE_PATTERN_PROGRAMMED_BITS)){
 | |
| 		    pCache = (*infoRec->CacheMono8x8Pattern)(
 | |
| 					infoRec->pScrn, patx, paty);
 | |
| 		    patx = pCache->x;  paty = pCache->y;
 | |
| 	    	}
 | |
| 		else {
 | |
| 		  pCache = &(infoRec->ScratchCacheInfoRec);
 | |
| 		  pCache->pat0 = patx;
 | |
| 		  pCache->pat1 = paty;
 | |
| 		}
 | |
| 		RectFunc = Mono8x8PatternRectHelper;
 | |
|        	    }
 | |
| 
 | |
| 	    (*infoRec->SetupForMono8x8PatternFill)(infoRec->pScrn, 
 | |
| 		 patx, paty, pPriv->fg, pPriv->bg, pGC->alu, pGC->planemask);
 | |
| 	    break;
 | |
| 	case DO_CACHE_BLT:
 | |
|             pCache = (*infoRec->CacheTile)(infoRec->pScrn, pGC->tile.pixmap);
 | |
| 	    (*infoRec->SetupForScreenToScreenCopy)(infoRec->pScrn, 1, 1, 
 | |
| 		pGC->alu, pGC->planemask, -1);
 | |
| 
 | |
| 	    RectFunc = CacheBltRectHelper;
 | |
| 	    break;
 | |
| 	case DO_PIXMAP_COPY:
 | |
| 	    pCache = &(infoRec->ScratchCacheInfoRec);
 | |
| 	    pCache->x = pPriv->offscreenArea->box.x1;
 | |
| 	    pCache->y = pPriv->offscreenArea->box.y1;
 | |
| 	    pCache->w = pCache->orig_w = 
 | |
| 		pPriv->offscreenArea->box.x2 - pCache->x;
 | |
| 	    pCache->h = pCache->orig_h = 
 | |
| 		pPriv->offscreenArea->box.y2 - pCache->y;
 | |
| 
 | |
| 	    (*infoRec->SetupForScreenToScreenCopy)(infoRec->pScrn, 1, 1, 
 | |
| 		pGC->alu, pGC->planemask, -1);
 | |
| 
 | |
| 	    RectFunc = CacheBltRectHelper;
 | |
| 	    break;
 | |
| 	default:
 | |
| 	    return;
 | |
|     }
 | |
| 
 | |
|     XAAFillPolygonHelper(infoRec->pScrn, ptsIn, count, topPoint, 
 | |
| 		y, maxy, origin, RectFunc, TrapFunc, xorg, yorg, pCache);
 | |
| 
 | |
|     SET_SYNC_FLAG(infoRec);	
 | |
| }
 | |
| 
 | |
| 
 |