476 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			476 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $XFree86: xc/programs/Xserver/hw/xfree86/xaa/xaaBitmap.c,v 1.9 2000/06/29 10:55:41 alanh 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
 |