xserver-multidpi/hw/xfree86/xaa/xaaBitmap.c
2006-07-21 17:56:00 -04:00

477 lines
10 KiB
C

#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#include "xaa.h"
#include "xaalocal.h"
#include "xaacexp.h"
#include "xf86.h"
/********** byte swapping ***************/
#ifdef FIXEDBASE
# define DEST(i) *dest
# define RETURN(i) return(dest)
#else
# define DEST(i) dest[i]
# define RETURN(i) return(dest + i)
#endif
#ifdef MSBFIRST
# define SOURCE(i) SWAP_BITS_IN_BYTES(src[i])
#else
# define SOURCE(i) src[i]
#endif
typedef CARD32 *(* BitmapScanlineProcPtr)(CARD32 *, CARD32 *, int, int);
#ifdef TRIPLE_BITS
static CARD32*
BitmapScanline(
CARD32 *src, CARD32 *base,
int count, int skipleft )
{
CARD32 bits;
while(count >= 3) {
bits = *src;
WRITE_BITS3(bits);
src++;
count -= 3;
}
if (count == 2) {
bits = *src;
WRITE_BITS2(bits);
} else if (count == 1) {
bits = *src;
WRITE_BITS1(bits);
}
return base;
}
static CARD32*
BitmapScanline_Inverted(
CARD32 *src, CARD32 *base,
int count, int skipleft )
{
CARD32 bits;
while(count >= 3) {
bits = ~(*src);
WRITE_BITS3(bits);
src++;
count -= 3;
}
if (count == 2) {
bits = ~(*src);
WRITE_BITS2(bits);
} else if (count == 1) {
bits = ~(*src);
WRITE_BITS1(bits);
}
return base;
}
static CARD32*
BitmapScanline_Shifted(
CARD32 *src, CARD32 *base,
int count, int skipleft )
{
CARD32 bits;
while(count >= 3) {
bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft));
WRITE_BITS3(bits);
src++;
count -= 3;
}
if (count == 2) {
bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft));
WRITE_BITS2(bits);
} else if (count == 1) {
bits = SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft));
WRITE_BITS1(bits);
}
return base;
}
static CARD32*
BitmapScanline_Shifted_Inverted(
CARD32 *src, CARD32 *base,
int count, int skipleft )
{
CARD32 bits;
while(count >= 3) {
bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)));
WRITE_BITS3(bits);
src++;
count -= 3;
}
if (count == 2) {
bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)));
WRITE_BITS2(bits);
} else if (count == 1) {
bits = ~(SHIFT_R(*src,skipleft) | SHIFT_L(*(src + 1),(32 - skipleft)));
WRITE_BITS1(bits);
}
return base;
}
#define BitmapScanline_Shifted_Careful BitmapScanline_Shifted
#define BitmapScanline_Shifted_Inverted_Careful BitmapScanline_Shifted_Inverted
#else
static CARD32*
BitmapScanline(
CARD32 *src, CARD32 *dest,
int count, int skipleft )
{
while(count >= 4) {
DEST(0) = SOURCE(0);
DEST(1) = SOURCE(1);
DEST(2) = SOURCE(2);
DEST(3) = SOURCE(3);
count -= 4;
src += 4;
#ifndef FIXEDBASE
dest += 4;
#endif
}
if(!count) return dest;
DEST(0) = SOURCE(0);
if(count == 1) RETURN(1);
DEST(1) = SOURCE(1);
if(count == 2) RETURN(2);
DEST(2) = SOURCE(2);
RETURN(3);
}
static CARD32*
BitmapScanline_Inverted(
CARD32 *src, CARD32 *dest,
int count, int skipleft )
{
while(count >= 4) {
DEST(0) = ~SOURCE(0);
DEST(1) = ~SOURCE(1);
DEST(2) = ~SOURCE(2);
DEST(3) = ~SOURCE(3);
count -= 4;
src += 4;
#ifndef FIXEDBASE
dest += 4;
#endif
}
if(!count) return dest;
DEST(0) = ~SOURCE(0);
if(count == 1) RETURN(1);
DEST(1) = ~SOURCE(1);
if(count == 2) RETURN(2);
DEST(2) = ~SOURCE(2);
RETURN(3);
}
static CARD32*
BitmapScanline_Shifted(
CARD32 *bits, CARD32 *base,
int count, int skipleft )
{
while(count--) {
register CARD32 tmp = SHIFT_R(*bits,skipleft) |
SHIFT_L(*(bits + 1),(32 - skipleft));
WRITE_BITS(tmp);
bits++;
}
return base;
}
static CARD32*
BitmapScanline_Shifted_Inverted(
CARD32 *bits, CARD32 *base,
int count, int skipleft )
{
while(count--) {
register CARD32 tmp = ~(SHIFT_R(*bits,skipleft) |
SHIFT_L(*(bits + 1),(32 - skipleft)));
WRITE_BITS(tmp);
bits++;
}
return base;
}
static CARD32*
BitmapScanline_Shifted_Careful(
CARD32 *bits, CARD32 *base,
int count, int skipleft )
{
register CARD32 tmp;
while(--count) {
tmp = SHIFT_R(*bits,skipleft) | SHIFT_L(*(bits + 1),(32 - skipleft));
WRITE_BITS(tmp);
bits++;
}
tmp = SHIFT_R(*bits,skipleft);
WRITE_BITS(tmp);
return base;
}
static CARD32*
BitmapScanline_Shifted_Inverted_Careful(
CARD32 *bits, CARD32 *base,
int count, int skipleft )
{
register CARD32 tmp;
while(--count) {
tmp = ~(SHIFT_R(*bits,skipleft) | SHIFT_L(*(bits + 1),(32 - skipleft)));
WRITE_BITS(tmp);
bits++;
}
tmp = ~(SHIFT_R(*bits,skipleft));
WRITE_BITS(tmp);
return base;
}
#endif
/*
When the accelerator is TRANSPARENCY_ONLY, WriteBitmap can do
the fill in two passes, inverting the source on the second pass.
For GXcopy we can fill the backing rectangle as a solid rect and
avoid the invert.
*/
void
#ifdef TRIPLE_BITS
EXPNAME(XAAWriteBitmapColorExpand3)(
#else
EXPNAME(XAAWriteBitmapColorExpand)(
#endif
ScrnInfoPtr pScrn,
int x, int y, int w, int H,
unsigned char *src,
int srcwidth,
int skipleft,
int fg, int bg,
int rop,
unsigned int planemask
)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
CARD32* base;
unsigned char *srcp = src;
int SecondPassColor = -1;
int shift = 0, dwords;
BitmapScanlineProcPtr firstFunc;
BitmapScanlineProcPtr secondFunc;
int flag;
int h = H;
#ifdef TRIPLE_BITS
if((bg != -1) &&
((infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY) ||
((infoRec->CPUToScreenColorExpandFillFlags & RGB_EQUAL) &&
(!CHECK_RGB_EQUAL(bg))))) {
#else
if((bg != -1) &&
(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
#endif
if((rop == GXcopy) && infoRec->SetupForSolidFill) {
(*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask);
(*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
} else SecondPassColor = bg;
bg = -1;
}
#ifdef TRIPLE_BITS
if(skipleft) {
#else
if(skipleft &&
(!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING) ||
(!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) &&
(skipleft > x)))) {
#endif
if((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) {
/* don't read past the end */
firstFunc = BitmapScanline_Shifted_Careful;
secondFunc = BitmapScanline_Shifted_Inverted_Careful;
} else {
firstFunc = BitmapScanline_Shifted;
secondFunc = BitmapScanline_Shifted_Inverted;
}
shift = skipleft;
skipleft = 0;
} else {
firstFunc = BitmapScanline;
secondFunc = BitmapScanline_Inverted;
w += skipleft;
x -= skipleft;
}
#ifdef TRIPLE_BITS
dwords = (3 * w + 31) >> 5;
#else
dwords = (w + 31) >> 5;
#endif
SECOND_PASS:
flag = (infoRec->CPUToScreenColorExpandFillFlags
& CPU_TRANSFER_PAD_QWORD) && ((dwords * h) & 0x01);
(*infoRec->SetupForCPUToScreenColorExpandFill)(
pScrn, fg, bg, rop, planemask);
(*infoRec->SubsequentCPUToScreenColorExpandFill)(
pScrn, x, y, w, h, skipleft);
base = (CARD32*)infoRec->ColorExpandBase;
#ifndef FIXEDBASE
if((dwords * h) <= infoRec->ColorExpandRange)
while(h--) {
base = (*firstFunc)((CARD32*)srcp, base, dwords, shift);
srcp += srcwidth;
}
else
#endif
while(h--) {
(*firstFunc)((CARD32*)srcp, base, dwords, shift);
srcp += srcwidth;
}
if(flag){
base = (CARD32*)infoRec->ColorExpandBase;
base[0] = 0x00000000;
}
if(SecondPassColor != -1) {
h = H; /* Reset height */
fg = SecondPassColor;
SecondPassColor = -1;
firstFunc = secondFunc;
srcp = src;
goto SECOND_PASS;
}
if(infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND)
(*infoRec->Sync)(pScrn);
else SET_SYNC_FLAG(infoRec);
}
#ifndef FIXEDBASE
void
#ifdef TRIPLE_BITS
EXPNAME(XAAWriteBitmapScanlineColorExpand3)(
#else
EXPNAME(XAAWriteBitmapScanlineColorExpand)(
#endif
ScrnInfoPtr pScrn,
int x, int y, int w, int h,
unsigned char *src,
int srcwidth,
int skipleft,
int fg, int bg,
int rop,
unsigned int planemask
)
{
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
CARD32* base;
unsigned char *srcp = src;
int SecondPassColor = -1;
int shift = 0, dwords, bufferNo;
BitmapScanlineProcPtr firstFunc;
BitmapScanlineProcPtr secondFunc;
#ifdef TRIPLE_BITS
if((bg != -1) &&
((infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)
|| ((infoRec->ScanlineCPUToScreenColorExpandFillFlags & RGB_EQUAL) &&
(!CHECK_RGB_EQUAL(bg))))) {
#else
if((bg != -1) &&
(infoRec->ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)){
#endif
if((rop == GXcopy) && infoRec->SetupForSolidFill) {
(*infoRec->SetupForSolidFill)(pScrn, bg, rop, planemask);
(*infoRec->SubsequentSolidFillRect)(pScrn, x, y, w, h);
} else SecondPassColor = bg;
bg = -1;
}
#ifdef TRIPLE_BITS
if(skipleft) {
#else
if(skipleft &&
(!(infoRec->ScanlineCPUToScreenColorExpandFillFlags &
LEFT_EDGE_CLIPPING) ||
(!(infoRec->ScanlineCPUToScreenColorExpandFillFlags &
LEFT_EDGE_CLIPPING_NEGATIVE_X) && (skipleft > x)))) {
#endif
if((skipleft + ((w + 31) & ~31)) > ((skipleft + w + 31) & ~31)) {
/* don't read past the end */
firstFunc = BitmapScanline_Shifted_Careful;
secondFunc = BitmapScanline_Shifted_Inverted_Careful;
} else {
firstFunc = BitmapScanline_Shifted;
secondFunc = BitmapScanline_Shifted_Inverted;
}
shift = skipleft;
skipleft = 0;
} else {
firstFunc = BitmapScanline;
secondFunc = BitmapScanline_Inverted;
w += skipleft;
x -= skipleft;
}
#ifdef TRIPLE_BITS
dwords = (3 * w + 31) >> 5;
#else
dwords = (w + 31) >> 5;
#endif
SECOND_PASS:
(*infoRec->SetupForScanlineCPUToScreenColorExpandFill)(pScrn, fg, bg, rop, planemask);
(*infoRec->SubsequentScanlineCPUToScreenColorExpandFill)(
pScrn, x, y, w, h, skipleft);
bufferNo = 0;
while(h--) {
base = (CARD32*)infoRec->ScanlineColorExpandBuffers[bufferNo];
(*firstFunc)((CARD32*)srcp, base, dwords, shift);
(*infoRec->SubsequentColorExpandScanline)(pScrn, bufferNo++);
srcp += srcwidth;
if(bufferNo >= infoRec->NumScanlineColorExpandBuffers)
bufferNo = 0;
}
if(SecondPassColor != -1) {
fg = SecondPassColor;
SecondPassColor = -1;
firstFunc = secondFunc;
srcp = src;
goto SECOND_PASS;
}
SET_SYNC_FLAG(infoRec);
}
#endif