477 lines
10 KiB
C
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
|