478 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			478 lines
		
	
	
		
			12 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
 |