4415 lines
		
	
	
		
			120 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			4415 lines
		
	
	
		
			120 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  *
 | |
|  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
 | |
|  *             2005 Lars Knoll & Zack Rusin, Trolltech
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that
 | |
|  * copyright notice and this permission notice appear in supporting
 | |
|  * documentation, and that the name of Keith Packard not be used in
 | |
|  * advertising or publicity pertaining to distribution of the software without
 | |
|  * specific, written prior permission.  Keith Packard makes no
 | |
|  * representations about the suitability of this software for any purpose.  It
 | |
|  * is provided "as is" without express or implied warranty.
 | |
|  *
 | |
|  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 | |
|  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | |
|  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 | |
|  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | |
|  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 | |
|  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 | |
|  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | |
|  * SOFTWARE.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include "fb.h"
 | |
| 
 | |
| #ifdef RENDER
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <math.h>
 | |
| #include <assert.h>
 | |
| 
 | |
| #include "picturestr.h"
 | |
| #include "mipict.h"
 | |
| #include "fbpict.h"
 | |
| 
 | |
| static unsigned int
 | |
| SourcePictureClassify (PicturePtr pict,
 | |
| 		       int	  x,
 | |
| 		       int	  y,
 | |
| 		       int	  width,
 | |
| 		       int	  height)
 | |
| {
 | |
|     if (pict->pSourcePict->type == SourcePictTypeSolidFill)
 | |
|     {
 | |
| 	pict->pSourcePict->solidFill.class = SourcePictClassHorizontal;
 | |
|     }
 | |
|     else if (pict->pSourcePict->type == SourcePictTypeLinear)
 | |
|     {
 | |
| 	PictVector   v;
 | |
| 	xFixed_32_32 l;
 | |
| 	xFixed_48_16 dx, dy, a, b, off;
 | |
| 	xFixed_48_16 factors[4];
 | |
| 	int	     i;
 | |
| 
 | |
| 	dx = pict->pSourcePict->linear.p2.x - pict->pSourcePict->linear.p1.x;
 | |
| 	dy = pict->pSourcePict->linear.p2.y - pict->pSourcePict->linear.p1.y;
 | |
| 	l = dx * dx + dy * dy;
 | |
| 	if (l)
 | |
| 	{
 | |
| 	    a = (dx << 32) / l;
 | |
| 	    b = (dy << 32) / l;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    a = b = 0;
 | |
| 	}
 | |
| 
 | |
| 	off = (-a * pict->pSourcePict->linear.p1.x
 | |
| 	       -b * pict->pSourcePict->linear.p1.y) >> 16;
 | |
| 
 | |
| 	for (i = 0; i < 3; i++)
 | |
| 	{
 | |
| 	    v.vector[0] = IntToxFixed ((i % 2) * (width  - 1) + x);
 | |
| 	    v.vector[1] = IntToxFixed ((i / 2) * (height - 1) + y);
 | |
| 	    v.vector[2] = xFixed1;
 | |
| 
 | |
| 	    if (pict->transform)
 | |
| 	    {
 | |
| 		if (!PictureTransformPoint3d (pict->transform, &v))
 | |
| 		    return SourcePictClassUnknown;
 | |
| 	    }
 | |
| 
 | |
| 	    factors[i] = ((a * v.vector[0] + b * v.vector[1]) >> 16) + off;
 | |
| 	}
 | |
| 
 | |
| 	if (factors[2] == factors[0])
 | |
| 	    pict->pSourcePict->linear.class = SourcePictClassHorizontal;
 | |
| 	else if (factors[1] == factors[0])
 | |
| 	    pict->pSourcePict->linear.class = SourcePictClassVertical;
 | |
|     }
 | |
| 
 | |
|     return pict->pSourcePict->solidFill.class;
 | |
| }
 | |
| 
 | |
| #define mod(a,b)	((b) == 1 ? 0 : (a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
 | |
| 
 | |
| #define SCANLINE_BUFFER_LENGTH 2048
 | |
| 
 | |
| typedef FASTCALL void (*fetchProc)(const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed);
 | |
| 
 | |
| /*
 | |
|  * All of the fetch functions
 | |
|  */
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     MEMCPY_WRAPPED(buffer, (const CARD32 *)bits + x, width*sizeof(CARD32));
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_x8r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD32 *pixel = (const CARD32 *)bits + x;
 | |
|     const CARD32 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         WRITE(buffer++, READ(pixel++) | 0xff000000);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a8b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD32 *pixel = (CARD32 *)bits + x;
 | |
|     const CARD32 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         WRITE(buffer++, ((READ(pixel) & 0xff00ff00) |
 | |
|                          ((READ(pixel) >> 16) & 0xff) |
 | |
|                          ((READ(pixel) & 0xff) << 16)));
 | |
|         ++pixel;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_x8b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD32 *pixel = (CARD32 *)bits + x;
 | |
|     const CARD32 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         WRITE(buffer++, 0xff000000 |
 | |
| 	      ((READ(pixel) & 0x0000ff00) |
 | |
| 	       ((READ(pixel) >> 16) & 0xff) |
 | |
| 	       ((READ(pixel) & 0xff) << 16)));
 | |
|         ++pixel;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_r8g8b8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + 3*x;
 | |
|     const CARD8 *end = pixel + 3*width;
 | |
|     while (pixel < end) {
 | |
|         CARD32 b = Fetch24(pixel) | 0xff000000;
 | |
|         pixel += 3;
 | |
|         WRITE(buffer++, b);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_b8g8r8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + 3*x;
 | |
|     const CARD8 *end = pixel + 3*width;
 | |
|     while (pixel < end) {
 | |
|         CARD32 b = 0xff000000;
 | |
| #if IMAGE_BYTE_ORDER == MSBFirst
 | |
|         b |= (READ(pixel++));
 | |
|         b |= (READ(pixel++) << 8);
 | |
|         b |= (READ(pixel++) << 16);
 | |
| #else
 | |
|         b |= (READ(pixel++) << 16);
 | |
|         b |= (READ(pixel++) << 8);
 | |
|         b |= (READ(pixel++));
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_r5g6b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32 r = (((p) << 3) & 0xf8) | 
 | |
| 	    (((p) << 5) & 0xfc00) |
 | |
| 	    (((p) << 8) & 0xf80000);
 | |
|         r |= (r >> 5) & 0x70007;
 | |
|         r |= (r >> 6) & 0x300;
 | |
|         WRITE(buffer++, 0xff000000 | r);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_b5g6r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         b = ((p & 0xf800) | ((p & 0xe000) >> 5)) >> 8;
 | |
|         g = ((p & 0x07e0) | ((p & 0x0600) >> 6)) << 5;
 | |
|         r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
 | |
|         WRITE(buffer++, (0xff000000 | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a1r5g5b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b, a;
 | |
| 
 | |
|         a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24;
 | |
|         r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9;
 | |
|         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
 | |
|         b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2;
 | |
|         WRITE(buffer++, (a | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_x1r5g5b5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         r = ((p & 0x7c00) | ((p & 0x7000) >> 5)) << 9;
 | |
|         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
 | |
|         b = ((p & 0x001c) | ((p & 0x001f) << 5)) >> 2;
 | |
|         WRITE(buffer++, (0xff000000 | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a1b5g5r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b, a;
 | |
| 
 | |
|         a = (CARD32) ((CARD8) (0 - ((p & 0x8000) >> 15))) << 24;
 | |
|         b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7;
 | |
|         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
 | |
|         r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
 | |
|         WRITE(buffer++, (a | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_x1b5g5r5 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         b = ((p & 0x7c00) | ((p & 0x7000) >> 5)) >> 7;
 | |
|         g = ((p & 0x03e0) | ((p & 0x0380) >> 5)) << 6;
 | |
|         r = ((p & 0x001c) | ((p & 0x001f) << 5)) << 14;
 | |
|         WRITE(buffer++, (0xff000000 | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a4r4g4b4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b, a;
 | |
| 
 | |
|         a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16;
 | |
|         r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
 | |
|         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
 | |
|         b = ((p & 0x000f) | ((p & 0x000f) << 4));
 | |
|         WRITE(buffer++, (a | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_x4r4g4b4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         r = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) << 12;
 | |
|         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
 | |
|         b = ((p & 0x000f) | ((p & 0x000f) << 4));
 | |
|         WRITE(buffer++, (0xff000000 | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a4b4g4r4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b, a;
 | |
| 
 | |
|         a = ((p & 0xf000) | ((p & 0xf000) >> 4)) << 16;
 | |
|         b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4;
 | |
|         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
 | |
|         r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16;
 | |
|         WRITE(buffer++, (a | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_x4b4g4r4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD16 *pixel = (const CARD16 *)bits + x;
 | |
|     const CARD16 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         b = ((p & 0x0f00) | ((p & 0x0f00) >> 4)) >> 4;
 | |
|         g = ((p & 0x00f0) | ((p & 0x00f0) >> 4)) << 8;
 | |
|         r = ((p & 0x000f) | ((p & 0x000f) << 4)) << 16;
 | |
|         WRITE(buffer++, (0xff000000 | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + x;
 | |
|     const CARD8 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         WRITE(buffer++, READ(pixel++) << 24);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_r3g3b2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + x;
 | |
|     const CARD8 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         r = ((p & 0xe0) | ((p & 0xe0) >> 3) | ((p & 0xc0) >> 6)) << 16;
 | |
|         g = ((p & 0x1c) | ((p & 0x18) >> 3) | ((p & 0x1c) << 3)) << 8;
 | |
|         b = (((p & 0x03)     ) |
 | |
|              ((p & 0x03) << 2) |
 | |
|              ((p & 0x03) << 4) |
 | |
|              ((p & 0x03) << 6));
 | |
|         WRITE(buffer++, (0xff000000 | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_b2g3r3 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + x;
 | |
|     const CARD8 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         b = (((p & 0xc0)     ) |
 | |
|              ((p & 0xc0) >> 2) |
 | |
|              ((p & 0xc0) >> 4) |
 | |
|              ((p & 0xc0) >> 6));
 | |
|         g = ((p & 0x38) | ((p & 0x38) >> 3) | ((p & 0x30) << 2)) << 8;
 | |
|         r = (((p & 0x07)     ) |
 | |
|              ((p & 0x07) << 3) |
 | |
|              ((p & 0x06) << 6)) << 16;
 | |
|         WRITE(buffer++, (0xff000000 | r | g | b));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a2r2g2b2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + x;
 | |
|     const CARD8 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32   a,r,g,b;
 | |
| 
 | |
|         a = ((p & 0xc0) * 0x55) << 18;
 | |
|         r = ((p & 0x30) * 0x55) << 12;
 | |
|         g = ((p & 0x0c) * 0x55) << 6;
 | |
|         b = ((p & 0x03) * 0x55);
 | |
|         WRITE(buffer++, a|r|g|b);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a2b2g2r2 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + x;
 | |
|     const CARD8 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         CARD32   a,r,g,b;
 | |
| 
 | |
|         a = ((p & 0xc0) * 0x55) << 18;
 | |
|         b = ((p & 0x30) * 0x55) >> 6;
 | |
|         g = ((p & 0x0c) * 0x55) << 6;
 | |
|         r = ((p & 0x03) * 0x55) << 16;
 | |
|         WRITE(buffer++, a|r|g|b);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_c8 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + x;
 | |
|     const CARD8 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
|         CARD32  p = READ(pixel++);
 | |
|         WRITE(buffer++, indexed->rgba[p]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_x4a4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     const CARD8 *pixel = (const CARD8 *)bits + x;
 | |
|     const CARD8 *end = pixel + width;
 | |
|     while (pixel < end) {
 | |
| 	CARD8 p = READ(pixel++) & 0xf;
 | |
|         WRITE(buffer++, (p | (p << 4)) << 24);
 | |
|     }
 | |
| }
 | |
| 
 | |
| #define Fetch8(l,o)    (((CARD8 *) (l))[(o) >> 2])
 | |
| #if IMAGE_BYTE_ORDER == MSBFirst
 | |
| #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4)
 | |
| #else
 | |
| #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf)
 | |
| #endif
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = Fetch4(bits, i + x);
 | |
| 
 | |
|         p |= p << 4;
 | |
|         WRITE(buffer++, p << 24);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_r1g2b1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = Fetch4(bits, i + x);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         r = ((p & 0x8) * 0xff) << 13;
 | |
|         g = ((p & 0x6) * 0x55) << 7;
 | |
|         b = ((p & 0x1) * 0xff);
 | |
|         WRITE(buffer++, 0xff000000|r|g|b);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_b1g2r1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = Fetch4(bits, i + x);
 | |
|         CARD32  r,g,b;
 | |
| 
 | |
|         b = ((p & 0x8) * 0xff) >> 3;
 | |
|         g = ((p & 0x6) * 0x55) << 7;
 | |
|         r = ((p & 0x1) * 0xff) << 16;
 | |
|         WRITE(buffer++, 0xff000000|r|g|b);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a1r1g1b1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = Fetch4(bits, i + x);
 | |
|         CARD32  a,r,g,b;
 | |
| 
 | |
|         a = ((p & 0x8) * 0xff) << 21;
 | |
|         r = ((p & 0x4) * 0xff) << 14;
 | |
|         g = ((p & 0x2) * 0xff) << 7;
 | |
|         b = ((p & 0x1) * 0xff);
 | |
|         WRITE(buffer++, a|r|g|b);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a1b1g1r1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = Fetch4(bits, i + x);
 | |
|         CARD32  a,r,g,b;
 | |
| 
 | |
|         a = ((p & 0x8) * 0xff) << 21;
 | |
|         r = ((p & 0x4) * 0xff) >> 3;
 | |
|         g = ((p & 0x2) * 0xff) << 7;
 | |
|         b = ((p & 0x1) * 0xff) << 16;
 | |
|         WRITE(buffer++, a|r|g|b);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_c4 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = Fetch4(bits, i + x);
 | |
| 
 | |
|         WRITE(buffer++, indexed->rgba[p]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_a1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = ((CARD32 *)bits)[(i + x) >> 5];
 | |
|         CARD32  a;
 | |
| #if BITMAP_BIT_ORDER == MSBFirst
 | |
|         a = p >> (0x1f - ((i+x) & 0x1f));
 | |
| #else
 | |
|         a = p >> ((i+x) & 0x1f);
 | |
| #endif
 | |
|         a = a & 1;
 | |
|         a |= a << 1;
 | |
|         a |= a << 2;
 | |
|         a |= a << 4;
 | |
|         WRITE(buffer++, a << 24);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbFetch_g1 (const FbBits *bits, int x, int width, CARD32 *buffer, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  p = ((CARD32 *)bits)[(i+x) >> 5];
 | |
|         CARD32 a;
 | |
| #if BITMAP_BIT_ORDER == MSBFirst
 | |
|         a = p >> (0x1f - ((i+x) & 0x1f));
 | |
| #else
 | |
|         a = p >> ((i+x) & 0x1f);
 | |
| #endif
 | |
|         a = a & 1;
 | |
|         WRITE(buffer++, indexed->rgba[a]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static fetchProc fetchProcForPicture (PicturePtr pict)
 | |
| {
 | |
|     switch(pict->format) {
 | |
|     case PICT_a8r8g8b8: return fbFetch_a8r8g8b8;
 | |
|     case PICT_x8r8g8b8: return fbFetch_x8r8g8b8;
 | |
|     case PICT_a8b8g8r8: return fbFetch_a8b8g8r8;
 | |
|     case PICT_x8b8g8r8: return fbFetch_x8b8g8r8;
 | |
| 
 | |
|         /* 24bpp formats */
 | |
|     case PICT_r8g8b8: return fbFetch_r8g8b8;
 | |
|     case PICT_b8g8r8: return fbFetch_b8g8r8;
 | |
| 
 | |
|         /* 16bpp formats */
 | |
|     case PICT_r5g6b5: return fbFetch_r5g6b5;
 | |
|     case PICT_b5g6r5: return fbFetch_b5g6r5;
 | |
| 
 | |
|     case PICT_a1r5g5b5: return fbFetch_a1r5g5b5;
 | |
|     case PICT_x1r5g5b5: return fbFetch_x1r5g5b5;
 | |
|     case PICT_a1b5g5r5: return fbFetch_a1b5g5r5;
 | |
|     case PICT_x1b5g5r5: return fbFetch_x1b5g5r5;
 | |
|     case PICT_a4r4g4b4: return fbFetch_a4r4g4b4;
 | |
|     case PICT_x4r4g4b4: return fbFetch_x4r4g4b4;
 | |
|     case PICT_a4b4g4r4: return fbFetch_a4b4g4r4;
 | |
|     case PICT_x4b4g4r4: return fbFetch_x4b4g4r4;
 | |
| 
 | |
|         /* 8bpp formats */
 | |
|     case PICT_a8: return  fbFetch_a8;
 | |
|     case PICT_r3g3b2: return fbFetch_r3g3b2;
 | |
|     case PICT_b2g3r3: return fbFetch_b2g3r3;
 | |
|     case PICT_a2r2g2b2: return fbFetch_a2r2g2b2;
 | |
|     case PICT_a2b2g2r2: return fbFetch_a2b2g2r2;
 | |
|     case PICT_c8: return  fbFetch_c8;
 | |
|     case PICT_g8: return  fbFetch_c8;
 | |
|     case PICT_x4a4: return fbFetch_x4a4;
 | |
| 
 | |
|         /* 4bpp formats */
 | |
|     case PICT_a4: return  fbFetch_a4;
 | |
|     case PICT_r1g2b1: return fbFetch_r1g2b1;
 | |
|     case PICT_b1g2r1: return fbFetch_b1g2r1;
 | |
|     case PICT_a1r1g1b1: return fbFetch_a1r1g1b1;
 | |
|     case PICT_a1b1g1r1: return fbFetch_a1b1g1r1;
 | |
|     case PICT_c4: return  fbFetch_c4;
 | |
|     case PICT_g4: return  fbFetch_c4;
 | |
| 
 | |
|         /* 1bpp formats */
 | |
|     case PICT_a1: return  fbFetch_a1;
 | |
|     case PICT_g1: return  fbFetch_g1;
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Pixel wise fetching
 | |
|  */
 | |
| 
 | |
| typedef FASTCALL CARD32 (*fetchPixelProc)(const FbBits *bits, int offset, miIndexedPtr indexed);
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a8r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     return READ((CARD32 *)bits + offset);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_x8r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     return READ((CARD32 *)bits + offset) | 0xff000000;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a8b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD32 *)bits + offset);
 | |
| 
 | |
|     return ((pixel & 0xff000000) |
 | |
| 	    ((pixel >> 16) & 0xff) |
 | |
| 	    (pixel & 0x0000ff00) |
 | |
| 	    ((pixel & 0xff) << 16));
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_x8b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD32 *)bits + offset);
 | |
| 
 | |
|     return ((0xff000000) |
 | |
| 	    ((pixel >> 16) & 0xff) |
 | |
| 	    (pixel & 0x0000ff00) |
 | |
| 	    ((pixel & 0xff) << 16));
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_r8g8b8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + (offset*3);
 | |
| #if IMAGE_BYTE_ORDER == MSBFirst
 | |
|     return (0xff000000 |
 | |
| 	    (READ(pixel + 0) << 16) |
 | |
| 	    (READ(pixel + 1) << 8) |
 | |
| 	    (READ(pixel + 2)));
 | |
| #else
 | |
|     return (0xff000000 |
 | |
|             (READ(pixel + 2) << 16) |
 | |
|             (READ(pixel + 1) << 8) |
 | |
|             (READ(pixel + 0)));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_b8g8r8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + (offset*3);
 | |
| #if IMAGE_BYTE_ORDER == MSBFirst
 | |
|     return (0xff000000 |
 | |
| 	    (READ(pixel + 2) << 16) |
 | |
| 	    (READ(pixel + 1) << 8) |
 | |
| 	    (READ(pixel + 0)));
 | |
| #else
 | |
|     return (0xff000000 |
 | |
| 	    (READ(pixel + 0) << 16) |
 | |
| 	    (READ(pixel + 1) << 8) |
 | |
| 	    (READ(pixel + 2)));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_r5g6b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     r = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) << 8;
 | |
|     g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5;
 | |
|     b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_b5g6r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     b = ((pixel & 0xf800) | ((pixel & 0xe000) >> 5)) >> 8;
 | |
|     g = ((pixel & 0x07e0) | ((pixel & 0x0600) >> 6)) << 5;
 | |
|     r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  a,r,g,b;
 | |
| 
 | |
|     a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24;
 | |
|     r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9;
 | |
|     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
 | |
|     b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
 | |
|     return (a | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_x1r5g5b5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     r = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) << 9;
 | |
|     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
 | |
|     b = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) >> 2;
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  a,r,g,b;
 | |
| 
 | |
|     a = (CARD32) ((CARD8) (0 - ((pixel & 0x8000) >> 15))) << 24;
 | |
|     b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7;
 | |
|     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
 | |
|     r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
 | |
|     return (a | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_x1b5g5r5 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     b = ((pixel & 0x7c00) | ((pixel & 0x7000) >> 5)) >> 7;
 | |
|     g = ((pixel & 0x03e0) | ((pixel & 0x0380) >> 5)) << 6;
 | |
|     r = ((pixel & 0x001c) | ((pixel & 0x001f) << 5)) << 14;
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  a,r,g,b;
 | |
| 
 | |
|     a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16;
 | |
|     r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
 | |
|     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
 | |
|     b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
 | |
|     return (a | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_x4r4g4b4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     r = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) << 12;
 | |
|     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
 | |
|     b = ((pixel & 0x000f) | ((pixel & 0x000f) << 4));
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a4b4g4r4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  a,r,g,b;
 | |
| 
 | |
|     a = ((pixel & 0xf000) | ((pixel & 0xf000) >> 4)) << 16;
 | |
|     b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4;
 | |
|     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
 | |
|     r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16;
 | |
|     return (a | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_x4b4g4r4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = READ((CARD16 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     b = ((pixel & 0x0f00) | ((pixel & 0x0f00) >> 4)) >> 4;
 | |
|     g = ((pixel & 0x00f0) | ((pixel & 0x00f0) >> 4)) << 8;
 | |
|     r = ((pixel & 0x000f) | ((pixel & 0x000f) << 4)) << 16;
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32   pixel = READ((CARD8 *) bits + offset);
 | |
| 
 | |
|     return pixel << 24;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_r3g3b2 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32   pixel = READ((CARD8 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     r = ((pixel & 0xe0) | ((pixel & 0xe0) >> 3) | ((pixel & 0xc0) >> 6)) << 16;
 | |
|     g = ((pixel & 0x1c) | ((pixel & 0x18) >> 3) | ((pixel & 0x1c) << 3)) << 8;
 | |
|     b = (((pixel & 0x03)     ) |
 | |
| 	 ((pixel & 0x03) << 2) |
 | |
| 	 ((pixel & 0x03) << 4) |
 | |
| 	 ((pixel & 0x03) << 6));
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_b2g3r3 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32   pixel = READ((CARD8 *) bits + offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     b = (((pixel & 0xc0)     ) |
 | |
| 	 ((pixel & 0xc0) >> 2) |
 | |
| 	 ((pixel & 0xc0) >> 4) |
 | |
| 	 ((pixel & 0xc0) >> 6));
 | |
|     g = ((pixel & 0x38) | ((pixel & 0x38) >> 3) | ((pixel & 0x30) << 2)) << 8;
 | |
|     r = (((pixel & 0x07)     ) |
 | |
| 	 ((pixel & 0x07) << 3) |
 | |
| 	 ((pixel & 0x06) << 6)) << 16;
 | |
|     return (0xff000000 | r | g | b);
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a2r2g2b2 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32   pixel = READ((CARD8 *) bits + offset);
 | |
|     CARD32   a,r,g,b;
 | |
| 
 | |
|     a = ((pixel & 0xc0) * 0x55) << 18;
 | |
|     r = ((pixel & 0x30) * 0x55) << 12;
 | |
|     g = ((pixel & 0x0c) * 0x55) << 6;
 | |
|     b = ((pixel & 0x03) * 0x55);
 | |
|     return a|r|g|b;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a2b2g2r2 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32   pixel = READ((CARD8 *) bits + offset);
 | |
|     CARD32   a,r,g,b;
 | |
| 
 | |
|     a = ((pixel & 0xc0) * 0x55) << 18;
 | |
|     b = ((pixel & 0x30) * 0x55) >> 6;
 | |
|     g = ((pixel & 0x0c) * 0x55) << 6;
 | |
|     r = ((pixel & 0x03) * 0x55) << 16;
 | |
|     return a|r|g|b;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_c8 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32   pixel = READ((CARD8 *) bits + offset);
 | |
|     return indexed->rgba[pixel];
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_x4a4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32   pixel = READ((CARD8 *) bits + offset);
 | |
| 
 | |
|     return ((pixel & 0xf) | ((pixel & 0xf) << 4)) << 24;
 | |
| }
 | |
| 
 | |
| #define Fetch8(l,o)    (((CARD8 *) (l))[(o) >> 2])
 | |
| #if IMAGE_BYTE_ORDER == MSBFirst
 | |
| #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) & 0xf : Fetch8(l,o) >> 4)
 | |
| #else
 | |
| #define Fetch4(l,o)    ((o) & 2 ? Fetch8(l,o) >> 4 : Fetch8(l,o) & 0xf)
 | |
| #endif
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = Fetch4(bits, offset);
 | |
| 
 | |
|     pixel |= pixel << 4;
 | |
|     return pixel << 24;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_r1g2b1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = Fetch4(bits, offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     r = ((pixel & 0x8) * 0xff) << 13;
 | |
|     g = ((pixel & 0x6) * 0x55) << 7;
 | |
|     b = ((pixel & 0x1) * 0xff);
 | |
|     return 0xff000000|r|g|b;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_b1g2r1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = Fetch4(bits, offset);
 | |
|     CARD32  r,g,b;
 | |
| 
 | |
|     b = ((pixel & 0x8) * 0xff) >> 3;
 | |
|     g = ((pixel & 0x6) * 0x55) << 7;
 | |
|     r = ((pixel & 0x1) * 0xff) << 16;
 | |
|     return 0xff000000|r|g|b;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a1r1g1b1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = Fetch4(bits, offset);
 | |
|     CARD32  a,r,g,b;
 | |
| 
 | |
|     a = ((pixel & 0x8) * 0xff) << 21;
 | |
|     r = ((pixel & 0x4) * 0xff) << 14;
 | |
|     g = ((pixel & 0x2) * 0xff) << 7;
 | |
|     b = ((pixel & 0x1) * 0xff);
 | |
|     return a|r|g|b;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a1b1g1r1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = Fetch4(bits, offset);
 | |
|     CARD32  a,r,g,b;
 | |
| 
 | |
|     a = ((pixel & 0x8) * 0xff) << 21;
 | |
|     r = ((pixel & 0x4) * 0xff) >> 3;
 | |
|     g = ((pixel & 0x2) * 0xff) << 7;
 | |
|     b = ((pixel & 0x1) * 0xff) << 16;
 | |
|     return a|r|g|b;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_c4 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = Fetch4(bits, offset);
 | |
| 
 | |
|     return indexed->rgba[pixel];
 | |
| }
 | |
| 
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_a1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32  pixel = ((CARD32 *)bits)[offset >> 5];
 | |
|     CARD32  a;
 | |
| #if BITMAP_BIT_ORDER == MSBFirst
 | |
|     a = pixel >> (0x1f - (offset & 0x1f));
 | |
| #else
 | |
|     a = pixel >> (offset & 0x1f);
 | |
| #endif
 | |
|     a = a & 1;
 | |
|     a |= a << 1;
 | |
|     a |= a << 2;
 | |
|     a |= a << 4;
 | |
|     return a << 24;
 | |
| }
 | |
| 
 | |
| static FASTCALL CARD32
 | |
| fbFetchPixel_g1 (const FbBits *bits, int offset, miIndexedPtr indexed)
 | |
| {
 | |
|     CARD32 pixel = ((CARD32 *)bits)[offset >> 5];
 | |
|     CARD32 a;
 | |
| #if BITMAP_BIT_ORDER == MSBFirst
 | |
|     a = pixel >> (0x1f - (offset & 0x1f));
 | |
| #else
 | |
|     a = pixel >> (offset & 0x1f);
 | |
| #endif
 | |
|     a = a & 1;
 | |
|     return indexed->rgba[a];
 | |
| }
 | |
| 
 | |
| static fetchPixelProc fetchPixelProcForPicture (PicturePtr pict)
 | |
| {
 | |
|     switch(pict->format) {
 | |
|     case PICT_a8r8g8b8: return fbFetchPixel_a8r8g8b8;
 | |
|     case PICT_x8r8g8b8: return fbFetchPixel_x8r8g8b8;
 | |
|     case PICT_a8b8g8r8: return fbFetchPixel_a8b8g8r8;
 | |
|     case PICT_x8b8g8r8: return fbFetchPixel_x8b8g8r8;
 | |
| 
 | |
|         /* 24bpp formats */
 | |
|     case PICT_r8g8b8: return fbFetchPixel_r8g8b8;
 | |
|     case PICT_b8g8r8: return fbFetchPixel_b8g8r8;
 | |
| 
 | |
|         /* 16bpp formats */
 | |
|     case PICT_r5g6b5: return fbFetchPixel_r5g6b5;
 | |
|     case PICT_b5g6r5: return fbFetchPixel_b5g6r5;
 | |
| 
 | |
|     case PICT_a1r5g5b5: return fbFetchPixel_a1r5g5b5;
 | |
|     case PICT_x1r5g5b5: return fbFetchPixel_x1r5g5b5;
 | |
|     case PICT_a1b5g5r5: return fbFetchPixel_a1b5g5r5;
 | |
|     case PICT_x1b5g5r5: return fbFetchPixel_x1b5g5r5;
 | |
|     case PICT_a4r4g4b4: return fbFetchPixel_a4r4g4b4;
 | |
|     case PICT_x4r4g4b4: return fbFetchPixel_x4r4g4b4;
 | |
|     case PICT_a4b4g4r4: return fbFetchPixel_a4b4g4r4;
 | |
|     case PICT_x4b4g4r4: return fbFetchPixel_x4b4g4r4;
 | |
| 
 | |
|         /* 8bpp formats */
 | |
|     case PICT_a8: return  fbFetchPixel_a8;
 | |
|     case PICT_r3g3b2: return fbFetchPixel_r3g3b2;
 | |
|     case PICT_b2g3r3: return fbFetchPixel_b2g3r3;
 | |
|     case PICT_a2r2g2b2: return fbFetchPixel_a2r2g2b2;
 | |
|     case PICT_a2b2g2r2: return fbFetchPixel_a2b2g2r2;
 | |
|     case PICT_c8: return  fbFetchPixel_c8;
 | |
|     case PICT_g8: return  fbFetchPixel_c8;
 | |
|     case PICT_x4a4: return fbFetchPixel_x4a4;
 | |
| 
 | |
|         /* 4bpp formats */
 | |
|     case PICT_a4: return  fbFetchPixel_a4;
 | |
|     case PICT_r1g2b1: return fbFetchPixel_r1g2b1;
 | |
|     case PICT_b1g2r1: return fbFetchPixel_b1g2r1;
 | |
|     case PICT_a1r1g1b1: return fbFetchPixel_a1r1g1b1;
 | |
|     case PICT_a1b1g1r1: return fbFetchPixel_a1b1g1r1;
 | |
|     case PICT_c4: return  fbFetchPixel_c4;
 | |
|     case PICT_g4: return  fbFetchPixel_c4;
 | |
| 
 | |
|         /* 1bpp formats */
 | |
|     case PICT_a1: return  fbFetchPixel_a1;
 | |
|     case PICT_g1: return  fbFetchPixel_g1;
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * All the store functions
 | |
|  */
 | |
| 
 | |
| typedef FASTCALL void (*storeProc) (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed);
 | |
| 
 | |
| #define Splita(v)	CARD32	a = ((v) >> 24), r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff
 | |
| #define Split(v)	CARD32	r = ((v) >> 16) & 0xff, g = ((v) >> 8) & 0xff, b = (v) & 0xff
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a8r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     MEMCPY_WRAPPED(((CARD32 *)bits) + x, values, width*sizeof(CARD32));
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_x8r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD32 *pixel = (CARD32 *)bits + x;
 | |
|     for (i = 0; i < width; ++i)
 | |
|         WRITE(pixel++, READ(values + i) & 0xffffff);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD32 *pixel = (CARD32 *)bits + x;
 | |
|     for (i = 0; i < width; ++i)
 | |
|         WRITE(pixel++, (READ(values + i) & 0xff00ff00) | ((READ(values + i) >> 16) & 0xff) | ((READ(values + i) & 0xff) << 16));
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_x8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD32 *pixel = (CARD32 *)bits + x;
 | |
|     for (i = 0; i < width; ++i)
 | |
|         WRITE(pixel++, (READ(values + i) & 0x0000ff00) | ((READ(values + i) >> 16) & 0xff) | ((READ(values + i) & 0xff) << 16));
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_r8g8b8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8 *pixel = ((CARD8 *) bits) + 3*x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Store24(pixel, READ(values + i));
 | |
|         pixel += 3;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8 *pixel = ((CARD8 *) bits) + 3*x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 val = READ(values + i);
 | |
| #if IMAGE_BYTE_ORDER == MSBFirst
 | |
|         WRITE(pixel++, Blue(val));
 | |
|         WRITE(pixel++, Green(val));
 | |
|         WRITE(pixel++, Red(val));
 | |
| #else
 | |
|         WRITE(pixel++, Red(val));
 | |
|         WRITE(pixel++, Green(val));
 | |
|         WRITE(pixel++, Blue(val));
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_r5g6b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16 *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(values + i);
 | |
|         WRITE(pixel++, ((s >> 3) & 0x001f) |
 | |
| 	      ((s >> 5) & 0x07e0) |
 | |
| 	      ((s >> 8) & 0xf800));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_b5g6r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Split(READ(values + i));
 | |
|         WRITE(pixel++, ((b << 8) & 0xf800) |
 | |
| 	      ((g << 3) & 0x07e0) |
 | |
| 	      ((r >> 3)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a1r5g5b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Splita(READ(values + i));
 | |
|         WRITE(pixel++, ((a << 8) & 0x8000) |
 | |
| 	      ((r << 7) & 0x7c00) |
 | |
| 	      ((g << 2) & 0x03e0) |
 | |
| 	      ((b >> 3)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_x1r5g5b5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Split(READ(values + i));
 | |
|         WRITE(pixel++, ((r << 7) & 0x7c00) |
 | |
| 	      ((g << 2) & 0x03e0) |
 | |
| 	      ((b >> 3)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a1b5g5r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Splita(READ(values + i));
 | |
|         WRITE(pixel++, ((a << 8) & 0x8000) |
 | |
| 	      ((b << 7) & 0x7c00) |
 | |
| 	      ((g << 2) & 0x03e0) |
 | |
| 	      ((r >> 3)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_x1b5g5r5 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Split(READ(values + i));
 | |
|         WRITE(pixel++, ((b << 7) & 0x7c00) |
 | |
| 	      ((g << 2) & 0x03e0) |
 | |
| 	      ((r >> 3)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a4r4g4b4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Splita(READ(values + i));
 | |
|         WRITE(pixel++, ((a << 8) & 0xf000) |
 | |
| 	      ((r << 4) & 0x0f00) |
 | |
| 	      ((g     ) & 0x00f0) |
 | |
| 	      ((b >> 4)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_x4r4g4b4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Split(READ(values + i));
 | |
|         WRITE(pixel++, ((r << 4) & 0x0f00) |
 | |
| 	      ((g     ) & 0x00f0) |
 | |
| 	      ((b >> 4)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a4b4g4r4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Splita(READ(values + i));
 | |
|         WRITE(pixel++, ((a << 8) & 0xf000) |
 | |
| 	      ((b << 4) & 0x0f00) |
 | |
| 	      ((g     ) & 0x00f0) |
 | |
| 	      ((r >> 4)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_x4b4g4r4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD16  *pixel = ((CARD16 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Split(READ(values + i));
 | |
|         WRITE(pixel++, ((b << 4) & 0x0f00) |
 | |
| 	      ((g     ) & 0x00f0) |
 | |
| 	      ((r >> 4)         ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         WRITE(pixel++, READ(values + i) >> 24);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_r3g3b2 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Split(READ(values + i));
 | |
|         WRITE(pixel++, ((r     ) & 0xe0) |
 | |
| 	      ((g >> 3) & 0x1c) |
 | |
| 	      ((b >> 6)       ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_b2g3r3 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Split(READ(values + i));
 | |
|         WRITE(pixel++, ((b     ) & 0xe0) |
 | |
| 	      ((g >> 3) & 0x1c) |
 | |
| 	      ((r >> 6)       ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a2r2g2b2 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Splita(READ(values + i));
 | |
|         WRITE(pixel++, ((a     ) & 0xc0) |
 | |
| 	      ((r >> 2) & 0x30) |
 | |
| 	      ((g >> 4) & 0x0c) |
 | |
| 	      ((b >> 6)       ));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_c8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         WRITE(pixel++, miIndexToEnt24(indexed,READ(values + i)));
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_x4a4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     CARD8   *pixel = ((CARD8 *) bits) + x;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         WRITE(pixel++, READ(values + i) >> 28);
 | |
|     }
 | |
| }
 | |
| 
 | |
| #define Store8(l,o,v)  (((CARD8 *) l)[(o) >> 3] = (v))
 | |
| #if IMAGE_BYTE_ORDER == MSBFirst
 | |
| #define Store4(l,o,v)  Store8(l,o,((o) & 4 ?			\
 | |
| 				   (Fetch8(l,o) & 0xf0) | (v) :		\
 | |
| 				   (Fetch8(l,o) & 0x0f) | ((v) << 4)))
 | |
| #else
 | |
| #define Store4(l,o,v)  Store8(l,o,((o) & 4 ?			       \
 | |
| 				   (Fetch8(l,o) & 0x0f) | ((v) << 4) : \
 | |
| 				   (Fetch8(l,o) & 0xf0) | (v)))
 | |
| #endif
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         Store4(bits, i + x, READ(values + i)>>28);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_r1g2b1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  pixel;
 | |
| 
 | |
|         Split(READ(values + i));
 | |
|         pixel = (((r >> 4) & 0x8) |
 | |
|                  ((g >> 5) & 0x6) |
 | |
|                  ((b >> 7)      ));
 | |
|         Store4(bits, i + x, pixel);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_b1g2r1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  pixel;
 | |
| 
 | |
|         Split(READ(values + i));
 | |
|         pixel = (((b >> 4) & 0x8) |
 | |
|                  ((g >> 5) & 0x6) |
 | |
|                  ((r >> 7)      ));
 | |
|         Store4(bits, i + x, pixel);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a1r1g1b1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  pixel;
 | |
|         Splita(READ(values + i));
 | |
|         pixel = (((a >> 4) & 0x8) |
 | |
|                  ((r >> 5) & 0x4) |
 | |
|                  ((g >> 6) & 0x2) |
 | |
|                  ((b >> 7)      ));
 | |
|         Store4(bits, i + x, pixel);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a1b1g1r1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  pixel;
 | |
|         Splita(READ(values + i));
 | |
|         pixel = (((a >> 4) & 0x8) |
 | |
|                  ((b >> 5) & 0x4) |
 | |
|                  ((g >> 6) & 0x2) |
 | |
|                  ((r >> 7)      ));
 | |
|         Store4(bits, i + x, pixel);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_c4 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  pixel;
 | |
| 
 | |
|         pixel = miIndexToEnt24(indexed, READ(values + i));
 | |
|         Store4(bits, i + x, pixel);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_a1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  *pixel = ((CARD32 *) bits) + ((i+x) >> 5);
 | |
|         CARD32  mask = FbStipMask((i+x) & 0x1f, 1);
 | |
| 
 | |
|         CARD32 v = READ(values + i) & 0x80000000 ? mask : 0;
 | |
|         WRITE(pixel, (READ(pixel) & ~mask) | v);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbStore_g1 (FbBits *bits, const CARD32 *values, int x, int width, miIndexedPtr indexed)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  *pixel = ((CARD32 *) bits) + ((i+x) >> 5);
 | |
|         CARD32  mask = FbStipMask((i+x) & 0x1f, 1);
 | |
| 
 | |
|         CARD32 v = miIndexToEntY24(indexed,READ(values + i)) ? mask : 0;
 | |
|         WRITE(pixel, (READ(pixel) & ~mask) | v);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static storeProc storeProcForPicture (PicturePtr pict)
 | |
| {
 | |
|     switch(pict->format) {
 | |
|     case PICT_a8r8g8b8: return fbStore_a8r8g8b8;
 | |
|     case PICT_x8r8g8b8: return fbStore_x8r8g8b8;
 | |
|     case PICT_a8b8g8r8: return fbStore_a8b8g8r8;
 | |
|     case PICT_x8b8g8r8: return fbStore_x8b8g8r8;
 | |
| 
 | |
|         /* 24bpp formats */
 | |
|     case PICT_r8g8b8: return fbStore_r8g8b8;
 | |
|     case PICT_b8g8r8: return fbStore_b8g8r8;
 | |
| 
 | |
|         /* 16bpp formats */
 | |
|     case PICT_r5g6b5: return fbStore_r5g6b5;
 | |
|     case PICT_b5g6r5: return fbStore_b5g6r5;
 | |
| 
 | |
|     case PICT_a1r5g5b5: return fbStore_a1r5g5b5;
 | |
|     case PICT_x1r5g5b5: return fbStore_x1r5g5b5;
 | |
|     case PICT_a1b5g5r5: return fbStore_a1b5g5r5;
 | |
|     case PICT_x1b5g5r5: return fbStore_x1b5g5r5;
 | |
|     case PICT_a4r4g4b4: return fbStore_a4r4g4b4;
 | |
|     case PICT_x4r4g4b4: return fbStore_x4r4g4b4;
 | |
|     case PICT_a4b4g4r4: return fbStore_a4b4g4r4;
 | |
|     case PICT_x4b4g4r4: return fbStore_x4b4g4r4;
 | |
| 
 | |
|         /* 8bpp formats */
 | |
|     case PICT_a8: return  fbStore_a8;
 | |
|     case PICT_r3g3b2: return fbStore_r3g3b2;
 | |
|     case PICT_b2g3r3: return fbStore_b2g3r3;
 | |
|     case PICT_a2r2g2b2: return fbStore_a2r2g2b2;
 | |
|     case PICT_c8: return  fbStore_c8;
 | |
|     case PICT_g8: return  fbStore_c8;
 | |
|     case PICT_x4a4: return fbStore_x4a4;
 | |
| 
 | |
|         /* 4bpp formats */
 | |
|     case PICT_a4: return  fbStore_a4;
 | |
|     case PICT_r1g2b1: return fbStore_r1g2b1;
 | |
|     case PICT_b1g2r1: return fbStore_b1g2r1;
 | |
|     case PICT_a1r1g1b1: return fbStore_a1r1g1b1;
 | |
|     case PICT_a1b1g1r1: return fbStore_a1b1g1r1;
 | |
|     case PICT_c4: return  fbStore_c4;
 | |
|     case PICT_g4: return  fbStore_c4;
 | |
| 
 | |
|         /* 1bpp formats */
 | |
|     case PICT_a1: return  fbStore_a1;
 | |
|     case PICT_g1: return  fbStore_g1;
 | |
|     default:
 | |
|         return NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Combine src and mask
 | |
|  */
 | |
| static FASTCALL void
 | |
| fbCombineMaskU (CARD32 *src, const CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 a = READ(mask + i) >> 24;
 | |
|         CARD32 s = READ(src + i);
 | |
|         FbByteMul(s, a);
 | |
|         WRITE(src + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * All of the composing functions
 | |
|  */
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineClear (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     MEMSET_WRAPPED(dest, 0, width*sizeof(CARD32));
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineSrcU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     MEMCPY_WRAPPED(dest, src, width*sizeof(CARD32));
 | |
| }
 | |
| 
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOverU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 ia = Alpha(~s);
 | |
| 
 | |
|         FbByteMulAdd(d, ia, s);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOverReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 ia = Alpha(~READ(dest + i));
 | |
|         FbByteMulAdd(s, ia, d);
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineInU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 a = Alpha(READ(dest + i));
 | |
|         FbByteMul(s, a);
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineInReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 a = Alpha(READ(src + i));
 | |
|         FbByteMul(d, a);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOutU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 a = Alpha(~READ(dest + i));
 | |
|         FbByteMul(s, a);
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOutReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 a = Alpha(~READ(src + i));
 | |
|         FbByteMul(d, a);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineAtopU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 dest_a = Alpha(d);
 | |
|         CARD32 src_ia = Alpha(~s);
 | |
| 
 | |
|         FbByteAddMul(s, dest_a, d, src_ia);
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineAtopReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 src_a = Alpha(s);
 | |
|         CARD32 dest_ia = Alpha(~d);
 | |
| 
 | |
|         FbByteAddMul(s, dest_ia, d, src_a);
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineXorU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 src_ia = Alpha(~s);
 | |
|         CARD32 dest_ia = Alpha(~d);
 | |
| 
 | |
|         FbByteAddMul(s, dest_ia, d, src_ia);
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineAddU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         FbByteAdd(d, s);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineSaturateU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD16  sa, da;
 | |
| 
 | |
|         sa = s >> 24;
 | |
|         da = ~d >> 24;
 | |
|         if (sa > da)
 | |
|         {
 | |
|             sa = FbIntDiv(da, sa);
 | |
|             FbByteMul(s, sa);
 | |
|         }
 | |
|         FbByteAdd(d, s);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * All of the disjoint composing functions
 | |
| 
 | |
|  The four entries in the first column indicate what source contributions
 | |
|  come from each of the four areas of the picture -- areas covered by neither
 | |
|  A nor B, areas covered only by A, areas covered only by B and finally
 | |
|  areas covered by both A and B.
 | |
| 
 | |
|  Disjoint			Conjoint
 | |
|  Fa		Fb		Fa		Fb
 | |
|  (0,0,0,0)	0		0		0		0
 | |
|  (0,A,0,A)	1		0		1		0
 | |
|  (0,0,B,B)	0		1		0		1
 | |
|  (0,A,B,A)	1		min((1-a)/b,1)	1		max(1-a/b,0)
 | |
|  (0,A,B,B)	min((1-b)/a,1)	1		max(1-b/a,0)	1
 | |
|  (0,0,0,A)	max(1-(1-b)/a,0) 0		min(1,b/a)	0
 | |
|  (0,0,0,B)	0		max(1-(1-a)/b,0) 0		min(a/b,1)
 | |
|  (0,A,0,0)	min(1,(1-b)/a)	0		max(1-b/a,0)	0
 | |
|  (0,0,B,0)	0		min(1,(1-a)/b)	0		max(1-a/b,0)
 | |
|  (0,0,B,A)	max(1-(1-b)/a,0) min(1,(1-a)/b)	 min(1,b/a)	max(1-a/b,0)
 | |
|  (0,A,0,B)	min(1,(1-b)/a)	max(1-(1-a)/b,0) max(1-b/a,0)	min(1,a/b)
 | |
|  (0,A,B,0)	min(1,(1-b)/a)	min(1,(1-a)/b)	max(1-b/a,0)	max(1-a/b,0)
 | |
| 
 | |
| */
 | |
| 
 | |
| #define CombineAOut 1
 | |
| #define CombineAIn  2
 | |
| #define CombineBOut 4
 | |
| #define CombineBIn  8
 | |
| 
 | |
| #define CombineClear	0
 | |
| #define CombineA	(CombineAOut|CombineAIn)
 | |
| #define CombineB	(CombineBOut|CombineBIn)
 | |
| #define CombineAOver	(CombineAOut|CombineBOut|CombineAIn)
 | |
| #define CombineBOver	(CombineAOut|CombineBOut|CombineBIn)
 | |
| #define CombineAAtop	(CombineBOut|CombineAIn)
 | |
| #define CombineBAtop	(CombineAOut|CombineBIn)
 | |
| #define CombineXor	(CombineAOut|CombineBOut)
 | |
| 
 | |
| /* portion covered by a but not b */
 | |
| static INLINE CARD8
 | |
| fbCombineDisjointOutPart (CARD8 a, CARD8 b)
 | |
| {
 | |
|     /* min (1, (1-b) / a) */
 | |
| 
 | |
|     b = ~b;		    /* 1 - b */
 | |
|     if (b >= a)		    /* 1 - b >= a -> (1-b)/a >= 1 */
 | |
| 	return 0xff;	    /* 1 */
 | |
|     return FbIntDiv(b,a);   /* (1-b) / a */
 | |
| }
 | |
| 
 | |
| /* portion covered by both a and b */
 | |
| static INLINE CARD8
 | |
| fbCombineDisjointInPart (CARD8 a, CARD8 b)
 | |
| {
 | |
|     /* max (1-(1-b)/a,0) */
 | |
|     /*  = - min ((1-b)/a - 1, 0) */
 | |
|     /*  = 1 - min (1, (1-b)/a) */
 | |
| 
 | |
|     b = ~b;		    /* 1 - b */
 | |
|     if (b >= a)		    /* 1 - b >= a -> (1-b)/a >= 1 */
 | |
| 	return 0;	    /* 1 - 1 */
 | |
|     return ~FbIntDiv(b,a);  /* 1 - (1-b) / a */
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointGeneralU (CARD32 *dest, const CARD32 *src, int width, CARD8 combine)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 m,n,o,p;
 | |
|         CARD16 Fa, Fb, t, u, v;
 | |
|         CARD8 sa = s >> 24;
 | |
|         CARD8 da = d >> 24;
 | |
| 
 | |
|         switch (combine & CombineA) {
 | |
|         default:
 | |
|             Fa = 0;
 | |
|             break;
 | |
|         case CombineAOut:
 | |
|             Fa = fbCombineDisjointOutPart (sa, da);
 | |
|             break;
 | |
|         case CombineAIn:
 | |
|             Fa = fbCombineDisjointInPart (sa, da);
 | |
|             break;
 | |
|         case CombineA:
 | |
|             Fa = 0xff;
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         switch (combine & CombineB) {
 | |
|         default:
 | |
|             Fb = 0;
 | |
|             break;
 | |
|         case CombineBOut:
 | |
|             Fb = fbCombineDisjointOutPart (da, sa);
 | |
|             break;
 | |
|         case CombineBIn:
 | |
|             Fb = fbCombineDisjointInPart (da, sa);
 | |
|             break;
 | |
|         case CombineB:
 | |
|             Fb = 0xff;
 | |
|             break;
 | |
|         }
 | |
|         m = FbGen (s,d,0,Fa,Fb,t, u, v);
 | |
|         n = FbGen (s,d,8,Fa,Fb,t, u, v);
 | |
|         o = FbGen (s,d,16,Fa,Fb,t, u, v);
 | |
|         p = FbGen (s,d,24,Fa,Fb,t, u, v);
 | |
|         s = m|n|o|p;
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointOverU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  s = READ(src + i);
 | |
|         CARD16  a = s >> 24;
 | |
| 
 | |
|         if (a != 0x00)
 | |
|         {
 | |
|             if (a != 0xff)
 | |
|             {
 | |
|                 CARD32 d = READ(dest + i);
 | |
|                 a = fbCombineDisjointOutPart (d >> 24, a);
 | |
|                 FbByteMulAdd(d, a, s);
 | |
|                 s = d;
 | |
|             }
 | |
|             WRITE(dest + i, s);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointInU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralU (dest, src, width, CombineAIn);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointInReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralU (dest, src, width, CombineBIn);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointOutU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralU (dest, src, width, CombineAOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointOutReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralU (dest, src, width, CombineBOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointAtopU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralU (dest, src, width, CombineAAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointAtopReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralU (dest, src, width, CombineBAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointXorU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralU (dest, src, width, CombineXor);
 | |
| }
 | |
| 
 | |
| /* portion covered by a but not b */
 | |
| static INLINE CARD8
 | |
| fbCombineConjointOutPart (CARD8 a, CARD8 b)
 | |
| {
 | |
|     /* max (1-b/a,0) */
 | |
|     /* = 1-min(b/a,1) */
 | |
| 
 | |
|     /* min (1, (1-b) / a) */
 | |
| 
 | |
|     if (b >= a)		    /* b >= a -> b/a >= 1 */
 | |
| 	return 0x00;	    /* 0 */
 | |
|     return ~FbIntDiv(b,a);   /* 1 - b/a */
 | |
| }
 | |
| 
 | |
| /* portion covered by both a and b */
 | |
| static INLINE CARD8
 | |
| fbCombineConjointInPart (CARD8 a, CARD8 b)
 | |
| {
 | |
|     /* min (1,b/a) */
 | |
| 
 | |
|     if (b >= a)		    /* b >= a -> b/a >= 1 */
 | |
| 	return 0xff;	    /* 1 */
 | |
|     return FbIntDiv(b,a);   /* b/a */
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointGeneralU (CARD32 *dest, const CARD32 *src, int width, CARD8 combine)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  s = READ(src + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32  m,n,o,p;
 | |
|         CARD16  Fa, Fb, t, u, v;
 | |
|         CARD8 sa = s >> 24;
 | |
|         CARD8 da = d >> 24;
 | |
| 
 | |
|         switch (combine & CombineA) {
 | |
|         default:
 | |
|             Fa = 0;
 | |
|             break;
 | |
|         case CombineAOut:
 | |
|             Fa = fbCombineConjointOutPart (sa, da);
 | |
|             break;
 | |
|         case CombineAIn:
 | |
|             Fa = fbCombineConjointInPart (sa, da);
 | |
|             break;
 | |
|         case CombineA:
 | |
|             Fa = 0xff;
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         switch (combine & CombineB) {
 | |
|         default:
 | |
|             Fb = 0;
 | |
|             break;
 | |
|         case CombineBOut:
 | |
|             Fb = fbCombineConjointOutPart (da, sa);
 | |
|             break;
 | |
|         case CombineBIn:
 | |
|             Fb = fbCombineConjointInPart (da, sa);
 | |
|             break;
 | |
|         case CombineB:
 | |
|             Fb = 0xff;
 | |
|             break;
 | |
|         }
 | |
|         m = FbGen (s,d,0,Fa,Fb,t, u, v);
 | |
|         n = FbGen (s,d,8,Fa,Fb,t, u, v);
 | |
|         o = FbGen (s,d,16,Fa,Fb,t, u, v);
 | |
|         p = FbGen (s,d,24,Fa,Fb,t, u, v);
 | |
|         s = m|n|o|p;
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOverU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineAOver);
 | |
| }
 | |
| 
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOverReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineBOver);
 | |
| }
 | |
| 
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointInU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineAIn);
 | |
| }
 | |
| 
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointInReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineBIn);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOutU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineAOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOutReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineBOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointAtopU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineAAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointAtopReverseU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineBAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointXorU (CARD32 *dest, const CARD32 *src, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralU (dest, src, width, CombineXor);
 | |
| }
 | |
| 
 | |
| static CombineFuncU fbCombineFuncU[] = {
 | |
|     fbCombineClear,
 | |
|     fbCombineSrcU,
 | |
|     NULL, /* CombineDst */
 | |
|     fbCombineOverU,
 | |
|     fbCombineOverReverseU,
 | |
|     fbCombineInU,
 | |
|     fbCombineInReverseU,
 | |
|     fbCombineOutU,
 | |
|     fbCombineOutReverseU,
 | |
|     fbCombineAtopU,
 | |
|     fbCombineAtopReverseU,
 | |
|     fbCombineXorU,
 | |
|     fbCombineAddU,
 | |
|     fbCombineSaturateU,
 | |
|     NULL,
 | |
|     NULL,
 | |
|     fbCombineClear,
 | |
|     fbCombineSrcU,
 | |
|     NULL, /* CombineDst */
 | |
|     fbCombineDisjointOverU,
 | |
|     fbCombineSaturateU, /* DisjointOverReverse */
 | |
|     fbCombineDisjointInU,
 | |
|     fbCombineDisjointInReverseU,
 | |
|     fbCombineDisjointOutU,
 | |
|     fbCombineDisjointOutReverseU,
 | |
|     fbCombineDisjointAtopU,
 | |
|     fbCombineDisjointAtopReverseU,
 | |
|     fbCombineDisjointXorU,
 | |
|     NULL,
 | |
|     NULL,
 | |
|     NULL,
 | |
|     NULL,
 | |
|     fbCombineClear,
 | |
|     fbCombineSrcU,
 | |
|     NULL, /* CombineDst */
 | |
|     fbCombineConjointOverU,
 | |
|     fbCombineConjointOverReverseU,
 | |
|     fbCombineConjointInU,
 | |
|     fbCombineConjointInReverseU,
 | |
|     fbCombineConjointOutU,
 | |
|     fbCombineConjointOutReverseU,
 | |
|     fbCombineConjointAtopU,
 | |
|     fbCombineConjointAtopReverseU,
 | |
|     fbCombineConjointXorU,
 | |
| };
 | |
| 
 | |
| static INLINE void
 | |
| fbCombineMaskC (CARD32 *src, CARD32 *mask)
 | |
| {
 | |
|     CARD32 a = *mask;
 | |
| 
 | |
|     CARD32	x;
 | |
|     CARD16	xa;
 | |
| 
 | |
|     if (!a)
 | |
|     {
 | |
| 	WRITE(src, 0);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     x = READ(src);
 | |
|     if (a == 0xffffffff)
 | |
|     {
 | |
| 	x = x >> 24;
 | |
| 	x |= x << 8;
 | |
| 	x |= x << 16;
 | |
| 	WRITE(mask, x);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     xa = x >> 24;
 | |
|     FbByteMulC(x, a);
 | |
|     WRITE(src, x);
 | |
|     FbByteMul(a, xa);
 | |
|     WRITE(mask, a);
 | |
| }
 | |
| 
 | |
| static INLINE void
 | |
| fbCombineMaskValueC (CARD32 *src, const CARD32 *mask)
 | |
| {
 | |
|     CARD32 a = READ(mask);
 | |
|     CARD32	x;
 | |
| 
 | |
|     if (!a)
 | |
|     {
 | |
| 	WRITE(src, 0);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     if (a == 0xffffffff)
 | |
| 	return;
 | |
| 
 | |
|     x = READ(src);
 | |
|     FbByteMulC(x, a);
 | |
|     WRITE(src,x);
 | |
| }
 | |
| 
 | |
| static INLINE void
 | |
| fbCombineMaskAlphaC (const CARD32 *src, CARD32 *mask)
 | |
| {
 | |
|     CARD32 a = READ(mask);
 | |
|     CARD32	x;
 | |
| 
 | |
|     if (!a)
 | |
| 	return;
 | |
| 
 | |
|     x = READ(src) >> 24;
 | |
|     if (x == 0xff)
 | |
| 	return;
 | |
|     if (a == 0xffffffff)
 | |
|     {
 | |
| 	x = x >> 24;
 | |
| 	x |= x << 8;
 | |
| 	x |= x << 16;
 | |
| 	WRITE(mask, x);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     FbByteMul(a, x);
 | |
|     WRITE(mask, a);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineClearC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     MEMSET_WRAPPED(dest, 0, width*sizeof(CARD32));
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineSrcC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
| 	CARD32 s = READ(src + i);
 | |
| 	CARD32 m = READ(mask + i);
 | |
| 
 | |
| 	fbCombineMaskValueC (&s, &m);
 | |
| 
 | |
| 	WRITE(dest, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
| 	CARD32 s = READ(src + i);
 | |
| 	CARD32 m = READ(mask + i);
 | |
| 	CARD32 a;
 | |
| 
 | |
| 	fbCombineMaskC (&s, &m);
 | |
| 
 | |
| 	a = ~m;
 | |
|         if (a != 0xffffffff)
 | |
|         {
 | |
|             if (a)
 | |
|             {
 | |
|                 CARD32 d = READ(dest + i);
 | |
|                 FbByteMulAddC(d, a, s);
 | |
|                 s = d;
 | |
|             }
 | |
|             WRITE(dest + i, s);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 a = ~d >> 24;
 | |
| 
 | |
|         if (a)
 | |
|         {
 | |
|             CARD32 s = READ(src + i);
 | |
| 	    CARD32 m = READ(mask + i);
 | |
| 
 | |
| 	    fbCombineMaskValueC (&s, &m);
 | |
| 
 | |
|             if (a != 0xff)
 | |
|             {
 | |
|                 FbByteMulAdd(s, a, d);
 | |
|             }
 | |
|             WRITE(dest + i, s);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD16 a = d >> 24;
 | |
|         CARD32 s = 0;
 | |
|         if (a)
 | |
|         {
 | |
| 	    CARD32 m = READ(mask + i);
 | |
| 
 | |
| 	    s = READ(src + i);
 | |
| 	    fbCombineMaskValueC (&s, &m);
 | |
|             if (a != 0xff)
 | |
|             {
 | |
|                 FbByteMul(s, a);
 | |
|             }
 | |
|         }
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 m = READ(mask + i);
 | |
|         CARD32 a;
 | |
| 
 | |
| 	fbCombineMaskAlphaC (&s, &m);
 | |
| 
 | |
| 	a = m;
 | |
|         if (a != 0xffffffff)
 | |
|         {
 | |
|             CARD32 d = 0;
 | |
|             if (a)
 | |
|             {
 | |
|                 d = READ(dest + i);
 | |
|                 FbByteMulC(d, a);
 | |
|             }
 | |
|             WRITE(dest + i, d); 
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD16 a = ~d >> 24;
 | |
|         CARD32 s = 0;
 | |
|         if (a)
 | |
|         {
 | |
| 	    CARD32 m = READ(mask + i);
 | |
| 
 | |
| 	    s = READ(src + i);
 | |
| 	    fbCombineMaskValueC (&s, &m);
 | |
| 
 | |
|             if (a != 0xff)
 | |
|             {
 | |
|                 FbByteMul(s, a);
 | |
|             }
 | |
|         }
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
| 	CARD32 s = READ(src + i);
 | |
| 	CARD32 m = READ(mask + i);
 | |
| 	CARD32 a;
 | |
| 
 | |
| 	fbCombineMaskAlphaC (&s, &m);
 | |
| 
 | |
|         a = ~m;
 | |
|         if (a != 0xffffffff)
 | |
|         {
 | |
|             CARD32 d = 0;
 | |
|             if (a)
 | |
|             {
 | |
|                 d = READ(dest + i);
 | |
|                 FbByteMulC(d, a);
 | |
|             }
 | |
|             WRITE(dest + i, d);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 m = READ(mask + i);
 | |
|         CARD32 ad;
 | |
|         CARD16 as = d >> 24;
 | |
| 
 | |
| 	fbCombineMaskC (&s, &m);
 | |
| 
 | |
|         ad = ~m;
 | |
| 
 | |
|         FbByteAddMulC(d, ad, s, as);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
| 
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 m = READ(mask + i);
 | |
|         CARD32 ad;
 | |
|         CARD16 as = ~d >> 24;
 | |
| 
 | |
| 	fbCombineMaskC (&s, &m);
 | |
| 
 | |
| 	ad = m;
 | |
| 
 | |
|         FbByteAddMulC(d, ad, s, as);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 d = READ(dest + i);
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 m = READ(mask + i);
 | |
|         CARD32 ad;
 | |
|         CARD16 as = ~d >> 24;
 | |
| 
 | |
| 	fbCombineMaskC (&s, &m);
 | |
| 
 | |
| 	ad = ~m;
 | |
| 
 | |
|         FbByteAddMulC(d, ad, s, as);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineAddC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32 s = READ(src + i);
 | |
|         CARD32 m = READ(mask + i);
 | |
|         CARD32 d = READ(dest + i);
 | |
| 
 | |
| 	fbCombineMaskValueC (&s, &m);
 | |
| 
 | |
|         FbByteAdd(d, s);
 | |
|         WRITE(dest + i, d);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineSaturateC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  s, d;
 | |
|         CARD16  sa, sr, sg, sb, da;
 | |
|         CARD16  t, u, v;
 | |
|         CARD32  m,n,o,p;
 | |
| 
 | |
|         d = READ(dest + i);
 | |
|         s = READ(src + i);
 | |
| 	m = READ(mask + i);
 | |
| 
 | |
| 	fbCombineMaskC (&s, &m);
 | |
| 
 | |
|         sa = (m >> 24);
 | |
|         sr = (m >> 16) & 0xff;
 | |
|         sg = (m >>  8) & 0xff;
 | |
|         sb = (m      ) & 0xff;
 | |
|         da = ~d >> 24;
 | |
| 
 | |
|         if (sb <= da)
 | |
|             m = FbAdd(s,d,0,t);
 | |
|         else
 | |
|             m = FbGen (s, d, 0, (da << 8) / sb, 0xff, t, u, v);
 | |
| 
 | |
|         if (sg <= da)
 | |
|             n = FbAdd(s,d,8,t);
 | |
|         else
 | |
|             n = FbGen (s, d, 8, (da << 8) / sg, 0xff, t, u, v);
 | |
| 
 | |
|         if (sr <= da)
 | |
|             o = FbAdd(s,d,16,t);
 | |
|         else
 | |
|             o = FbGen (s, d, 16, (da << 8) / sr, 0xff, t, u, v);
 | |
| 
 | |
|         if (sa <= da)
 | |
|             p = FbAdd(s,d,24,t);
 | |
|         else
 | |
|             p = FbGen (s, d, 24, (da << 8) / sa, 0xff, t, u, v);
 | |
| 
 | |
|         WRITE(dest + i, m|n|o|p);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  s, d;
 | |
|         CARD32  m,n,o,p;
 | |
|         CARD32  Fa, Fb;
 | |
|         CARD16  t, u, v;
 | |
|         CARD32  sa;
 | |
|         CARD8   da;
 | |
| 
 | |
|         s = READ(src + i);
 | |
|         m = READ(mask + i);
 | |
|         d = READ(dest + i);
 | |
|         da = d >> 24;
 | |
| 
 | |
| 	fbCombineMaskC (&s, &m);
 | |
| 
 | |
| 	sa = m;
 | |
| 
 | |
|         switch (combine & CombineA) {
 | |
|         default:
 | |
|             Fa = 0;
 | |
|             break;
 | |
|         case CombineAOut:
 | |
|             m = fbCombineDisjointOutPart ((CARD8) (sa >> 0), da);
 | |
|             n = fbCombineDisjointOutPart ((CARD8) (sa >> 8), da) << 8;
 | |
|             o = fbCombineDisjointOutPart ((CARD8) (sa >> 16), da) << 16;
 | |
|             p = fbCombineDisjointOutPart ((CARD8) (sa >> 24), da) << 24;
 | |
|             Fa = m|n|o|p;
 | |
|             break;
 | |
|         case CombineAIn:
 | |
|             m = fbCombineDisjointInPart ((CARD8) (sa >> 0), da);
 | |
|             n = fbCombineDisjointInPart ((CARD8) (sa >> 8), da) << 8;
 | |
|             o = fbCombineDisjointInPart ((CARD8) (sa >> 16), da) << 16;
 | |
|             p = fbCombineDisjointInPart ((CARD8) (sa >> 24), da) << 24;
 | |
|             Fa = m|n|o|p;
 | |
|             break;
 | |
|         case CombineA:
 | |
|             Fa = 0xffffffff;
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         switch (combine & CombineB) {
 | |
|         default:
 | |
|             Fb = 0;
 | |
|             break;
 | |
|         case CombineBOut:
 | |
|             m = fbCombineDisjointOutPart (da, (CARD8) (sa >> 0));
 | |
|             n = fbCombineDisjointOutPart (da, (CARD8) (sa >> 8)) << 8;
 | |
|             o = fbCombineDisjointOutPart (da, (CARD8) (sa >> 16)) << 16;
 | |
|             p = fbCombineDisjointOutPart (da, (CARD8) (sa >> 24)) << 24;
 | |
|             Fb = m|n|o|p;
 | |
|             break;
 | |
|         case CombineBIn:
 | |
|             m = fbCombineDisjointInPart (da, (CARD8) (sa >> 0));
 | |
|             n = fbCombineDisjointInPart (da, (CARD8) (sa >> 8)) << 8;
 | |
|             o = fbCombineDisjointInPart (da, (CARD8) (sa >> 16)) << 16;
 | |
|             p = fbCombineDisjointInPart (da, (CARD8) (sa >> 24)) << 24;
 | |
|             Fb = m|n|o|p;
 | |
|             break;
 | |
|         case CombineB:
 | |
|             Fb = 0xffffffff;
 | |
|             break;
 | |
|         }
 | |
|         m = FbGen (s,d,0,FbGet8(Fa,0),FbGet8(Fb,0),t, u, v);
 | |
|         n = FbGen (s,d,8,FbGet8(Fa,8),FbGet8(Fb,8),t, u, v);
 | |
|         o = FbGen (s,d,16,FbGet8(Fa,16),FbGet8(Fb,16),t, u, v);
 | |
|         p = FbGen (s,d,24,FbGet8(Fa,24),FbGet8(Fb,24),t, u, v);
 | |
|         s = m|n|o|p;
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAOver);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAIn);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineBIn);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineBOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineAAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineBAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineDisjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineDisjointGeneralC (dest, src, mask, width, CombineXor);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointGeneralC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width, CARD8 combine)
 | |
| {
 | |
|     int i;
 | |
| 
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         CARD32  s, d;
 | |
|         CARD32  m,n,o,p;
 | |
|         CARD32  Fa, Fb;
 | |
|         CARD16  t, u, v;
 | |
|         CARD32  sa;
 | |
|         CARD8   da;
 | |
| 
 | |
|         s = READ(src + i);
 | |
|         m = READ(mask + i);
 | |
|         d = READ(dest + i);
 | |
|         da = d >> 24;
 | |
| 
 | |
| 	fbCombineMaskC (&s, &m);
 | |
| 
 | |
|         sa = m;
 | |
| 
 | |
|         switch (combine & CombineA) {
 | |
|         default:
 | |
|             Fa = 0;
 | |
|             break;
 | |
|         case CombineAOut:
 | |
|             m = fbCombineConjointOutPart ((CARD8) (sa >> 0), da);
 | |
|             n = fbCombineConjointOutPart ((CARD8) (sa >> 8), da) << 8;
 | |
|             o = fbCombineConjointOutPart ((CARD8) (sa >> 16), da) << 16;
 | |
|             p = fbCombineConjointOutPart ((CARD8) (sa >> 24), da) << 24;
 | |
|             Fa = m|n|o|p;
 | |
|             break;
 | |
|         case CombineAIn:
 | |
|             m = fbCombineConjointInPart ((CARD8) (sa >> 0), da);
 | |
|             n = fbCombineConjointInPart ((CARD8) (sa >> 8), da) << 8;
 | |
|             o = fbCombineConjointInPart ((CARD8) (sa >> 16), da) << 16;
 | |
|             p = fbCombineConjointInPart ((CARD8) (sa >> 24), da) << 24;
 | |
|             Fa = m|n|o|p;
 | |
|             break;
 | |
|         case CombineA:
 | |
|             Fa = 0xffffffff;
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         switch (combine & CombineB) {
 | |
|         default:
 | |
|             Fb = 0;
 | |
|             break;
 | |
|         case CombineBOut:
 | |
|             m = fbCombineConjointOutPart (da, (CARD8) (sa >> 0));
 | |
|             n = fbCombineConjointOutPart (da, (CARD8) (sa >> 8)) << 8;
 | |
|             o = fbCombineConjointOutPart (da, (CARD8) (sa >> 16)) << 16;
 | |
|             p = fbCombineConjointOutPart (da, (CARD8) (sa >> 24)) << 24;
 | |
|             Fb = m|n|o|p;
 | |
|             break;
 | |
|         case CombineBIn:
 | |
|             m = fbCombineConjointInPart (da, (CARD8) (sa >> 0));
 | |
|             n = fbCombineConjointInPart (da, (CARD8) (sa >> 8)) << 8;
 | |
|             o = fbCombineConjointInPart (da, (CARD8) (sa >> 16)) << 16;
 | |
|             p = fbCombineConjointInPart (da, (CARD8) (sa >> 24)) << 24;
 | |
|             Fb = m|n|o|p;
 | |
|             break;
 | |
|         case CombineB:
 | |
|             Fb = 0xffffffff;
 | |
|             break;
 | |
|         }
 | |
|         m = FbGen (s,d,0,FbGet8(Fa,0),FbGet8(Fb,0),t, u, v);
 | |
|         n = FbGen (s,d,8,FbGet8(Fa,8),FbGet8(Fb,8),t, u, v);
 | |
|         o = FbGen (s,d,16,FbGet8(Fa,16),FbGet8(Fb,16),t, u, v);
 | |
|         p = FbGen (s,d,24,FbGet8(Fa,24),FbGet8(Fb,24),t, u, v);
 | |
|         s = m|n|o|p;
 | |
|         WRITE(dest + i, s);
 | |
|     }
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOverC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineAOver);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOverReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineBOver);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointInC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineAIn);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointInReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineBIn);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOutC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineAOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointOutReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineBOut);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointAtopC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineAAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointAtopReverseC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineBAtop);
 | |
| }
 | |
| 
 | |
| static FASTCALL void
 | |
| fbCombineConjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width)
 | |
| {
 | |
|     fbCombineConjointGeneralC (dest, src, mask, width, CombineXor);
 | |
| }
 | |
| 
 | |
| static CombineFuncC fbCombineFuncC[] = {
 | |
|     fbCombineClearC,
 | |
|     fbCombineSrcC,
 | |
|     NULL, /* Dest */
 | |
|     fbCombineOverC,
 | |
|     fbCombineOverReverseC,
 | |
|     fbCombineInC,
 | |
|     fbCombineInReverseC,
 | |
|     fbCombineOutC,
 | |
|     fbCombineOutReverseC,
 | |
|     fbCombineAtopC,
 | |
|     fbCombineAtopReverseC,
 | |
|     fbCombineXorC,
 | |
|     fbCombineAddC,
 | |
|     fbCombineSaturateC,
 | |
|     NULL,
 | |
|     NULL,
 | |
|     fbCombineClearC,	    /* 0x10 */
 | |
|     fbCombineSrcC,
 | |
|     NULL, /* Dest */
 | |
|     fbCombineDisjointOverC,
 | |
|     fbCombineSaturateC, /* DisjointOverReverse */
 | |
|     fbCombineDisjointInC,
 | |
|     fbCombineDisjointInReverseC,
 | |
|     fbCombineDisjointOutC,
 | |
|     fbCombineDisjointOutReverseC,
 | |
|     fbCombineDisjointAtopC,
 | |
|     fbCombineDisjointAtopReverseC,
 | |
|     fbCombineDisjointXorC,  /* 0x1b */
 | |
|     NULL,
 | |
|     NULL,
 | |
|     NULL,
 | |
|     NULL,
 | |
|     fbCombineClearC,
 | |
|     fbCombineSrcC,
 | |
|     NULL, /* Dest */
 | |
|     fbCombineConjointOverC,
 | |
|     fbCombineConjointOverReverseC,
 | |
|     fbCombineConjointInC,
 | |
|     fbCombineConjointInReverseC,
 | |
|     fbCombineConjointOutC,
 | |
|     fbCombineConjointOutReverseC,
 | |
|     fbCombineConjointAtopC,
 | |
|     fbCombineConjointAtopReverseC,
 | |
|     fbCombineConjointXorC,
 | |
| };
 | |
| 
 | |
| 
 | |
| FbComposeFunctions composeFunctions = {
 | |
|     fbCombineFuncU,
 | |
|     fbCombineFuncC,
 | |
|     fbCombineMaskU
 | |
| };
 | |
| 
 | |
| 
 | |
| static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 | |
| {
 | |
|     FbBits *bits;
 | |
|     FbStride stride;
 | |
|     int bpp;
 | |
|     int xoff, yoff;
 | |
|     CARD32 color;
 | |
|     CARD32 *end;
 | |
|     fetchPixelProc fetch = fetchPixelProcForPicture(pict);
 | |
|     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
 | |
| 
 | |
|     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
 | |
|     bits += yoff*stride + (xoff*bpp >> FB_SHIFT);
 | |
| 
 | |
|     color = fetch(bits, 0, indexed);
 | |
| 
 | |
|     end = buffer + width;
 | |
|     while (buffer < end)
 | |
|         WRITE(buffer++, color);
 | |
|     fbFinishAccess (pict->pDrawable);
 | |
| }
 | |
| 
 | |
| static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 | |
| {
 | |
|     FbBits *bits;
 | |
|     FbStride stride;
 | |
|     int bpp;
 | |
|     int xoff, yoff;
 | |
|     fetchProc fetch = fetchProcForPicture(pict);
 | |
|     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
 | |
| 
 | |
|     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
 | |
|     x += xoff;
 | |
|     y += yoff;
 | |
| 
 | |
|     bits += y*stride;
 | |
| 
 | |
|     fetch(bits, x, width, buffer, indexed);
 | |
|     fbFinishAccess (pict->pDrawable);
 | |
| }
 | |
| 
 | |
| #define MOD(a,b) ((a) < 0 ? ((b) - ((-(a) - 1) % (b))) - 1 : (a) % (b))
 | |
| #define DIV(a,b) ((((a) < 0) == ((b) < 0)) ? (a) / (b) :		\
 | |
| 		  ((a) - (b) + 1 - (((b) < 0) << 1)) / (b))
 | |
| 
 | |
| typedef struct
 | |
| {
 | |
|     CARD32        left_ag;
 | |
|     CARD32        left_rb;
 | |
|     CARD32        right_ag;
 | |
|     CARD32        right_rb;
 | |
|     int32_t       left_x;
 | |
|     int32_t       right_x;
 | |
|     int32_t       stepper;
 | |
|     
 | |
|     PictGradientStopPtr      stops;
 | |
|     int                      num_stops;
 | |
|     unsigned int             spread;
 | |
| 
 | |
|     int		  need_reset;
 | |
| } GradientWalker;
 | |
| 
 | |
| static void
 | |
| _gradient_walker_init (GradientWalker  *walker,
 | |
| 		       SourcePictPtr    pGradient,
 | |
| 		       unsigned int     spread)
 | |
| {
 | |
|     walker->num_stops = pGradient->gradient.nstops;
 | |
|     walker->stops     = pGradient->gradient.stops;
 | |
|     walker->left_x    = 0;
 | |
|     walker->right_x   = 0x10000;
 | |
|     walker->stepper   = 0;
 | |
|     walker->left_ag   = 0;
 | |
|     walker->left_rb   = 0;
 | |
|     walker->right_ag  = 0;
 | |
|     walker->right_rb  = 0;
 | |
|     walker->spread    = spread;
 | |
| 
 | |
|     walker->need_reset = TRUE;
 | |
| }
 | |
| 
 | |
| static void
 | |
| _gradient_walker_reset (GradientWalker  *walker,
 | |
|                         xFixed_32_32     pos)
 | |
| {
 | |
|     int32_t                  x, left_x, right_x;
 | |
|     xRenderColor          *left_c, *right_c;
 | |
|     int                      n, count = walker->num_stops;
 | |
|     PictGradientStopPtr      stops = walker->stops;
 | |
|     
 | |
|     static const xRenderColor   transparent_black = { 0, 0, 0, 0 };
 | |
|     
 | |
|     switch (walker->spread)
 | |
|     {
 | |
|     case RepeatNormal:
 | |
| 	x = (int32_t)pos & 0xFFFF;
 | |
| 	for (n = 0; n < count; n++)
 | |
| 	    if (x < stops[n].x)
 | |
| 		break;
 | |
| 	if (n == 0) {
 | |
| 	    left_x =  stops[count-1].x - 0x10000;
 | |
| 	    left_c = &stops[count-1].color;
 | |
| 	} else {
 | |
| 	    left_x =  stops[n-1].x;
 | |
| 	    left_c = &stops[n-1].color;
 | |
| 	}
 | |
| 	
 | |
| 	if (n == count) {
 | |
| 	    right_x =  stops[0].x + 0x10000;
 | |
| 	    right_c = &stops[0].color;
 | |
| 	} else {
 | |
| 	    right_x =  stops[n].x;
 | |
| 	    right_c = &stops[n].color;
 | |
| 	}
 | |
| 	left_x  += (pos - x);
 | |
| 	right_x += (pos - x);
 | |
| 	break;
 | |
| 	
 | |
|     case RepeatPad:
 | |
| 	for (n = 0; n < count; n++)
 | |
| 	    if (pos < stops[n].x)
 | |
| 		break;
 | |
| 	
 | |
| 	if (n == 0) {
 | |
| 	    left_x =  INT_MIN;
 | |
| 	    left_c = &stops[0].color;
 | |
| 	} else {
 | |
| 	    left_x =  stops[n-1].x;
 | |
| 	    left_c = &stops[n-1].color;
 | |
| 	}
 | |
| 	
 | |
| 	if (n == count) {
 | |
| 	    right_x =  INT_MAX;
 | |
| 	    right_c = &stops[n-1].color;
 | |
| 	} else {
 | |
| 	    right_x =  stops[n].x;
 | |
| 	    right_c = &stops[n].color;
 | |
| 	}
 | |
| 	break;
 | |
| 	
 | |
|     case RepeatReflect:
 | |
| 	x = (int32_t)pos & 0xFFFF;
 | |
| 	if ((int32_t)pos & 0x10000)
 | |
| 	    x = 0x10000 - x;
 | |
| 	for (n = 0; n < count; n++)
 | |
| 	    if (x < stops[n].x)
 | |
| 		break;
 | |
| 	
 | |
| 	if (n == 0) {
 | |
| 	    left_x =  -stops[0].x;
 | |
| 	    left_c = &stops[0].color;
 | |
| 	} else {
 | |
| 	    left_x =  stops[n-1].x;
 | |
| 	    left_c = &stops[n-1].color;
 | |
| 	}
 | |
| 	
 | |
| 	if (n == count) {
 | |
| 	    right_x = 0x20000 - stops[n-1].x;
 | |
| 	    right_c = &stops[n-1].color;
 | |
| 	} else {
 | |
| 	    right_x =  stops[n].x;
 | |
| 	    right_c = &stops[n].color;
 | |
| 	}
 | |
| 	
 | |
| 	if ((int32_t)pos & 0x10000) {
 | |
| 	    xRenderColor  *tmp_c;
 | |
| 	    int32_t          tmp_x;
 | |
| 	    
 | |
| 	    tmp_x   = 0x10000 - right_x;
 | |
| 	    right_x = 0x10000 - left_x;
 | |
| 	    left_x  = tmp_x;
 | |
| 	    
 | |
| 	    tmp_c   = right_c;
 | |
| 	    right_c = left_c;
 | |
| 	    left_c  = tmp_c;
 | |
| 
 | |
| 	    x = 0x10000 - x;
 | |
| 	}
 | |
| 	left_x  += (pos - x);
 | |
| 	right_x += (pos - x);
 | |
| 	break;
 | |
| 	
 | |
|     default:  /* RepeatNone */
 | |
| 	for (n = 0; n < count; n++)
 | |
| 	    if (pos < stops[n].x)
 | |
| 		break;
 | |
| 	
 | |
| 	if (n == 0)
 | |
| 	{
 | |
| 	    left_x  =  INT_MIN;
 | |
| 	    right_x =  stops[0].x;
 | |
| 	    left_c  = right_c = (xRenderColor*) &transparent_black;
 | |
| 	}
 | |
| 	else if (n == count)
 | |
| 	{
 | |
| 	    left_x  = stops[n-1].x;
 | |
| 	    right_x = INT_MAX;
 | |
| 	    left_c  = right_c = (xRenderColor*) &transparent_black;
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    left_x  =  stops[n-1].x;
 | |
| 	    right_x =  stops[n].x;
 | |
| 	    left_c  = &stops[n-1].color;
 | |
| 	    right_c = &stops[n].color;
 | |
| 	}
 | |
|     }
 | |
|     
 | |
|     walker->left_x   = left_x;
 | |
|     walker->right_x  = right_x;
 | |
|     walker->left_ag  = ((left_c->alpha >> 8) << 16)   | (left_c->green >> 8);
 | |
|     walker->left_rb  = ((left_c->red & 0xff00) << 8)  | (left_c->blue >> 8);
 | |
|     walker->right_ag = ((right_c->alpha >> 8) << 16)  | (right_c->green >> 8);
 | |
|     walker->right_rb = ((right_c->red & 0xff00) << 8) | (right_c->blue >> 8);
 | |
|     
 | |
|     if ( walker->left_x == walker->right_x                ||
 | |
| 	 ( walker->left_ag == walker->right_ag &&
 | |
| 	   walker->left_rb == walker->right_rb )   )
 | |
|     {
 | |
| 	walker->stepper = 0;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	int32_t width = right_x - left_x;
 | |
| 	walker->stepper = ((1 << 24) + width/2)/width;
 | |
|     }
 | |
| 
 | |
|     walker->need_reset = FALSE;
 | |
| }
 | |
| 
 | |
| #define  GRADIENT_WALKER_NEED_RESET(w,x)				\
 | |
|     ( (w)->need_reset || (x) < (w)->left_x || (x) >= (w)->right_x)
 | |
| 
 | |
| 
 | |
| /* the following assumes that GRADIENT_WALKER_NEED_RESET(w,x) is FALSE */
 | |
| static CARD32
 | |
| _gradient_walker_pixel (GradientWalker  *walker,
 | |
|                         xFixed_32_32     x)
 | |
| {
 | |
|     int  dist, idist;
 | |
|     CARD32  t1, t2, a, color;
 | |
|     
 | |
|     if (GRADIENT_WALKER_NEED_RESET (walker, x))
 | |
|         _gradient_walker_reset (walker, x);
 | |
|     
 | |
|     dist  = ((int)(x - walker->left_x)*walker->stepper) >> 16;
 | |
|     idist = 256 - dist;
 | |
|     
 | |
|     /* combined INTERPOLATE and premultiply */
 | |
|     t1 = walker->left_rb*idist + walker->right_rb*dist;
 | |
|     t1 = (t1 >> 8) & 0xff00ff;
 | |
|     
 | |
|     t2  = walker->left_ag*idist + walker->right_ag*dist;
 | |
|     t2 &= 0xff00ff00;
 | |
|     
 | |
|     color = t2 & 0xff000000;
 | |
|     a     = t2 >> 24;
 | |
|     
 | |
|     t1  = t1*a + 0x800080;
 | |
|     t1  = (t1 + ((t1 >> 8) & 0xff00ff)) >> 8;
 | |
|     
 | |
|     t2  = (t2 >> 8)*a + 0x800080;
 | |
|     t2  = (t2 + ((t2 >> 8) & 0xff00ff));
 | |
|     
 | |
|     return (color | (t1 & 0xff00ff) | (t2 & 0xff00));
 | |
| }
 | |
| 
 | |
| static void fbFetchSourcePict(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 | |
| {
 | |
|      SourcePictPtr   pGradient = pict->pSourcePict;
 | |
|      GradientWalker  walker;
 | |
|      CARD32         *end = buffer + width;
 | |
|  
 | |
|      _gradient_walker_init (&walker, pGradient, pict->repeat);
 | |
|     
 | |
|     if (pGradient->type == SourcePictTypeSolidFill) {
 | |
|         register CARD32 color = pGradient->solidFill.color;
 | |
|         while (buffer < end) {
 | |
|             WRITE(buffer++, color);
 | |
|         }
 | |
|     } else if (pGradient->type == SourcePictTypeLinear) {
 | |
|         PictVector v, unit;
 | |
|         xFixed_32_32 l;
 | |
|         xFixed_48_16 dx, dy, a, b, off;
 | |
| 	
 | |
|         /* reference point is the center of the pixel */
 | |
|         v.vector[0] = IntToxFixed(x) + xFixed1/2;
 | |
|         v.vector[1] = IntToxFixed(y) + xFixed1/2;
 | |
|         v.vector[2] = xFixed1;
 | |
|         if (pict->transform) {
 | |
|             if (!PictureTransformPoint3d (pict->transform, &v))
 | |
|                 return;
 | |
|             unit.vector[0] = pict->transform->matrix[0][0];
 | |
|             unit.vector[1] = pict->transform->matrix[1][0];
 | |
|             unit.vector[2] = pict->transform->matrix[2][0];
 | |
|         } else {
 | |
|             unit.vector[0] = xFixed1;
 | |
|             unit.vector[1] = 0;
 | |
|             unit.vector[2] = 0;
 | |
|         }
 | |
| 
 | |
|         dx = pGradient->linear.p2.x - pGradient->linear.p1.x;
 | |
|         dy = pGradient->linear.p2.y - pGradient->linear.p1.y;
 | |
|         l = dx*dx + dy*dy;
 | |
|         if (l != 0) {
 | |
|             a = (dx << 32) / l;
 | |
|             b = (dy << 32) / l;
 | |
|             off = (-a*pGradient->linear.p1.x - b*pGradient->linear.p1.y)>>16;
 | |
|         }
 | |
|         if (l == 0  || (unit.vector[2] == 0 && v.vector[2] == xFixed1)) {
 | |
|             xFixed_48_16 inc, t;
 | |
|             /* affine transformation only */
 | |
|             if (l == 0) {
 | |
|                 t = 0;
 | |
|                 inc = 0;
 | |
|             } else {
 | |
|                 t = ((a*v.vector[0] + b*v.vector[1]) >> 16) + off;
 | |
|                 inc = (a * unit.vector[0] + b * unit.vector[1]) >> 16;
 | |
|             }
 | |
| 
 | |
| 	    if (pGradient->linear.class == SourcePictClassVertical)
 | |
| 	    {
 | |
| 		register CARD32 color;
 | |
| 
 | |
| 		color = _gradient_walker_pixel( &walker, t );
 | |
| 		while (buffer < end)
 | |
| 		    WRITE(buffer++, color);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
|                 if (!mask) {
 | |
|                     while (buffer < end)
 | |
|                     {
 | |
|                         WRITE(buffer, _gradient_walker_pixel (&walker, t));
 | |
|                         buffer += 1;
 | |
|                         t      += inc;
 | |
|                     }
 | |
|                 } else {
 | |
|                     while (buffer < end) {
 | |
|                         if (*mask++ & maskBits)
 | |
|                         {
 | |
|                             WRITE(buffer, _gradient_walker_pixel (&walker, t));
 | |
|                         }
 | |
|                         buffer += 1;
 | |
|                         t      += inc;
 | |
|                     }
 | |
|                 }
 | |
| 	    }
 | |
| 	}
 | |
| 	else /* projective transformation */
 | |
| 	{
 | |
| 	    xFixed_48_16 t;
 | |
| 
 | |
| 	    if (pGradient->linear.class == SourcePictClassVertical)
 | |
| 	    {
 | |
| 		register CARD32 color;
 | |
| 
 | |
| 		if (v.vector[2] == 0)
 | |
| 		{
 | |
| 		    t = 0;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 		    xFixed_48_16 x, y;
 | |
| 
 | |
| 		    x = ((xFixed_48_16) v.vector[0] << 16) / v.vector[2];
 | |
| 		    y = ((xFixed_48_16) v.vector[1] << 16) / v.vector[2];
 | |
| 		    t = ((a * x + b * y) >> 16) + off;
 | |
| 		}
 | |
| 
 | |
|  		color = _gradient_walker_pixel( &walker, t );
 | |
| 		while (buffer < end)
 | |
| 		    WRITE(buffer++, color);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		while (buffer < end)
 | |
| 		{
 | |
| 		    if (!mask || *mask++ & maskBits)
 | |
| 		    {
 | |
| 			if (v.vector[2] == 0) {
 | |
| 			    t = 0;
 | |
| 			} else {
 | |
| 			    xFixed_48_16 x, y;
 | |
| 			    x = ((xFixed_48_16)v.vector[0] << 16) / v.vector[2];
 | |
| 			    y = ((xFixed_48_16)v.vector[1] << 16) / v.vector[2];
 | |
| 			    t = ((a*x + b*y) >> 16) + off;
 | |
| 			}
 | |
| 			WRITE(buffer, _gradient_walker_pixel (&walker, t));
 | |
| 		    }
 | |
| 		    ++buffer;
 | |
| 		    v.vector[0] += unit.vector[0];
 | |
| 		    v.vector[1] += unit.vector[1];
 | |
| 		    v.vector[2] += unit.vector[2];
 | |
| 		}
 | |
|             }
 | |
|         }
 | |
|     } else {
 | |
| 
 | |
| /*
 | |
|  * In the radial gradient problem we are given two circles (c₁,r₁) and
 | |
|  * (c₂,r₂) that define the gradient itself. Then, for any point p, we
 | |
|  * must compute the value(s) of t within [0.0, 1.0] representing the
 | |
|  * circle(s) that would color the point.
 | |
|  *
 | |
|  * There are potentially two values of t since the point p can be
 | |
|  * colored by both sides of the circle, (which happens whenever one
 | |
|  * circle is not entirely contained within the other).
 | |
|  *
 | |
|  * If we solve for a value of t that is outside of [0.0, 1.0] then we
 | |
|  * use the extend mode (NONE, REPEAT, REFLECT, or PAD) to map to a
 | |
|  * value within [0.0, 1.0].
 | |
|  *
 | |
|  * Here is an illustration of the problem:
 | |
|  *
 | |
|  *              p₂
 | |
|  *           p  •
 | |
|  *           •   ╲
 | |
|  *        ·       ╲r₂
 | |
|  *  p₁ ·           ╲
 | |
|  *  •              θ╲
 | |
|  *   ╲             ╌╌•
 | |
|  *    ╲r₁        ·   c₂
 | |
|  *    θ╲    ·
 | |
|  *    ╌╌•
 | |
|  *      c₁
 | |
|  *
 | |
|  * Given (c₁,r₁), (c₂,r₂) and p, we must find an angle θ such that two
 | |
|  * points p₁ and p₂ on the two circles are collinear with p. Then, the
 | |
|  * desired value of t is the ratio of the length of p₁p to the length
 | |
|  * of p₁p₂.
 | |
|  *
 | |
|  * So, we have six unknown values: (p₁x, p₁y), (p₂x, p₂y), θ and t.
 | |
|  * We can also write six equations that constrain the problem:
 | |
|  *
 | |
|  * Point p₁ is a distance r₁ from c₁ at an angle of θ:
 | |
|  *
 | |
|  *	1. p₁x = c₁x + r₁·cos θ
 | |
|  *	2. p₁y = c₁y + r₁·sin θ
 | |
|  *
 | |
|  * Point p₂ is a distance r₂ from c₂ at an angle of θ:
 | |
|  *
 | |
|  *	3. p₂x = c₂x + r2·cos θ
 | |
|  *	4. p₂y = c₂y + r2·sin θ
 | |
|  *
 | |
|  * Point p lies at a fraction t along the line segment p₁p₂:
 | |
|  *
 | |
|  *	5. px = t·p₂x + (1-t)·p₁x
 | |
|  *	6. py = t·p₂y + (1-t)·p₁y
 | |
|  *
 | |
|  * To solve, first subtitute 1-4 into 5 and 6:
 | |
|  *
 | |
|  * px = t·(c₂x + r₂·cos θ) + (1-t)·(c₁x + r₁·cos θ)
 | |
|  * py = t·(c₂y + r₂·sin θ) + (1-t)·(c₁y + r₁·sin θ)
 | |
|  *
 | |
|  * Then solve each for cos θ and sin θ expressed as a function of t:
 | |
|  *
 | |
|  * cos θ = (-(c₂x - c₁x)·t + (px - c₁x)) / ((r₂-r₁)·t + r₁)
 | |
|  * sin θ = (-(c₂y - c₁y)·t + (py - c₁y)) / ((r₂-r₁)·t + r₁)
 | |
|  *
 | |
|  * To simplify this a bit, we define new variables for several of the
 | |
|  * common terms as shown below:
 | |
|  *
 | |
|  *              p₂
 | |
|  *           p  •
 | |
|  *           •   ╲
 | |
|  *        ·  ┆    ╲r₂
 | |
|  *  p₁ ·     ┆     ╲
 | |
|  *  •     pdy┆      ╲
 | |
|  *   ╲       ┆       •c₂
 | |
|  *    ╲r₁    ┆   ·   ┆
 | |
|  *     ╲    ·┆       ┆cdy
 | |
|  *      •╌╌╌╌┴╌╌╌╌╌╌╌┘
 | |
|  *    c₁  pdx   cdx
 | |
|  *
 | |
|  * cdx = (c₂x - c₁x)
 | |
|  * cdy = (c₂y - c₁y)
 | |
|  *  dr =  r₂-r₁
 | |
|  * pdx =  px - c₁x
 | |
|  * pdy =  py - c₁y
 | |
|  *
 | |
|  * Note that cdx, cdy, and dr do not depend on point p at all, so can
 | |
|  * be pre-computed for the entire gradient. The simplifed equations
 | |
|  * are now:
 | |
|  *
 | |
|  * cos θ = (-cdx·t + pdx) / (dr·t + r₁)
 | |
|  * sin θ = (-cdy·t + pdy) / (dr·t + r₁)
 | |
|  *
 | |
|  * Finally, to get a single function of t and eliminate the last
 | |
|  * unknown θ, we use the identity sin²θ + cos²θ = 1. First, square
 | |
|  * each equation, (we knew a quadratic was coming since it must be
 | |
|  * possible to obtain two solutions in some cases):
 | |
|  *
 | |
|  * cos²θ = (cdx²t² - 2·cdx·pdx·t + pdx²) / (dr²·t² + 2·r₁·dr·t + r₁²)
 | |
|  * sin²θ = (cdy²t² - 2·cdy·pdy·t + pdy²) / (dr²·t² + 2·r₁·dr·t + r₁²)
 | |
|  *
 | |
|  * Then add both together, set the result equal to 1, and express as a
 | |
|  * standard quadratic equation in t of the form At² + Bt + C = 0
 | |
|  *
 | |
|  * (cdx² + cdy² - dr²)·t² - 2·(cdx·pdx + cdy·pdy + r₁·dr)·t + (pdx² + pdy² - r₁²) = 0
 | |
|  *
 | |
|  * In other words:
 | |
|  *
 | |
|  * A = cdx² + cdy² - dr²
 | |
|  * B = -2·(pdx·cdx + pdy·cdy + r₁·dr)
 | |
|  * C = pdx² + pdy² - r₁²
 | |
|  *
 | |
|  * And again, notice that A does not depend on p, so can be
 | |
|  * precomputed. From here we just use the quadratic formula to solve
 | |
|  * for t:
 | |
|  *
 | |
|  * t = (-2·B ± ⎷(B² - 4·A·C)) / 2·A
 | |
|  */
 | |
|         /* radial or conical */
 | |
|         Bool affine = TRUE;
 | |
|         double cx = 1.;
 | |
|         double cy = 0.;
 | |
|         double cz = 0.;
 | |
| 	double rx = x + 0.5;
 | |
| 	double ry = y + 0.5;
 | |
|         double rz = 1.;
 | |
| 
 | |
|         if (pict->transform) {
 | |
|             PictVector v;
 | |
|             /* reference point is the center of the pixel */
 | |
|             v.vector[0] = IntToxFixed(x) + xFixed1/2;
 | |
|             v.vector[1] = IntToxFixed(y) + xFixed1/2;
 | |
|             v.vector[2] = xFixed1;
 | |
|             if (!PictureTransformPoint3d (pict->transform, &v))
 | |
|                 return;
 | |
| 
 | |
|             cx = pict->transform->matrix[0][0]/65536.;
 | |
|             cy = pict->transform->matrix[1][0]/65536.;
 | |
|             cz = pict->transform->matrix[2][0]/65536.;
 | |
|             rx = v.vector[0]/65536.;
 | |
|             ry = v.vector[1]/65536.;
 | |
|             rz = v.vector[2]/65536.;
 | |
|             affine = pict->transform->matrix[2][0] == 0 && v.vector[2] == xFixed1;
 | |
|         }
 | |
| 
 | |
|         if (pGradient->type == SourcePictTypeRadial) {
 | |
| 	    PictRadialGradient *radial;
 | |
| 	    radial = &pGradient->radial;
 | |
|             if (affine) {
 | |
|                 while (buffer < end) {
 | |
| 		    if (!mask || *mask++ & maskBits)
 | |
| 		    {
 | |
| 			double pdx, pdy;
 | |
| 			double B, C;
 | |
| 			double det;
 | |
| 			double c1x = radial->c1.x / 65536.0;
 | |
| 			double c1y = radial->c1.y / 65536.0;
 | |
| 			double r1  = radial->c1.radius / 65536.0;
 | |
|                         xFixed_48_16 t;
 | |
| 
 | |
| 			pdx = rx - c1x;
 | |
| 			pdy = ry - c1y;
 | |
| 
 | |
| 			B = -2 * (  pdx * radial->cdx
 | |
| 				  + pdy * radial->cdy
 | |
| 				  + r1 * radial->dr);
 | |
| 			C = (pdx * pdx + pdy * pdy - r1 * r1);
 | |
| 
 | |
|                         det = (B * B) - (4 * radial->A * C);
 | |
| 			if (det < 0.0)
 | |
| 			    det = 0.0;
 | |
| 
 | |
| 			if (radial->A < 0)
 | |
| 			    t = (xFixed_48_16) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536);
 | |
| 			else
 | |
| 			    t = (xFixed_48_16) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536);
 | |
| 			
 | |
|  			WRITE(buffer, _gradient_walker_pixel (&walker, t));
 | |
| 		    }
 | |
| 		    ++buffer;
 | |
| 		    
 | |
|                     rx += cx;
 | |
|                     ry += cy;
 | |
|                 }
 | |
|             } else {
 | |
| 		/* projective */
 | |
|                 while (buffer < end) {
 | |
| 		    if (!mask || *mask++ & maskBits)
 | |
| 		    {
 | |
| 			double pdx, pdy;
 | |
| 			double B, C;
 | |
| 			double det;
 | |
| 			double c1x = radial->c1.x / 65536.0;
 | |
| 			double c1y = radial->c1.y / 65536.0;
 | |
| 			double r1  = radial->c1.radius / 65536.0;
 | |
|                         xFixed_48_16 t;
 | |
| 			double x, y;
 | |
| 
 | |
| 			if (rz != 0) {
 | |
| 			    x = rx/rz;
 | |
| 			    y = ry/rz;
 | |
| 			} else {
 | |
| 			    x = y = 0.;
 | |
| 			}
 | |
| 			
 | |
| 			pdx = x - c1x;
 | |
| 			pdy = y - c1y;
 | |
| 
 | |
| 			B = -2 * (  pdx * radial->cdx
 | |
| 				  + pdy * radial->cdy
 | |
| 				  + r1 * radial->dr);
 | |
| 			C = (pdx * pdx + pdy * pdy - r1 * r1);
 | |
| 
 | |
|                         det = (B * B) - (4 * radial->A * C);
 | |
| 			if (det < 0.0)
 | |
| 			    det = 0.0;
 | |
| 
 | |
| 			if (radial->A < 0)
 | |
| 			    t = (xFixed_48_16) ((- B - sqrt(det)) / (2.0 * radial->A) * 65536);
 | |
| 			else
 | |
| 			    t = (xFixed_48_16) ((- B + sqrt(det)) / (2.0 * radial->A) * 65536);
 | |
| 			
 | |
|  			WRITE(buffer, _gradient_walker_pixel (&walker, t));
 | |
| 		    }
 | |
| 		    ++buffer;
 | |
| 		    
 | |
|                     rx += cx;
 | |
|                     ry += cy;
 | |
| 		    rz += cz;
 | |
|                 }
 | |
|             }
 | |
|         } else /* SourcePictTypeConical */ {
 | |
|             double a = pGradient->conical.angle/(180.*65536);
 | |
|             if (affine) {
 | |
|                 rx -= pGradient->conical.center.x/65536.;
 | |
|                 ry -= pGradient->conical.center.y/65536.;
 | |
| 
 | |
|                 while (buffer < end) {
 | |
| 		    double angle;
 | |
| 
 | |
|                     if (!mask || *mask++ & maskBits)
 | |
| 		    {
 | |
|                         xFixed_48_16   t;
 | |
| 			
 | |
|                         angle = atan2(ry, rx) + a;
 | |
| 			t     = (xFixed_48_16) (angle * (65536. / (2*M_PI)));
 | |
| 			
 | |
| 			WRITE(buffer, _gradient_walker_pixel (&walker, t));
 | |
| 		    }
 | |
| 
 | |
|                     ++buffer;
 | |
|                     rx += cx;
 | |
|                     ry += cy;
 | |
|                 }
 | |
|             } else {
 | |
|                 while (buffer < end) {
 | |
|                     double x, y;
 | |
|                     double angle;
 | |
| 		    
 | |
|                     if (!mask || *mask++ & maskBits)
 | |
|                     {
 | |
| 			xFixed_48_16  t;
 | |
| 			
 | |
| 			if (rz != 0) {
 | |
| 			    x = rx/rz;
 | |
| 			    y = ry/rz;
 | |
| 			} else {
 | |
| 			    x = y = 0.;
 | |
| 			}
 | |
| 			x -= pGradient->conical.center.x/65536.;
 | |
| 			y -= pGradient->conical.center.y/65536.;
 | |
| 			angle = atan2(y, x) + a;
 | |
| 			t     = (xFixed_48_16) (angle * (65536. / (2*M_PI)));
 | |
| 			
 | |
| 			WRITE(buffer, _gradient_walker_pixel (&walker, t));
 | |
| 		    }
 | |
| 		    
 | |
|                     ++buffer;
 | |
|                     rx += cx;
 | |
|                     ry += cy;
 | |
|                     rz += cz;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 | |
| {
 | |
|     FbBits     *bits;
 | |
|     FbStride    stride;
 | |
|     int         bpp;
 | |
|     int         xoff, yoff, dx, dy;
 | |
|     fetchPixelProc   fetch;
 | |
|     PictVector	v;
 | |
|     PictVector  unit;
 | |
|     int         i;
 | |
|     BoxRec	box;
 | |
|     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
 | |
|     Bool affine = TRUE;
 | |
| 
 | |
|     fetch = fetchPixelProcForPicture(pict);
 | |
| 
 | |
|     fbGetDrawable(pict->pDrawable, bits, stride, bpp, xoff, yoff);
 | |
|     x += xoff;
 | |
|     y += yoff;
 | |
| 
 | |
|     dx = pict->pDrawable->x;
 | |
|     dy = pict->pDrawable->y;
 | |
| 
 | |
|     /* reference point is the center of the pixel */
 | |
|     v.vector[0] = IntToxFixed(x - dx) + xFixed1 / 2;
 | |
|     v.vector[1] = IntToxFixed(y - dy) + xFixed1 / 2;
 | |
|     v.vector[2] = xFixed1;
 | |
| 
 | |
|     /* when using convolution filters one might get here without a transform */
 | |
|     if (pict->transform) {
 | |
|         if (!PictureTransformPoint3d (pict->transform, &v)) {
 | |
|             fbFinishAccess (pict->pDrawable);
 | |
|             return;
 | |
|         }
 | |
|         unit.vector[0] = pict->transform->matrix[0][0];
 | |
|         unit.vector[1] = pict->transform->matrix[1][0];
 | |
|         unit.vector[2] = pict->transform->matrix[2][0];
 | |
|         affine = v.vector[2] == xFixed1 && unit.vector[2] == 0;
 | |
|     } else {
 | |
|         unit.vector[0] = xFixed1;
 | |
|         unit.vector[1] = 0;
 | |
|         unit.vector[2] = 0;
 | |
|     }
 | |
| 
 | |
|     if (pict->filter == PictFilterNearest)
 | |
|     {
 | |
|         if (pict->repeatType == RepeatNormal) {
 | |
|             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
 | |
|                 for (i = 0; i < width; ++i) {
 | |
| 		    if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    if (!affine) {
 | |
| 				y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
 | |
| 				x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
 | |
| 			    } else {
 | |
| 				y = MOD(v.vector[1]>>16, pict->pDrawable->height);
 | |
| 				x = MOD(v.vector[0]>>16, pict->pDrawable->width);
 | |
| 			    }
 | |
| 			    WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
 | |
| 			}
 | |
| 		    }
 | |
| 
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             } else {
 | |
|                 for (i = 0; i < width; ++i) {
 | |
| 		    if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    if (!affine) {
 | |
| 				y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height);
 | |
| 				x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width);
 | |
| 			    } else {
 | |
| 				y = MOD(v.vector[1]>>16, pict->pDrawable->height);
 | |
| 				x = MOD(v.vector[0]>>16, pict->pDrawable->width);
 | |
| 			    }
 | |
| 			    if (POINT_IN_REGION (0, pict->pCompositeClip, x, y, &box))
 | |
| 				WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
 | |
| 			    else
 | |
| 				WRITE(buffer + i, 0);
 | |
| 			}
 | |
| 		    }
 | |
| 
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
 | |
|                 box = pict->pCompositeClip->extents;
 | |
|                 for (i = 0; i < width; ++i) {
 | |
| 		    if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    if (!affine) {
 | |
| 				y = DIV(v.vector[1],v.vector[2]);
 | |
| 				x = DIV(v.vector[0],v.vector[2]);
 | |
| 			    } else {
 | |
| 				y = v.vector[1]>>16;
 | |
| 				x = v.vector[0]>>16;
 | |
| 			    }
 | |
| 			    WRITE(buffer + i, ((x < box.x1-dx) | (x >= box.x2-dx) | (y < box.y1-dy) | (y >= box.y2-dy)) ?
 | |
| 				  0 : fetch(bits + (y + dy)*stride, x + dx, indexed));
 | |
| 			}
 | |
| 		    }
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             } else {
 | |
|                 for (i = 0; i < width; ++i) {
 | |
|                     if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    if (!affine) {
 | |
| 				y = DIV(v.vector[1],v.vector[2]);
 | |
| 				x = DIV(v.vector[0],v.vector[2]);
 | |
| 			    } else {
 | |
| 				y = v.vector[1]>>16;
 | |
| 				x = v.vector[0]>>16;
 | |
| 			    }
 | |
| 			    if (POINT_IN_REGION (0, pict->pCompositeClip, x + dx, y + dy, &box))
 | |
| 				WRITE(buffer + i, fetch(bits + (y + dy)*stride, x + dx, indexed));
 | |
| 			    else
 | |
| 				WRITE(buffer + i, 0);
 | |
| 			}
 | |
| 		    }
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     } else if (pict->filter == PictFilterBilinear) {
 | |
|         /* adjust vector for maximum contribution at 0.5, 0.5 of each texel. */
 | |
|         v.vector[0] -= v.vector[2] / 2;
 | |
|         v.vector[1] -= v.vector[2] / 2;
 | |
|         unit.vector[0] -= unit.vector[2] / 2;
 | |
|         unit.vector[1] -= unit.vector[2] / 2;
 | |
| 
 | |
|         if (pict->repeatType == RepeatNormal) {
 | |
|             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
 | |
|                 for (i = 0; i < width; ++i) {
 | |
|                     if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
 | |
| 			    FbBits *b;
 | |
| 			    CARD32 tl, tr, bl, br, r;
 | |
| 			    CARD32 ft, fb;
 | |
| 
 | |
| 			    if (!affine) {
 | |
| 				xFixed_48_16 div;
 | |
| 				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
 | |
| 				x1 = div >> 16;
 | |
| 				distx = ((xFixed)div >> 8) & 0xff;
 | |
| 				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
 | |
| 				y1 = div >> 16;
 | |
| 				disty = ((xFixed)div >> 8) & 0xff;
 | |
| 			    } else {
 | |
| 				x1 = v.vector[0] >> 16;
 | |
| 				distx = (v.vector[0] >> 8) & 0xff;
 | |
| 				y1 = v.vector[1] >> 16;
 | |
| 				disty = (v.vector[1] >> 8) & 0xff;
 | |
| 			    }
 | |
| 			    x2 = x1 + 1;
 | |
| 			    y2 = y1 + 1;
 | |
| 
 | |
| 			    idistx = 256 - distx;
 | |
| 			    idisty = 256 - disty;
 | |
| 
 | |
| 			    x1 = MOD (x1, pict->pDrawable->width);
 | |
| 			    x2 = MOD (x2, pict->pDrawable->width);
 | |
| 			    y1 = MOD (y1, pict->pDrawable->height);
 | |
| 			    y2 = MOD (y2, pict->pDrawable->height);
 | |
| 
 | |
| 			    b = bits + (y1 + dy)*stride;
 | |
| 
 | |
| 			    tl = fetch(b, x1 + dx, indexed);
 | |
| 			    tr = fetch(b, x2 + dx, indexed);
 | |
| 			    b = bits + (y2 + dy)*stride;
 | |
| 			    bl = fetch(b, x1 + dx, indexed);
 | |
| 			    br = fetch(b, x2 + dx, indexed);
 | |
| 
 | |
| 			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
 | |
| 			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
 | |
| 			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
 | |
| 			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
 | |
| 			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
 | |
| 			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
 | |
| 			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
 | |
| 			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
 | |
| 			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
 | |
| 			    WRITE(buffer + i, r);
 | |
| 			}
 | |
| 		    }
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             } else {
 | |
|                 for (i = 0; i < width; ++i) {
 | |
| 		    if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    int x1, x2, y1, y2, distx, idistx, disty, idisty;
 | |
| 			    FbBits *b;
 | |
| 			    CARD32 tl, tr, bl, br, r;
 | |
| 			    CARD32 ft, fb;
 | |
| 
 | |
| 			    if (!affine) {
 | |
| 				xFixed_48_16 div;
 | |
| 				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
 | |
| 				x1 = div >> 16;
 | |
| 				distx = ((xFixed)div >> 8) & 0xff;
 | |
| 				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
 | |
| 				y1 = div >> 16;
 | |
| 				disty = ((xFixed)div >> 8) & 0xff;
 | |
| 			    } else {
 | |
| 				x1 = v.vector[0] >> 16;
 | |
| 				distx = (v.vector[0] >> 8) & 0xff;
 | |
| 				y1 = v.vector[1] >> 16;
 | |
| 				disty = (v.vector[1] >> 8) & 0xff;
 | |
| 			    }
 | |
| 			    x2 = x1 + 1;
 | |
| 			    y2 = y1 + 1;
 | |
| 
 | |
| 			    idistx = 256 - distx;
 | |
| 			    idisty = 256 - disty;
 | |
| 
 | |
| 			    x1 = MOD (x1, pict->pDrawable->width);
 | |
| 			    x2 = MOD (x2, pict->pDrawable->width);
 | |
| 			    y1 = MOD (y1, pict->pDrawable->height);
 | |
| 			    y2 = MOD (y2, pict->pDrawable->height);
 | |
| 
 | |
| 			    b = bits + (y1 + dy)*stride;
 | |
| 
 | |
| 			    tl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y1 + dy, &box)
 | |
| 				? fetch(b, x1 + dx, indexed) : 0;
 | |
| 			    tr = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y1 + dy, &box)
 | |
| 				? fetch(b, x2 + dx, indexed) : 0;
 | |
| 			    b = bits + (y2 + dy)*stride;
 | |
| 			    bl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y2 + dy, &box)
 | |
| 				? fetch(b, x1 + dx, indexed) : 0;
 | |
| 			    br = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y2 + dy, &box)
 | |
| 				? fetch(b, x2 + dx, indexed) : 0;
 | |
| 
 | |
| 			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
 | |
| 			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
 | |
| 			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
 | |
| 			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
 | |
| 			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
 | |
| 			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
 | |
| 			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
 | |
| 			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
 | |
| 			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
 | |
| 			    WRITE(buffer + i, r);
 | |
| 			}
 | |
| 		    }
 | |
| 
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             }
 | |
|         } else {
 | |
|             if (REGION_NUM_RECTS(pict->pCompositeClip) == 1) {
 | |
|                 box = pict->pCompositeClip->extents;
 | |
|                 for (i = 0; i < width; ++i) {
 | |
| 		    if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
 | |
| 			    FbBits *b;
 | |
| 			    CARD32 tl, tr, bl, br, r;
 | |
| 			    Bool x1_out, x2_out, y1_out, y2_out;
 | |
| 			    CARD32 ft, fb;
 | |
| 
 | |
| 			    if (!affine) {
 | |
| 				xFixed_48_16 div;
 | |
| 				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
 | |
| 				x1 = div >> 16;
 | |
| 				distx = ((xFixed)div >> 8) & 0xff;
 | |
| 				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
 | |
| 				y1 = div >> 16;
 | |
| 				disty = ((xFixed)div >> 8) & 0xff;
 | |
| 			    } else {
 | |
| 				x1 = v.vector[0] >> 16;
 | |
| 				distx = (v.vector[0] >> 8) & 0xff;
 | |
| 				y1 = v.vector[1] >> 16;
 | |
| 				disty = (v.vector[1] >> 8) & 0xff;
 | |
| 			    }
 | |
| 			    x2 = x1 + 1;
 | |
| 			    y2 = y1 + 1;
 | |
| 
 | |
| 			    idistx = 256 - distx;
 | |
| 			    idisty = 256 - disty;
 | |
| 
 | |
| 			    b = bits + (y1 + dy)*stride;
 | |
| 			    x_off = x1 + dx;
 | |
| 
 | |
| 			    x1_out = (x1 < box.x1-dx) | (x1 >= box.x2-dx);
 | |
| 			    x2_out = (x2 < box.x1-dx) | (x2 >= box.x2-dx);
 | |
| 			    y1_out = (y1 < box.y1-dy) | (y1 >= box.y2-dy);
 | |
| 			    y2_out = (y2 < box.y1-dy) | (y2 >= box.y2-dy);
 | |
| 
 | |
| 			    tl = x1_out|y1_out ? 0 : fetch(b, x_off, indexed);
 | |
| 			    tr = x2_out|y1_out ? 0 : fetch(b, x_off + 1, indexed);
 | |
| 			    b += stride;
 | |
| 			    bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed);
 | |
| 			    br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed);
 | |
| 
 | |
| 			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
 | |
| 			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
 | |
| 			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
 | |
| 			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
 | |
| 			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
 | |
| 			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
 | |
| 			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
 | |
| 			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
 | |
| 			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
 | |
| 			    WRITE(buffer + i, r);
 | |
| 			}
 | |
| 		    }
 | |
| 
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             } else {
 | |
|                 for (i = 0; i < width; ++i) {
 | |
|                     if (!mask || mask[i] & maskBits)
 | |
| 		    {
 | |
| 			if (!v.vector[2]) {
 | |
| 			    WRITE(buffer + i, 0);
 | |
| 			} else {
 | |
| 			    int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off;
 | |
| 			    FbBits *b;
 | |
| 			    CARD32 tl, tr, bl, br, r;
 | |
| 			    CARD32 ft, fb;
 | |
| 
 | |
| 			    if (!affine) {
 | |
| 				xFixed_48_16 div;
 | |
| 				div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2];
 | |
| 				x1 = div >> 16;
 | |
| 				distx = ((xFixed)div >> 8) & 0xff;
 | |
| 				div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2];
 | |
| 				y1 = div >> 16;
 | |
| 				disty = ((xFixed)div >> 8) & 0xff;
 | |
| 			    } else {
 | |
| 				x1 = v.vector[0] >> 16;
 | |
| 				distx = (v.vector[0] >> 8) & 0xff;
 | |
| 				y1 = v.vector[1] >> 16;
 | |
| 				disty = (v.vector[1] >> 8) & 0xff;
 | |
| 			    }
 | |
| 			    x2 = x1 + 1;
 | |
| 			    y2 = y1 + 1;
 | |
| 
 | |
| 			    idistx = 256 - distx;
 | |
| 			    idisty = 256 - disty;
 | |
| 
 | |
| 			    b = bits + (y1 + dy)*stride;
 | |
| 			    x_off = x1 + dx;
 | |
| 
 | |
| 			    tl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y1 + dy, &box)
 | |
| 				? fetch(b, x_off, indexed) : 0;
 | |
| 			    tr = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y1 + dy, &box)
 | |
| 				? fetch(b, x_off + 1, indexed) : 0;
 | |
| 			    b += stride;
 | |
| 			    bl = POINT_IN_REGION(0, pict->pCompositeClip, x1 + dx, y2 + dy, &box)
 | |
| 				? fetch(b, x_off, indexed) : 0;
 | |
| 			    br = POINT_IN_REGION(0, pict->pCompositeClip, x2 + dx, y2 + dy, &box)
 | |
| 				? fetch(b, x_off + 1, indexed) : 0;
 | |
| 
 | |
| 			    ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
 | |
| 			    fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx;
 | |
| 			    r = (((ft * idisty + fb * disty) >> 16) & 0xff);
 | |
| 			    ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx;
 | |
| 			    fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) >> 8) & 0xff00);
 | |
| 			    ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx;
 | |
| 			    fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty)) & 0xff0000);
 | |
| 			    ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx;
 | |
| 			    fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx;
 | |
| 			    r |= (((ft * idisty + fb * disty) << 8) & 0xff000000);
 | |
| 			    WRITE(buffer + i, r);
 | |
| 			}
 | |
| 		    }
 | |
| 
 | |
|                     v.vector[0] += unit.vector[0];
 | |
|                     v.vector[1] += unit.vector[1];
 | |
|                     v.vector[2] += unit.vector[2];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     } else if (pict->filter == PictFilterConvolution) {
 | |
|         xFixed *params = pict->filter_params;
 | |
|         INT32 cwidth = xFixedToInt(params[0]);
 | |
|         INT32 cheight = xFixedToInt(params[1]);
 | |
|         int xoff = (params[0] - xFixed1) >> 1;
 | |
| 	int yoff = (params[1] - xFixed1) >> 1;
 | |
|         params += 2;
 | |
|         for (i = 0; i < width; ++i) {
 | |
| 	    if (!mask || mask[i] & maskBits)
 | |
| 	    {
 | |
| 		if (!v.vector[2]) {
 | |
| 		    WRITE(buffer + i, 0);
 | |
| 		} else {
 | |
| 		    int x1, x2, y1, y2, x, y;
 | |
| 		    INT32 srtot, sgtot, sbtot, satot;
 | |
| 		    xFixed *p = params;
 | |
| 
 | |
| 		    if (!affine) {
 | |
| 			xFixed_48_16 tmp;
 | |
| 			tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff;
 | |
| 			x1 = xFixedToInt(tmp);
 | |
| 			tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff;
 | |
| 			y1 = xFixedToInt(tmp);
 | |
| 		    } else {
 | |
| 			x1 = xFixedToInt(v.vector[0] - xoff);
 | |
| 			y1 = xFixedToInt(v.vector[1] - yoff);
 | |
| 		    }
 | |
| 		    x2 = x1 + cwidth;
 | |
| 		    y2 = y1 + cheight;
 | |
| 
 | |
| 		    srtot = sgtot = sbtot = satot = 0;
 | |
| 
 | |
| 		    for (y = y1; y < y2; y++) {
 | |
| 			int ty = (pict->repeatType == RepeatNormal) ? MOD (y, pict->pDrawable->height) : y;
 | |
| 			for (x = x1; x < x2; x++) {
 | |
| 			    if (*p) {
 | |
| 				int tx = (pict->repeatType == RepeatNormal) ? MOD (x, pict->pDrawable->width) : x;
 | |
| 				if (POINT_IN_REGION (0, pict->pCompositeClip, tx + dx, ty + dy, &box)) {
 | |
| 				    FbBits *b = bits + (ty + dy)*stride;
 | |
| 				    CARD32 c = fetch(b, tx + dx, indexed);
 | |
| 
 | |
| 				    srtot += Red(c) * *p;
 | |
| 				    sgtot += Green(c) * *p;
 | |
| 				    sbtot += Blue(c) * *p;
 | |
| 				    satot += Alpha(c) * *p;
 | |
| 				}
 | |
| 			    }
 | |
| 			    p++;
 | |
| 			}
 | |
| 		    }
 | |
| 
 | |
| 		    satot >>= 16;
 | |
| 		    srtot >>= 16;
 | |
| 		    sgtot >>= 16;
 | |
| 		    sbtot >>= 16;
 | |
| 
 | |
| 		    if (satot < 0) satot = 0; else if (satot > 0xff) satot = 0xff;
 | |
| 		    if (srtot < 0) srtot = 0; else if (srtot > 0xff) srtot = 0xff;
 | |
| 		    if (sgtot < 0) sgtot = 0; else if (sgtot > 0xff) sgtot = 0xff;
 | |
| 		    if (sbtot < 0) sbtot = 0; else if (sbtot > 0xff) sbtot = 0xff;
 | |
| 
 | |
| 		    WRITE(buffer + i, ((satot << 24) |
 | |
| 				       (srtot << 16) |
 | |
| 				       (sgtot <<  8) |
 | |
| 				       (sbtot       )));
 | |
| 		}
 | |
| 	    }
 | |
|             v.vector[0] += unit.vector[0];
 | |
|             v.vector[1] += unit.vector[1];
 | |
|             v.vector[2] += unit.vector[2];
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     fbFinishAccess (pict->pDrawable);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void fbFetchExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer, CARD32 *mask, CARD32 maskBits)
 | |
| {
 | |
|     int i;
 | |
|     CARD32 _alpha_buffer[SCANLINE_BUFFER_LENGTH];
 | |
|     CARD32 *alpha_buffer = _alpha_buffer;
 | |
| 
 | |
|     if (!pict->alphaMap) {
 | |
|         fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits);
 | |
| 	return;
 | |
|     }
 | |
|     if (width > SCANLINE_BUFFER_LENGTH)
 | |
|         alpha_buffer = (CARD32 *) malloc(width*sizeof(CARD32));
 | |
| 
 | |
|     fbFetchTransformed(pict, x, y, width, buffer, mask, maskBits);
 | |
|     fbFetchTransformed(pict->alphaMap, x - pict->alphaOrigin.x,
 | |
| 		       y - pict->alphaOrigin.y, width, alpha_buffer,
 | |
| 		       mask, maskBits);
 | |
|     for (i = 0; i < width; ++i) {
 | |
|         if (!mask || mask[i] & maskBits)
 | |
| 	{
 | |
| 	    int a = alpha_buffer[i]>>24;
 | |
| 	    WRITE(buffer + i, (a << 24)
 | |
| 		  | (div_255(Red(READ(buffer + i)) * a) << 16)
 | |
| 		  | (div_255(Green(READ(buffer + i)) * a) << 8)
 | |
| 		  | (div_255(Blue(READ(buffer + i)) * a)));
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if (alpha_buffer != _alpha_buffer)
 | |
|         free(alpha_buffer);
 | |
| }
 | |
| 
 | |
| static void fbStore(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
 | |
| {
 | |
|     FbBits *bits;
 | |
|     FbStride stride;
 | |
|     int bpp;
 | |
|     int xoff, yoff;
 | |
|     storeProc store = storeProcForPicture(pict);
 | |
|     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
 | |
| 
 | |
|     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
 | |
|     x += xoff;
 | |
|     y += yoff;
 | |
| 
 | |
|     bits += y*stride;
 | |
|     store(bits, buffer, x, width, indexed);
 | |
|     fbFinishAccess (pict->pDrawable);
 | |
| }
 | |
| 
 | |
| static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD32 *buffer)
 | |
| {
 | |
|     FbBits *bits, *alpha_bits;
 | |
|     FbStride stride, astride;
 | |
|     int bpp, abpp;
 | |
|     int xoff, yoff;
 | |
|     int ax, ay;
 | |
|     storeProc store;
 | |
|     storeProc astore;
 | |
|     miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate;
 | |
|     miIndexedPtr aindexed;
 | |
| 
 | |
|     if (!pict->alphaMap) {
 | |
|         fbStore(pict, x, y, width, buffer);
 | |
| 	return;
 | |
|     }
 | |
| 
 | |
|     store = storeProcForPicture(pict);
 | |
|     astore = storeProcForPicture(pict->alphaMap);
 | |
|     aindexed = (miIndexedPtr) pict->alphaMap->pFormat->index.devPrivate;
 | |
| 
 | |
|     ax = x;
 | |
|     ay = y;
 | |
| 
 | |
|     fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
 | |
|     x += xoff;
 | |
|     y += yoff;
 | |
|     fbGetDrawable (pict->alphaMap->pDrawable, alpha_bits, astride, abpp, xoff, yoff);
 | |
|     ax += xoff;
 | |
|     ay += yoff;
 | |
| 
 | |
|     bits       += y*stride;
 | |
|     alpha_bits += (ay - pict->alphaOrigin.y)*astride;
 | |
| 
 | |
| 
 | |
|     store(bits, buffer, x, width, indexed);
 | |
|     astore(alpha_bits, buffer, ax - pict->alphaOrigin.x, width, aindexed);
 | |
| 
 | |
|     fbFinishAccess (pict->alphaMap->pDrawable);
 | |
|     fbFinishAccess (pict->pDrawable);
 | |
| }
 | |
| 
 | |
| typedef void (*scanStoreProc)(PicturePtr , int , int , int , CARD32 *);
 | |
| typedef void (*scanFetchProc)(PicturePtr , int , int , int , CARD32 * , CARD32 *, CARD32);
 | |
| 
 | |
| static void
 | |
| fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer)
 | |
| {
 | |
|     CARD32 *src_buffer = scanline_buffer;
 | |
|     CARD32 *dest_buffer = src_buffer + data->width;
 | |
|     int i;
 | |
|     scanStoreProc store;
 | |
|     scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
 | |
|     unsigned int srcClass = SourcePictClassUnknown;
 | |
|     unsigned int maskClass = SourcePictClassUnknown;
 | |
|     FbBits *bits;
 | |
|     FbStride stride;
 | |
|     int xoff, yoff;
 | |
|     
 | |
|     if (data->op == PictOpClear)
 | |
|         fetchSrc = NULL;
 | |
|     else if (!data->src->pDrawable) {
 | |
|         if (data->src->pSourcePict)
 | |
| 	{
 | |
|             fetchSrc = fbFetchSourcePict;
 | |
| 	    srcClass = SourcePictureClassify (data->src,
 | |
| 					      data->xSrc, data->ySrc,
 | |
| 					      data->width, data->height);
 | |
| 	}
 | |
|     } else if (data->src->alphaMap)
 | |
|         fetchSrc = fbFetchExternalAlpha;
 | |
|     else if (data->src->repeatType == RepeatNormal &&
 | |
|              data->src->pDrawable->width == 1 && data->src->pDrawable->height == 1)
 | |
|     {
 | |
|         fetchSrc = fbFetchSolid;
 | |
| 	srcClass = SourcePictClassHorizontal;
 | |
|     }
 | |
|     else if (!data->src->transform && data->src->filter != PictFilterConvolution)
 | |
|         fetchSrc = fbFetch;
 | |
|     else
 | |
|         fetchSrc = fbFetchTransformed;
 | |
|     
 | |
|     if (data->mask && data->op != PictOpClear) {
 | |
|         if (!data->mask->pDrawable) {
 | |
|             if (data->mask->pSourcePict)
 | |
|                 fetchMask = fbFetchSourcePict;
 | |
|         } else if (data->mask->alphaMap)
 | |
| 	{
 | |
|             fetchMask = fbFetchExternalAlpha;
 | |
| 	    maskClass = SourcePictureClassify (data->mask,
 | |
| 					       data->xMask, data->yMask,
 | |
| 					       data->width, data->height);
 | |
| 	}
 | |
|         else if (data->mask->repeatType == RepeatNormal
 | |
|                  && data->mask->pDrawable->width == 1 && data->mask->pDrawable->height == 1)
 | |
| 	{
 | |
| 	    fetchMask = fbFetchSolid;
 | |
| 	    maskClass = SourcePictClassHorizontal;
 | |
| 	}
 | |
|         else if (!data->mask->transform && data->mask->filter != PictFilterConvolution)
 | |
|             fetchMask = fbFetch;
 | |
|         else
 | |
|             fetchMask = fbFetchTransformed;
 | |
|     } else {
 | |
|         fetchMask = NULL;
 | |
|     }
 | |
|     
 | |
|     if (data->dest->alphaMap)
 | |
|     {
 | |
| 	fetchDest = fbFetchExternalAlpha;
 | |
| 	store = fbStoreExternalAlpha;
 | |
| 	
 | |
| 	if (data->op == PictOpClear || data->op == PictOpSrc)
 | |
| 	    fetchDest = NULL;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	fetchDest = fbFetch;
 | |
| 	store = fbStore;
 | |
| 	
 | |
| 	switch (data->op) {
 | |
| 	case PictOpClear:
 | |
| 	case PictOpSrc:
 | |
| 	    fetchDest = NULL;
 | |
| 	    /* fall-through */
 | |
| 	case PictOpAdd:
 | |
| 	case PictOpOver:
 | |
| 	    switch (data->dest->format) {
 | |
| 	    case PICT_a8r8g8b8:
 | |
| 	    case PICT_x8r8g8b8:
 | |
| 		store = NULL;
 | |
| 		break;
 | |
| 	    default:
 | |
| 		break;
 | |
| 	    }
 | |
| 	    break;
 | |
| 	}
 | |
|     }
 | |
|     
 | |
|     if (!store)
 | |
|     {
 | |
| 	int bpp;
 | |
| 	
 | |
| 	fbGetDrawable (data->dest->pDrawable, bits, stride, bpp, xoff, yoff);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	bits = NULL;
 | |
| 	stride = 0;
 | |
| 	xoff = yoff = 0;
 | |
|     }
 | |
|     
 | |
|     if (fetchSrc		   &&
 | |
| 	fetchMask		   &&
 | |
| 	data->mask		   &&
 | |
| 	data->mask->componentAlpha &&
 | |
| 	PICT_FORMAT_RGB (data->mask->format))
 | |
|     {
 | |
| 	CARD32 *mask_buffer = dest_buffer + data->width;
 | |
| 	CombineFuncC compose = composeFunctions.combineC[data->op];
 | |
| 	if (!compose)
 | |
| 	    return;
 | |
| 	
 | |
| 	for (i = 0; i < data->height; ++i) {
 | |
| 	    /* fill first half of scanline with source */
 | |
| 	    if (fetchSrc)
 | |
| 	    {
 | |
| 		if (fetchMask)
 | |
| 		{
 | |
| 		    /* fetch mask before source so that fetching of
 | |
| 		       source can be optimized */
 | |
| 		    fetchMask (data->mask, data->xMask, data->yMask + i,
 | |
| 			       data->width, mask_buffer, 0, 0);
 | |
| 		    
 | |
| 		    if (maskClass == SourcePictClassHorizontal)
 | |
| 			fetchMask = NULL;
 | |
| 		}
 | |
| 		
 | |
| 		if (srcClass == SourcePictClassHorizontal)
 | |
| 		{
 | |
| 		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
 | |
| 			      data->width, src_buffer, 0, 0);
 | |
| 		    fetchSrc = NULL;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
 | |
| 			      data->width, src_buffer, mask_buffer,
 | |
| 			      0xffffffff);
 | |
| 		}
 | |
| 	    }
 | |
| 	    else if (fetchMask)
 | |
| 	    {
 | |
| 		fetchMask (data->mask, data->xMask, data->yMask + i,
 | |
| 			   data->width, mask_buffer, 0, 0);
 | |
| 	    }
 | |
| 	    
 | |
| 	    if (store)
 | |
| 	    {
 | |
| 		/* fill dest into second half of scanline */
 | |
| 		if (fetchDest)
 | |
| 		    fetchDest (data->dest, data->xDest, data->yDest + i,
 | |
| 			       data->width, dest_buffer, 0, 0);
 | |
| 		
 | |
| 		/* blend */
 | |
| 		compose (dest_buffer, src_buffer, mask_buffer, data->width);
 | |
| 		
 | |
| 		/* write back */
 | |
| 		store (data->dest, data->xDest, data->yDest + i, data->width,
 | |
| 		       dest_buffer);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		/* blend */
 | |
| 		compose (bits + (data->yDest + i+ yoff) * stride +
 | |
| 			 data->xDest + xoff,
 | |
| 			 src_buffer, mask_buffer, data->width);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	CARD32 *src_mask_buffer = 0, *mask_buffer = 0;
 | |
| 	CombineFuncU compose = composeFunctions.combineU[data->op];
 | |
| 	if (!compose)
 | |
| 	    return;
 | |
| 	
 | |
| 	if (fetchMask)
 | |
| 	    mask_buffer = dest_buffer + data->width;
 | |
| 	
 | |
| 	for (i = 0; i < data->height; ++i) {
 | |
| 	    /* fill first half of scanline with source */
 | |
| 	    if (fetchSrc)
 | |
| 	    {
 | |
| 		if (fetchMask)
 | |
| 		{
 | |
| 		    /* fetch mask before source so that fetching of
 | |
| 		       source can be optimized */
 | |
| 		    fetchMask (data->mask, data->xMask, data->yMask + i,
 | |
| 			       data->width, mask_buffer, 0, 0);
 | |
| 		    
 | |
| 		    if (maskClass == SourcePictClassHorizontal)
 | |
| 			fetchMask = NULL;
 | |
| 		}
 | |
| 		
 | |
| 		if (srcClass == SourcePictClassHorizontal)
 | |
| 		{
 | |
| 		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
 | |
| 			      data->width, src_buffer, 0, 0);
 | |
| 		    
 | |
| 		    if (mask_buffer)
 | |
| 		    {
 | |
| 			fbCombineInU (mask_buffer, src_buffer, data->width);
 | |
| 			src_mask_buffer = mask_buffer;
 | |
| 		    }
 | |
| 		    else
 | |
| 			src_mask_buffer = src_buffer;
 | |
| 		    
 | |
| 		    fetchSrc = NULL;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 		    fetchSrc (data->src, data->xSrc, data->ySrc + i,
 | |
| 			      data->width, src_buffer, mask_buffer,
 | |
| 			      0xff000000);
 | |
| 		    
 | |
| 		    if (mask_buffer)
 | |
| 			composeFunctions.combineMaskU (src_buffer,
 | |
| 						       mask_buffer,
 | |
| 						       data->width);
 | |
| 		    
 | |
| 		    src_mask_buffer = src_buffer;
 | |
| 		}
 | |
| 	    }
 | |
| 	    else if (fetchMask)
 | |
| 	    {
 | |
| 		fetchMask (data->mask, data->xMask, data->yMask + i,
 | |
| 			   data->width, mask_buffer, 0, 0);
 | |
| 		
 | |
| 		fbCombineInU (mask_buffer, src_buffer, data->width);
 | |
| 		
 | |
| 		src_mask_buffer = mask_buffer;
 | |
| 	    }
 | |
| 	    
 | |
| 	    if (store)
 | |
| 	    {
 | |
| 		/* fill dest into second half of scanline */
 | |
| 		if (fetchDest)
 | |
| 		    fetchDest (data->dest, data->xDest, data->yDest + i,
 | |
| 			       data->width, dest_buffer, 0, 0);
 | |
| 		
 | |
| 		/* blend */
 | |
| 		compose (dest_buffer, src_mask_buffer, data->width);
 | |
| 		
 | |
| 		/* write back */
 | |
| 		store (data->dest, data->xDest, data->yDest + i, data->width,
 | |
| 		       dest_buffer);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		/* blend */
 | |
| 		compose (bits + (data->yDest + i+ yoff) * stride +
 | |
| 			 data->xDest + xoff,
 | |
| 			 src_mask_buffer, data->width);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     if (!store)
 | |
| 	fbFinishAccess (data->dest->pDrawable);
 | |
| }
 | |
| 
 | |
| void
 | |
| fbCompositeGeneral (CARD8	op,
 | |
| 		    PicturePtr	pSrc,
 | |
| 		    PicturePtr	pMask,
 | |
| 		    PicturePtr	pDst,
 | |
| 		    INT16	xSrc,
 | |
| 		    INT16	ySrc,
 | |
| 		    INT16	xMask,
 | |
| 		    INT16	yMask,
 | |
| 		    INT16	xDst,
 | |
| 		    INT16	yDst,
 | |
| 		    CARD16	width,
 | |
| 		    CARD16	height)
 | |
| {
 | |
|     RegionRec	    region;
 | |
|     int		    n;
 | |
|     BoxPtr	    pbox;
 | |
|     Bool	    srcRepeat = FALSE;
 | |
|     Bool	    maskRepeat = FALSE;
 | |
|     int		    w, h;
 | |
|     CARD32 _scanline_buffer[SCANLINE_BUFFER_LENGTH*3];
 | |
|     CARD32 *scanline_buffer = _scanline_buffer;
 | |
|     FbComposeData compose_data;
 | |
|     
 | |
|     if (pSrc->pDrawable)
 | |
|         srcRepeat = pSrc->repeatType == RepeatNormal && !pSrc->transform
 | |
| 	    && (pSrc->pDrawable->width != 1 || pSrc->pDrawable->height != 1);
 | |
| 
 | |
|     if (pMask && pMask->pDrawable)
 | |
| 	maskRepeat = pMask->repeatType == RepeatNormal && !pMask->transform
 | |
| 	    && (pMask->pDrawable->width != 1 || pMask->pDrawable->height != 1);
 | |
| 
 | |
|     if (op == PictOpOver && !pMask && !pSrc->transform && !PICT_FORMAT_A(pSrc->format) && !pSrc->alphaMap)
 | |
|         op = PictOpSrc;
 | |
| 
 | |
|     if (!miComputeCompositeRegion (®ion,
 | |
| 				   pSrc,
 | |
| 				   pMask,
 | |
| 				   pDst,
 | |
| 				   xSrc,
 | |
| 				   ySrc,
 | |
| 				   xMask,
 | |
| 				   yMask,
 | |
| 				   xDst,
 | |
| 				   yDst,
 | |
| 				   width,
 | |
| 				   height))
 | |
| 	return;
 | |
| 
 | |
|     compose_data.op = op;
 | |
|     compose_data.src = pSrc;
 | |
|     compose_data.mask = pMask;
 | |
|     compose_data.dest = pDst;
 | |
|     if (width > SCANLINE_BUFFER_LENGTH)
 | |
|         scanline_buffer = (CARD32 *) malloc(width * 3 * sizeof(CARD32));
 | |
| 
 | |
|     n = REGION_NUM_RECTS (®ion);
 | |
|     pbox = REGION_RECTS (®ion);
 | |
|     while (n--)
 | |
|     {
 | |
| 	h = pbox->y2 - pbox->y1;
 | |
| 	compose_data.ySrc = pbox->y1 - yDst + ySrc;
 | |
| 	compose_data.yMask = pbox->y1 - yDst + yMask;
 | |
| 	compose_data.yDest = pbox->y1;
 | |
| 	while (h)
 | |
| 	{
 | |
| 	    compose_data.height = h;
 | |
| 	    w = pbox->x2 - pbox->x1;
 | |
| 	    compose_data.xSrc = pbox->x1 - xDst + xSrc;
 | |
| 	    compose_data.xMask = pbox->x1 - xDst + xMask;
 | |
| 	    compose_data.xDest = pbox->x1;
 | |
| 	    if (maskRepeat)
 | |
| 	    {
 | |
| 		compose_data.yMask = mod (compose_data.yMask, pMask->pDrawable->height);
 | |
| 		if (compose_data.height > pMask->pDrawable->height - compose_data.yMask)
 | |
| 		    compose_data.height = pMask->pDrawable->height - compose_data.yMask;
 | |
| 	    }
 | |
| 	    if (srcRepeat)
 | |
| 	    {
 | |
| 		compose_data.ySrc = mod (compose_data.ySrc, pSrc->pDrawable->height);
 | |
| 		if (compose_data.height > pSrc->pDrawable->height - compose_data.ySrc)
 | |
| 		    compose_data.height = pSrc->pDrawable->height - compose_data.ySrc;
 | |
| 	    }
 | |
| 	    while (w)
 | |
| 	    {
 | |
| 		compose_data.width = w;
 | |
| 		if (maskRepeat)
 | |
| 		{
 | |
| 		    compose_data.xMask = mod (compose_data.xMask, pMask->pDrawable->width);
 | |
| 		    if (compose_data.width > pMask->pDrawable->width - compose_data.xMask)
 | |
| 			compose_data.width = pMask->pDrawable->width - compose_data.xMask;
 | |
| 		}
 | |
| 		if (srcRepeat)
 | |
| 		{
 | |
| 		    compose_data.xSrc = mod (compose_data.xSrc, pSrc->pDrawable->width);
 | |
| 		    if (compose_data.width > pSrc->pDrawable->width - compose_data.xSrc)
 | |
| 			compose_data.width = pSrc->pDrawable->width - compose_data.xSrc;
 | |
| 		}
 | |
| 		fbCompositeRect(&compose_data, scanline_buffer);
 | |
| 		w -= compose_data.width;
 | |
| 		compose_data.xSrc += compose_data.width;
 | |
| 		compose_data.xMask += compose_data.width;
 | |
| 		compose_data.xDest += compose_data.width;
 | |
| 	    }
 | |
| 	    h -= compose_data.height;
 | |
| 	    compose_data.ySrc += compose_data.height;
 | |
| 	    compose_data.yMask += compose_data.height;
 | |
| 	    compose_data.yDest += compose_data.height;
 | |
| 	}
 | |
| 	pbox++;
 | |
|     }
 | |
|     REGION_UNINIT (pDst->pDrawable->pScreen, ®ion);
 | |
| 
 | |
|     if (scanline_buffer != _scanline_buffer)
 | |
|         free(scanline_buffer);
 | |
| }
 | |
| 
 | |
| #endif
 |