xenocara/xserver/hw/xfree86/xaa/xaaFillPoly.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);
}