992 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			992 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
| 
 | |
| /*
 | |
|  * 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 = extents->x1 - origin;
 | |
|     vertex2 = 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 (!RegionNumRects(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 (RegionNumRects(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 (!RegionNumRects(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 (RegionNumRects(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 = 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 (!RegionNumRects(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 (RegionNumRects(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 = 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);
 | |
| }
 |