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);
|
|
}
|
|
|
|
|