xserver-multidpi/hw/xfree86/xaa/xaaBitmap.c

478 lines
12 KiB
C
Raw Normal View History

2003-11-14 17:48:57 +01:00
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
2003-11-14 17:48:57 +01:00
#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)
2003-11-14 17:48:57 +01:00
#else
#define DEST(i) dest[i]
#define RETURN(i) return(dest + i)
2003-11-14 17:48:57 +01:00
#endif
#ifdef MSBFIRST
#define SOURCE(i) SWAP_BITS_IN_BYTES(src[i])
2003-11-14 17:48:57 +01:00
#else
#define SOURCE(i) src[i]
2003-11-14 17:48:57 +01:00
#endif
typedef CARD32 *(*BitmapScanlineProcPtr) (CARD32 *, CARD32 *, int, int);
2003-11-14 17:48:57 +01:00
#ifdef TRIPLE_BITS
static CARD32 *
BitmapScanline(CARD32 *src, CARD32 *base, int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
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;
2003-11-14 17:48:57 +01:00
}
static CARD32 *
BitmapScanline_Inverted(CARD32 *src, CARD32 *base, int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
CARD32 bits;
2003-11-14 17:48:57 +01:00
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);
}
2003-11-14 17:48:57 +01:00
return base;
}
static CARD32 *
BitmapScanline_Shifted(CARD32 *src, CARD32 *base, int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
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;
2003-11-14 17:48:57 +01:00
}
static CARD32 *
BitmapScanline_Shifted_Inverted(CARD32 *src, CARD32 *base,
int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
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;
2003-11-14 17:48:57 +01:00
}
#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)
2003-11-14 17:48:57 +01:00
{
while (count >= 4) {
DEST(0) = SOURCE(0);
DEST(1) = SOURCE(1);
DEST(2) = SOURCE(2);
DEST(3) = SOURCE(3);
count -= 4;
src += 4;
2003-11-14 17:48:57 +01:00
#ifndef FIXEDBASE
dest += 4;
2003-11-14 17:48:57 +01:00
#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);
2003-11-14 17:48:57 +01:00
}
static CARD32 *
BitmapScanline_Inverted(CARD32 *src, CARD32 *dest, int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
while (count >= 4) {
DEST(0) = ~SOURCE(0);
DEST(1) = ~SOURCE(1);
DEST(2) = ~SOURCE(2);
DEST(3) = ~SOURCE(3);
count -= 4;
src += 4;
2003-11-14 17:48:57 +01:00
#ifndef FIXEDBASE
dest += 4;
2003-11-14 17:48:57 +01:00
#endif
}
2003-11-14 17:48:57 +01:00
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);
}
2003-11-14 17:48:57 +01:00
static CARD32 *
BitmapScanline_Shifted(CARD32 *bits, CARD32 *base, int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
while (count--) {
register CARD32 tmp = SHIFT_R(*bits, skipleft) |
SHIFT_L(*(bits + 1), (32 - skipleft));
WRITE_BITS(tmp);
bits++;
}
return base;
2003-11-14 17:48:57 +01:00
}
static CARD32 *
BitmapScanline_Shifted_Inverted(CARD32 *bits, CARD32 *base,
int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
while (count--) {
register CARD32 tmp = ~(SHIFT_R(*bits, skipleft) |
SHIFT_L(*(bits + 1), (32 - skipleft)));
WRITE_BITS(tmp);
bits++;
}
return base;
2003-11-14 17:48:57 +01:00
}
static CARD32 *
BitmapScanline_Shifted_Careful(CARD32 *bits, CARD32 *base,
int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
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;
2003-11-14 17:48:57 +01:00
}
static CARD32 *
BitmapScanline_Shifted_Inverted_Careful(CARD32 *bits, CARD32 *base,
int count, int skipleft)
2003-11-14 17:48:57 +01:00
{
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;
2003-11-14 17:48:57 +01:00
}
#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.
*/
2003-11-14 17:48:57 +01:00
void
2003-11-14 17:48:57 +01:00
#ifdef TRIPLE_BITS
EXPNAME(XAAWriteBitmapColorExpand3) (
2003-11-14 17:48:57 +01:00
#else
EXPNAME(XAAWriteBitmapColorExpand) (
2003-11-14 17:48:57 +01:00
#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) {
2003-11-14 17:48:57 +01:00
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
CARD32 *base;
2003-11-14 17:48:57 +01:00
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))))) {
2003-11-14 17:48:57 +01:00
#else
if ((bg != -1) &&
(infoRec->CPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
2003-11-14 17:48:57 +01:00
#endif
if ((rop == GXcopy) && infoRec->SetupForSolidFill) {
(*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask);
(*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
}
else
SecondPassColor = bg;
bg = -1;
2003-11-14 17:48:57 +01:00
}
#ifdef TRIPLE_BITS
if (skipleft) {
2003-11-14 17:48:57 +01:00
#else
if (skipleft &&
(!(infoRec->CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING) ||
(!(infoRec->
CPUToScreenColorExpandFillFlags & LEFT_EDGE_CLIPPING_NEGATIVE_X) &&
(skipleft > x)))) {
2003-11-14 17:48:57 +01:00
#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;
2003-11-14 17:48:57 +01:00
}
#ifdef TRIPLE_BITS
dwords = (3 * w + 31) >> 5;
#else
dwords = (w + 31) >> 5;
#endif
SECOND_PASS:
2003-11-14 17:48:57 +01:00
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);
2003-11-14 17:48:57 +01:00
base = (CARD32 *) infoRec->ColorExpandBase;
2003-11-14 17:48:57 +01:00
#ifndef FIXEDBASE
if ((dwords * h) <= infoRec->ColorExpandRange)
while (h--) {
base = (*firstFunc) ((CARD32 *) srcp, base, dwords, shift);
srcp += srcwidth;
}
2003-11-14 17:48:57 +01:00
else
#endif
while (h--) {
(*firstFunc) ((CARD32 *) srcp, base, dwords, shift);
srcp += srcwidth;
}
if (flag) {
base = (CARD32 *) infoRec->ColorExpandBase;
base[0] = 0x00000000;
2003-11-14 17:48:57 +01:00
}
if (SecondPassColor != -1) {
h = H; /* Reset height */
fg = SecondPassColor;
SecondPassColor = -1;
firstFunc = secondFunc;
srcp = src;
goto SECOND_PASS;
2003-11-14 17:48:57 +01:00
}
if (infoRec->CPUToScreenColorExpandFillFlags & SYNC_AFTER_COLOR_EXPAND)
(*infoRec->Sync) (pScrn);
else
SET_SYNC_FLAG(infoRec);
2003-11-14 17:48:57 +01:00
}
#ifndef FIXEDBASE
void
2003-11-14 17:48:57 +01:00
#ifdef TRIPLE_BITS
EXPNAME(XAAWriteBitmapScanlineColorExpand3) (
2003-11-14 17:48:57 +01:00
#else
EXPNAME(XAAWriteBitmapScanlineColorExpand) (
2003-11-14 17:48:57 +01:00
#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) {
2003-11-14 17:48:57 +01:00
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
CARD32 *base;
2003-11-14 17:48:57 +01:00
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))))) {
2003-11-14 17:48:57 +01:00
#else
if ((bg != -1) &&
(infoRec->
ScanlineCPUToScreenColorExpandFillFlags & TRANSPARENCY_ONLY)) {
2003-11-14 17:48:57 +01:00
#endif
if ((rop == GXcopy) && infoRec->SetupForSolidFill) {
(*infoRec->SetupForSolidFill) (pScrn, bg, rop, planemask);
(*infoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h);
}
else
SecondPassColor = bg;
bg = -1;
2003-11-14 17:48:57 +01:00
}
#ifdef TRIPLE_BITS
if (skipleft) {
2003-11-14 17:48:57 +01:00
#else
if (skipleft &&
(!(infoRec->ScanlineCPUToScreenColorExpandFillFlags &
LEFT_EDGE_CLIPPING) ||
(!(infoRec->ScanlineCPUToScreenColorExpandFillFlags &
LEFT_EDGE_CLIPPING_NEGATIVE_X) && (skipleft > x)))) {
2003-11-14 17:48:57 +01:00
#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;
2003-11-14 17:48:57 +01:00
}
#ifdef TRIPLE_BITS
dwords = (3 * w + 31) >> 5;
#else
dwords = (w + 31) >> 5;
#endif
SECOND_PASS:
2003-11-14 17:48:57 +01:00
(*infoRec->SetupForScanlineCPUToScreenColorExpandFill) (pScrn, fg, bg, rop,
planemask);
(*infoRec->SubsequentScanlineCPUToScreenColorExpandFill) (pScrn, x, y, w, h,
skipleft);
2003-11-14 17:48:57 +01:00
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;
2003-11-14 17:48:57 +01:00
}
if (SecondPassColor != -1) {
fg = SecondPassColor;
SecondPassColor = -1;
firstFunc = secondFunc;
srcp = src;
goto SECOND_PASS;
2003-11-14 17:48:57 +01:00
}
SET_SYNC_FLAG(infoRec);
}
#endif