xenocara/xserver/hw/xfree86/xaa/xaaFillRect.c

1102 lines
35 KiB
C

#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 "xaa.h"
#include "xaalocal.h"
static void XAARenderSolidRects(GCPtr, int, BoxPtr, int, int);
static void XAARenderColor8x8Rects(GCPtr, int, BoxPtr, int, int);
static void XAARenderMono8x8Rects(GCPtr, int, BoxPtr, int, int);
static void XAARenderColorExpandRects(GCPtr, int, BoxPtr, int, int);
static void XAARenderCacheExpandRects(GCPtr, int, BoxPtr, int, int);
static void XAARenderCacheBltRects(GCPtr, int, BoxPtr, int, int);
static void XAARenderImageWriteRects(GCPtr, int, BoxPtr, int, int);
static void XAARenderPixmapCopyRects(GCPtr, int, BoxPtr, int, int);
void
XAAPolyFillRect(DrawablePtr pDraw, GCPtr pGC, int nrectFill, /* number of rectangles to fill */
xRectangle *prectInit /* Pointer to first rectangle to fill */
)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
int xorg = pDraw->x;
int yorg = pDraw->y;
int type = 0;
ClipAndRenderRectsFunc function;
if ((nrectFill <= 0) || !pGC->planemask)
return;
if (!RegionNumRects(pGC->pCompositeClip))
return;
switch (pGC->fillStyle) {
case FillSolid:
type = DO_SOLID;
break;
case FillStippled:
type = (*infoRec->StippledFillChooser) (pGC);
break;
case FillOpaqueStippled:
if ((pGC->fgPixel == pGC->bgPixel) && infoRec->FillSolidRects &&
CHECK_PLANEMASK(pGC, infoRec->FillSolidRectsFlags) &&
CHECK_ROP(pGC, infoRec->FillSolidRectsFlags) &&
CHECK_ROPSRC(pGC, infoRec->FillSolidRectsFlags) &&
CHECK_FG(pGC, infoRec->FillSolidRectsFlags))
type = DO_SOLID;
else
type = (*infoRec->OpaqueStippledFillChooser) (pGC);
break;
case FillTiled:
type = (*infoRec->TiledFillChooser) (pGC);
break;
}
switch (type) {
case DO_SOLID:
function = XAARenderSolidRects;
break;
case DO_COLOR_8x8:
function = XAARenderColor8x8Rects;
break;
case DO_MONO_8x8:
function = XAARenderMono8x8Rects;
break;
case DO_CACHE_BLT:
function = XAARenderCacheBltRects;
break;
case DO_COLOR_EXPAND:
function = XAARenderColorExpandRects;
break;
case DO_CACHE_EXPAND:
function = XAARenderCacheExpandRects;
break;
case DO_IMAGE_WRITE:
function = XAARenderImageWriteRects;
break;
case DO_PIXMAP_COPY:
function = XAARenderPixmapCopyRects;
break;
default:
(*XAAFallbackOps.PolyFillRect) (pDraw, pGC, nrectFill, prectInit);
return;
}
if (xorg | yorg) {
int n = nrectFill;
xRectangle *prect = prectInit;
while (n--) {
prect->x += xorg;
prect->y += yorg;
prect++;
}
}
XAAClipAndRenderRects(pGC, function, nrectFill, prectInit, xorg, yorg);
}
/*********************\
| Solid Rects |
\*********************/
static void
XAARenderSolidRects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
(*infoRec->FillSolidRects) (infoRec->pScrn,
pGC->fgPixel, pGC->alu, pGC->planemask, nboxes,
pClipBoxes);
}
/************************\
| Mono 8x8 Rects |
\************************/
static void
XAARenderMono8x8Rects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
XAAPixmapPtr pPriv;
int fg, bg;
switch (pGC->fillStyle) {
case FillStippled:
pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple);
fg = pGC->fgPixel;
bg = -1;
break;
case FillOpaqueStippled:
pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple);
fg = pGC->fgPixel;
bg = pGC->bgPixel;
break;
case FillTiled:
pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap);
fg = pPriv->fg;
bg = pPriv->bg;
break;
default: /* Muffle compiler */
pPriv = NULL; /* Kaboom */
fg = -1;
bg = -1;
break;
}
(*infoRec->FillMono8x8PatternRects) (infoRec->pScrn,
fg, bg, pGC->alu, pGC->planemask,
nboxes, pClipBoxes, pPriv->pattern0,
pPriv->pattern1,
(xorg + pGC->patOrg.x),
(yorg + pGC->patOrg.y));
}
/*************************\
| Color 8x8 Rects |
\*************************/
static void
XAARenderColor8x8Rects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
XAACacheInfoPtr pCache;
PixmapPtr pPix;
int fg, bg;
switch (pGC->fillStyle) {
case FillStippled:
pPix = pGC->stipple;
fg = pGC->fgPixel;
bg = -1;
break;
case FillOpaqueStippled:
pPix = pGC->stipple;
fg = pGC->fgPixel;
bg = pGC->bgPixel;
break;
case FillTiled:
pPix = pGC->tile.pixmap;
fg = -1;
bg = -1;
break;
default: /* Muffle compiler */
pPix = NULL;
fg = -1;
bg = -1;
break;
}
pCache = (*infoRec->CacheColor8x8Pattern) (infoRec->pScrn, pPix, fg, bg);
(*infoRec->FillColor8x8PatternRects) (infoRec->pScrn,
pGC->alu, pGC->planemask, nboxes,
pClipBoxes, (xorg + pGC->patOrg.x),
(yorg + pGC->patOrg.y), pCache);
}
/****************************\
| Color Expand Rects |
\****************************/
static void
XAARenderColorExpandRects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
int fg, bg;
switch (pGC->fillStyle) {
case FillStippled:
fg = pGC->fgPixel;
bg = -1;
break;
case FillOpaqueStippled:
fg = pGC->fgPixel;
bg = pGC->bgPixel;
break;
default: /* Muffle compiler */
fg = -1;
bg = -1;
break;
}
(*infoRec->FillColorExpandRects) (infoRec->pScrn, fg, bg,
pGC->alu, pGC->planemask, nboxes,
pClipBoxes, (xorg + pGC->patOrg.x),
(yorg + pGC->patOrg.y), pGC->stipple);
}
/*************************\
| Cache Blt Rects |
\*************************/
static void
XAARenderCacheBltRects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
XAACacheInfoPtr pCache;
switch (pGC->fillStyle) {
case FillStippled:
pCache = (*infoRec->CacheStipple) (infoRec->pScrn, pGC->stipple,
pGC->fgPixel, -1);
break;
case FillOpaqueStippled:
pCache = (*infoRec->CacheStipple) (infoRec->pScrn, pGC->stipple,
pGC->fgPixel, pGC->bgPixel);
break;
case FillTiled:
pCache = (*infoRec->CacheTile) (infoRec->pScrn, pGC->tile.pixmap);
break;
default: /* Muffle compiler */
pCache = NULL;
break;
}
(*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu,
pGC->planemask, nboxes, pClipBoxes,
(xorg + pGC->patOrg.x),
(yorg + pGC->patOrg.y), pCache);
}
/****************************\
| Cache Expand Rects |
\****************************/
static void
XAARenderCacheExpandRects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
int fg, bg;
switch (pGC->fillStyle) {
case FillStippled:
fg = pGC->fgPixel;
bg = -1;
break;
case FillOpaqueStippled:
fg = pGC->fgPixel;
bg = pGC->bgPixel;
break;
default: /* Muffle compiler */
fg = -1;
bg = -1;
break;
}
(*infoRec->FillCacheExpandRects) (infoRec->pScrn, fg, bg,
pGC->alu, pGC->planemask, nboxes,
pClipBoxes, (xorg + pGC->patOrg.x),
(yorg + pGC->patOrg.y), pGC->stipple);
}
/***************************\
| Image Write Rects |
\***************************/
static void
XAARenderImageWriteRects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
(*infoRec->FillImageWriteRects) (infoRec->pScrn, pGC->alu,
pGC->planemask, nboxes, pClipBoxes,
(xorg + pGC->patOrg.x),
(yorg + pGC->patOrg.y), pGC->tile.pixmap);
}
/***************************\
| Pixmap Copy Rects |
\***************************/
static void
XAARenderPixmapCopyRects(GCPtr pGC,
int nboxes, BoxPtr pClipBoxes, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
XAACacheInfoPtr pCache = &(infoRec->ScratchCacheInfoRec);
XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap);
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;
pCache->trans_color = -1;
(*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu,
pGC->planemask, nboxes, pClipBoxes,
(xorg + pGC->patOrg.x),
(yorg + pGC->patOrg.y), pCache);
}
/************\
| Solid |
\************/
void
XAAFillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask, int nBox, /* number of rectangles to fill */
BoxPtr pBox /* Pointer to first rectangle to fill */
)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
(*infoRec->SetupForSolidFill) (pScrn, fg, rop, planemask);
while (nBox--) {
(*infoRec->SubsequentSolidFillRect) (pScrn, pBox->x1, pBox->y1,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1);
pBox++;
}
SET_SYNC_FLAG(infoRec);
}
/*********************\
| 8x8 Mono Patterns |
\*********************/
void
XAAFillMono8x8PatternRectsScreenOrigin(ScrnInfoPtr pScrn,
int fg, int bg, int rop,
unsigned int planemask,
int nBox,
BoxPtr pBox,
int pattern0, int pattern1,
int xorigin, int yorigin)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
int patx = pattern0, paty = pattern1;
int xorg = (-xorigin) & 0x07;
int yorg = (-yorigin) & 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) (pScrn, pattern0, pattern1);
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;
}
}
(*infoRec->SetupForMono8x8PatternFill) (pScrn, patx, paty,
fg, bg, rop, planemask);
while (nBox--) {
(*infoRec->SubsequentMono8x8PatternFillRect) (pScrn,
xorg, yorg, pBox->x1,
pBox->y1,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1);
pBox++;
}
SET_SYNC_FLAG(infoRec);
}
void
XAAFillMono8x8PatternRects(ScrnInfoPtr pScrn,
int fg, int bg, int rop,
unsigned int planemask,
int nBox,
BoxPtr pBox,
int pattern0, int pattern1, int xorigin, int yorigin)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
int patx = pattern0, paty = pattern1;
int xorg, yorg;
XAACacheInfoPtr pCache = NULL;
if (!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS)) {
pCache = (*infoRec->CacheMono8x8Pattern) (pScrn, pattern0, pattern1);
patx = pCache->x;
paty = pCache->y;
}
(*infoRec->SetupForMono8x8PatternFill) (pScrn, patx, paty,
fg, bg, rop, planemask);
while (nBox--) {
xorg = (pBox->x1 - xorigin) & 0x07;
yorg = (pBox->y1 - yorigin) & 0x07;
if (!(infoRec->Mono8x8PatternFillFlags &
HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
if (infoRec->Mono8x8PatternFillFlags &
HARDWARE_PATTERN_PROGRAMMED_BITS) {
patx = pattern0;
paty = pattern1;
XAARotateMonoPattern(&patx, &paty, xorg, yorg,
(infoRec->Mono8x8PatternFillFlags &
BIT_ORDER_IN_BYTE_MSBFIRST));
xorg = patx;
yorg = paty;
}
else {
int slot = (yorg << 3) + xorg;
xorg = patx + pCache->offsets[slot].x;
yorg = paty + pCache->offsets[slot].y;
}
}
(*infoRec->SubsequentMono8x8PatternFillRect) (pScrn,
xorg, yorg, pBox->x1,
pBox->y1,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1);
pBox++;
}
SET_SYNC_FLAG(infoRec);
}
/**********************\
| 8x8 Color Patterns |
\**********************/
void
XAAFillColor8x8PatternRectsScreenOrigin(ScrnInfoPtr pScrn,
int rop,
unsigned int planemask,
int nBox,
BoxPtr pBox,
int xorigin, int yorigin,
XAACacheInfoPtr pCache)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
int patx = pCache->x, paty = pCache->y;
int xorg = (-xorigin) & 0x07;
int yorg = (-yorigin) & 0x07;
if (!(infoRec->Color8x8PatternFillFlags &
HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
int slot = (yorg << 3) + xorg;
paty += pCache->offsets[slot].y;
patx += pCache->offsets[slot].x;
xorg = patx;
yorg = paty;
}
(*infoRec->SetupForColor8x8PatternFill) (pScrn, patx, paty,
rop, planemask,
pCache->trans_color);
while (nBox--) {
(*infoRec->SubsequentColor8x8PatternFillRect) (pScrn,
xorg, yorg, pBox->x1,
pBox->y1,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1);
pBox++;
}
SET_SYNC_FLAG(infoRec);
}
void
XAAFillColor8x8PatternRects(ScrnInfoPtr pScrn,
int rop,
unsigned int planemask,
int nBox,
BoxPtr pBox,
int xorigin, int yorigin, XAACacheInfoPtr pCache)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
int xorg, yorg;
(*infoRec->SetupForColor8x8PatternFill) (pScrn, pCache->x, pCache->y,
rop, planemask,
pCache->trans_color);
while (nBox--) {
xorg = (pBox->x1 - xorigin) & 0x07;
yorg = (pBox->y1 - yorigin) & 0x07;
if (!(infoRec->Color8x8PatternFillFlags &
HARDWARE_PATTERN_PROGRAMMED_ORIGIN)) {
int slot = (yorg << 3) + xorg;
yorg = pCache->y + pCache->offsets[slot].y;
xorg = pCache->x + pCache->offsets[slot].x;
}
(*infoRec->SubsequentColor8x8PatternFillRect) (pScrn,
xorg, yorg, pBox->x1,
pBox->y1,
pBox->x2 - pBox->x1,
pBox->y2 - pBox->y1);
pBox++;
}
SET_SYNC_FLAG(infoRec);
}
/***************\
| Cache Blits |
\***************/
void
XAAFillCacheBltRects(ScrnInfoPtr pScrn,
int rop,
unsigned int planemask,
int nBox,
BoxPtr pBox, int xorg, int yorg, XAACacheInfoPtr pCache)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h;
(*infoRec->SetupForScreenToScreenCopy) (pScrn, 1, 1, rop, planemask,
pCache->trans_color);
while (nBox--) {
y = pBox->y1;
phaseY = (y - yorg) % pCache->orig_h;
if (phaseY < 0)
phaseY += pCache->orig_h;
phaseX = (pBox->x1 - xorg) % pCache->orig_w;
if (phaseX < 0)
phaseX += pCache->orig_w;
height = pBox->y2 - y;
width = pBox->x2 - pBox->x1;
#if 0
if (rop == GXcopy) {
while (1) {
w = width;
skipleft = phaseX;
x = pBox->x1;
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;
if (blit_w >= pCache->orig_w)
break;
}
/* Expand horizontally */
if (w) {
skipleft -= phaseX;
if (skipleft < 0)
skipleft += pCache->orig_w;
blit_w = x - pBox->x1 - skipleft;
while (w) {
if (blit_w > w)
blit_w = w;
(*infoRec->SubsequentScreenToScreenCopy) (pScrn,
pBox->x1 +
skipleft, y,
x, y, blit_w,
blit_h);
w -= blit_w;
x += blit_w;
blit_w <<= 1;
}
}
height -= blit_h;
if (!height)
break;
y += blit_h;
phaseY = (phaseY + blit_h) % pCache->orig_h;
if (blit_h >= pCache->orig_h)
break;
}
/* Expand vertically */
if (height) {
blit_w = pBox->x2 - pBox->x1;
phaseY -= (pBox->y1 - yorg) % pCache->orig_h;
if (phaseY < 0)
phaseY += pCache->orig_h;
blit_h = y - pBox->y1 - phaseY;
while (height) {
if (blit_h > height)
blit_h = height;
(*infoRec->SubsequentScreenToScreenCopy) (pScrn, pBox->x1,
pBox->y1 + phaseY,
pBox->x1, y,
blit_w, blit_h);
height -= blit_h;
y += blit_h;
blit_h <<= 1;
}
}
}
else
#endif
{
while (1) {
w = width;
skipleft = phaseX;
x = pBox->x1;
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;
}
}
pBox++;
}
SET_SYNC_FLAG(infoRec);
}
/*******************\
| Cache Expansion |
\*******************/
void
XAAFillCacheExpandRects(ScrnInfoPtr pScrn,
int fg, int bg, int rop,
unsigned int planemask,
int nBox,
BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h;
int cacheWidth;
XAACacheInfoPtr pCache;
pCache = (*infoRec->CacheMonoStipple) (pScrn, pPix);
cacheWidth = (pCache->w * pScrn->bitsPerPixel) /
infoRec->CacheColorExpandDensity;
(*infoRec->SetupForScreenToScreenColorExpandFill) (pScrn, fg, bg, rop,
planemask);
while (nBox--) {
y = pBox->y1;
phaseY = (y - yorg) % pCache->orig_h;
if (phaseY < 0)
phaseY += pCache->orig_h;
phaseX = (pBox->x1 - xorg) % pCache->orig_w;
if (phaseX < 0)
phaseX += pCache->orig_w;
height = pBox->y2 - y;
width = pBox->x2 - pBox->x1;
while (1) {
w = width;
skipleft = phaseX;
x = pBox->x1;
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;
}
pBox++;
}
SET_SYNC_FLAG(infoRec);
}
/******************\
| Image Writes |
\******************/
/* This requires all LEFT_EDGE clipping. You get too many problems
with reading past the edge of the pattern otherwise */
static void
WriteColumn(ScrnInfoPtr pScrn,
unsigned char *pSrc,
int x, int y, int w, int h,
int xoff, int yoff, int pHeight, int srcwidth, int Bpp)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
unsigned char *src;
Bool PlusOne = FALSE;
int skipleft, dwords;
pSrc += (Bpp * xoff);
if ((skipleft = (long) pSrc & 0x03L)) {
if (Bpp == 3)
skipleft = 4 - skipleft;
else
skipleft /= Bpp;
x -= skipleft;
w += skipleft;
if (Bpp == 3)
pSrc -= 3 * skipleft;
else /* is this Alpha friendly ? */
pSrc = (unsigned char *) ((long) pSrc & ~0x03L);
}
src = pSrc + (yoff * srcwidth);
dwords = bytes_to_int32(w * Bpp);
if ((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) &&
((dwords * h) & 0x01)) {
PlusOne = TRUE;
}
(*infoRec->SubsequentImageWriteRect) (pScrn, x, y, w, h, skipleft);
if (dwords > infoRec->ImageWriteRange) {
while (h--) {
XAAMoveDWORDS_FixedBase((CARD32 *) infoRec->ImageWriteBase,
(CARD32 *) src, dwords);
src += srcwidth;
yoff++;
if (yoff >= pHeight) {
yoff = 0;
src = pSrc;
}
}
}
else {
if (srcwidth == (dwords << 2)) {
int maxLines = infoRec->ImageWriteRange / dwords;
int step;
while (h) {
step = pHeight - yoff;
if (step > maxLines)
step = maxLines;
if (step > h)
step = h;
XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase,
(CARD32 *) src, dwords * step);
src += (srcwidth * step);
yoff += step;
if (yoff >= pHeight) {
yoff = 0;
src = pSrc;
}
h -= step;
}
}
else {
while (h--) {
XAAMoveDWORDS((CARD32 *) infoRec->ImageWriteBase,
(CARD32 *) src, dwords);
src += srcwidth;
yoff++;
if (yoff >= pHeight) {
yoff = 0;
src = pSrc;
}
}
}
}
if (PlusOne) {
CARD32 *base = (CARD32 *) infoRec->ImageWriteBase;
*base = 0x00000000;
}
}
void
XAAFillImageWriteRects(ScrnInfoPtr pScrn,
int rop,
unsigned int planemask,
int nBox,
BoxPtr pBox, int xorg, int yorg, PixmapPtr pPix)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
int x, phaseY, phaseX, height, width, blit_w;
int pHeight = pPix->drawable.height;
int pWidth = pPix->drawable.width;
int Bpp = pPix->drawable.bitsPerPixel >> 3;
int srcwidth = pPix->devKind;
(*infoRec->SetupForImageWrite) (pScrn, rop, planemask, -1,
pPix->drawable.bitsPerPixel,
pPix->drawable.depth);
while (nBox--) {
x = pBox->x1;
phaseY = (pBox->y1 - yorg) % pHeight;
if (phaseY < 0)
phaseY += pHeight;
phaseX = (x - xorg) % pWidth;
if (phaseX < 0)
phaseX += pWidth;
height = pBox->y2 - pBox->y1;
width = pBox->x2 - x;
while (1) {
blit_w = pWidth - phaseX;
if (blit_w > width)
blit_w = width;
WriteColumn(pScrn, pPix->devPrivate.ptr, x, pBox->y1,
blit_w, height, phaseX, phaseY, pHeight, srcwidth, Bpp);
width -= blit_w;
if (!width)
break;
x += blit_w;
phaseX = (phaseX + blit_w) % pWidth;
}
pBox++;
}
if (infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE)
(*infoRec->Sync) (pScrn);
else
SET_SYNC_FLAG(infoRec);
}
/*************\
| Utilities |
\*************/
void
XAAClipAndRenderRects(GCPtr pGC,
ClipAndRenderRectsFunc BoxFunc,
int nrectFill, xRectangle *prect, int xorg, int yorg)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
int Right, Bottom, MaxBoxes;
BoxPtr pextent, pboxClipped, pboxClippedBase;
MaxBoxes = infoRec->PreAllocSize / sizeof(BoxRec);
pboxClippedBase = (BoxPtr) infoRec->PreAllocMem;
pboxClipped = pboxClippedBase;
if (RegionNumRects(pGC->pCompositeClip) == 1) {
pextent = RegionRects(pGC->pCompositeClip);
while (nrectFill--) {
pboxClipped->x1 = max(pextent->x1, prect->x);
pboxClipped->y1 = max(pextent->y1, prect->y);
Right = (int) prect->x + (int) prect->width;
pboxClipped->x2 = min(pextent->x2, Right);
Bottom = (int) prect->y + (int) prect->height;
pboxClipped->y2 = min(pextent->y2, Bottom);
prect++;
if ((pboxClipped->x1 < pboxClipped->x2) &&
(pboxClipped->y1 < pboxClipped->y2)) {
pboxClipped++;
if (pboxClipped >= (pboxClippedBase + MaxBoxes)) {
(*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg);
pboxClipped = pboxClippedBase;
}
}
}
}
else {
pextent = RegionExtents(pGC->pCompositeClip);
while (nrectFill--) {
int n;
BoxRec box, *pbox;
box.x1 = max(pextent->x1, prect->x);
box.y1 = max(pextent->y1, prect->y);
Right = (int) prect->x + (int) prect->width;
box.x2 = min(pextent->x2, Right);
Bottom = (int) prect->y + (int) prect->height;
box.y2 = min(pextent->y2, Bottom);
prect++;
if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
continue;
n = RegionNumRects(pGC->pCompositeClip);
pbox = RegionRects(pGC->pCompositeClip);
/* clip the rectangle to each box in the clip region
this is logically equivalent to calling Intersect()
*/
while (n--) {
pboxClipped->x1 = max(box.x1, pbox->x1);
pboxClipped->y1 = max(box.y1, pbox->y1);
pboxClipped->x2 = min(box.x2, pbox->x2);
pboxClipped->y2 = min(box.y2, pbox->y2);
pbox++;
/* see if clipping left anything */
if (pboxClipped->x1 < pboxClipped->x2 &&
pboxClipped->y1 < pboxClipped->y2) {
pboxClipped++;
if (pboxClipped >= (pboxClippedBase + MaxBoxes)) {
(*BoxFunc) (pGC, MaxBoxes, pboxClippedBase, xorg, yorg);
pboxClipped = pboxClippedBase;
}
}
}
}
}
if (pboxClipped != pboxClippedBase)
(*BoxFunc) (pGC, pboxClipped - pboxClippedBase, pboxClippedBase,
xorg, yorg);
}
int
XAAGetRectClipBoxes(GCPtr pGC,
BoxPtr pboxClippedBase,
int nrectFill, xRectangle *prectInit)
{
int Right, Bottom;
BoxPtr pextent, pboxClipped = pboxClippedBase;
xRectangle *prect = prectInit;
RegionPtr prgnClip = pGC->pCompositeClip;
if (RegionNumRects(prgnClip) == 1) {
pextent = RegionRects(prgnClip);
while (nrectFill--) {
pboxClipped->x1 = max(pextent->x1, prect->x);
pboxClipped->y1 = max(pextent->y1, prect->y);
Right = (int) prect->x + (int) prect->width;
pboxClipped->x2 = min(pextent->x2, Right);
Bottom = (int) prect->y + (int) prect->height;
pboxClipped->y2 = min(pextent->y2, Bottom);
prect++;
if ((pboxClipped->x1 < pboxClipped->x2) &&
(pboxClipped->y1 < pboxClipped->y2)) {
pboxClipped++;
}
}
}
else {
pextent = RegionExtents(prgnClip);
while (nrectFill--) {
int n;
BoxRec box, *pbox;
box.x1 = max(pextent->x1, prect->x);
box.y1 = max(pextent->y1, prect->y);
Right = (int) prect->x + (int) prect->width;
box.x2 = min(pextent->x2, Right);
Bottom = (int) prect->y + (int) prect->height;
box.y2 = min(pextent->y2, Bottom);
prect++;
if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
continue;
n = RegionNumRects(prgnClip);
pbox = RegionRects(prgnClip);
/* clip the rectangle to each box in the clip region
this is logically equivalent to calling Intersect()
*/
while (n--) {
pboxClipped->x1 = max(box.x1, pbox->x1);
pboxClipped->y1 = max(box.y1, pbox->y1);
pboxClipped->x2 = min(box.x2, pbox->x2);
pboxClipped->y2 = min(box.y2, pbox->y2);
pbox++;
/* see if clipping left anything */
if (pboxClipped->x1 < pboxClipped->x2 &&
pboxClipped->y1 < pboxClipped->y2) {
pboxClipped++;
}
}
}
}
return pboxClipped - pboxClippedBase;
}