xserver-multidpi/hw/xfree86/xaa/xaaFillRect.c
Paulo Cesar Pereira de Andrade 49f77fff14 Rework symbol visibility for easier maintenance
Save in a few special cases, _X_EXPORT should not be used in C source
files. Instead, it should be used in headers, and the proper C source
include that header. Some special cases are symbols that need to be
shared between modules, but not expected to be used by external drivers,
and symbols that are accessible via LoaderSymbol/dlopen.

  This patch also adds conditionally some new sdk header files, depending
on extensions enabled. These files were added to match pattern for
other extensions/modules, that is, have the headers "deciding" symbol
visibility in the sdk. These headers are:
o Xext/panoramiXsrv.h, Xext/panoramiX.h
o fbpict.h (unconditionally)
o vidmodeproc.h
o mioverlay.h (unconditionally, used only by xaa)
o xfixes.h (unconditionally, symbols required by dri2)

  LoaderSymbol and similar functions now don't have different prototypes,
in loaderProcs.h and xf86Module.h, so that both headers can be included,
without the need of defining IN_LOADER.

  xf86NewInputDevice() device prototype readded to xf86Xinput.h, but
not exported (and with a comment about it).
2008-12-03 05:43:34 -02:00

1096 lines
27 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(!REGION_NUM_RECTS(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 = ((w * Bpp) + 3) >> 2;
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 (REGION_NUM_RECTS(pGC->pCompositeClip) == 1) {
pextent = REGION_RECTS(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 = REGION_EXTENTS(pGC->pScreen, 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 = REGION_NUM_RECTS (pGC->pCompositeClip);
pbox = REGION_RECTS(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 (REGION_NUM_RECTS(prgnClip) == 1) {
pextent = REGION_RECTS(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 = REGION_EXTENTS(pGC->pScreen, 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 = REGION_NUM_RECTS (prgnClip);
pbox = REGION_RECTS(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);
}