diff options
Diffstat (limited to 'hw/xfree86/xaa/xaaBitmap.c')
-rw-r--r-- | hw/xfree86/xaa/xaaBitmap.c | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/hw/xfree86/xaa/xaaBitmap.c b/hw/xfree86/xaa/xaaBitmap.c new file mode 100644 index 000000000..9a8749dbf --- /dev/null +++ b/hw/xfree86/xaa/xaaBitmap.c @@ -0,0 +1,475 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/xaa/xaaBitmap.c,v 1.10 2000/09/01 05:49:45 mvojkovi Exp $ */ + + +#include "xaa.h" +#include "xaalocal.h" +#include "xaacexp.h" +#include "xf86.h" +#include "xf86_ansic.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 |