diff src/video/SDL_blit.h @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children e85e03f195b4
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/SDL_blit.h	Thu Apr 26 16:45:43 2001 +0000
@@ -0,0 +1,437 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+#ifndef _SDL_blit_h
+#define _SDL_blit_h
+
+#include "SDL_endian.h"
+
+/* The structure passed to the low level blit functions */
+typedef struct {
+	Uint8 *s_pixels;
+	int s_width;
+	int s_height;
+	int s_skip;
+	Uint8 *d_pixels;
+	int d_width;
+	int d_height;
+	int d_skip;
+	void *aux_data;
+	SDL_PixelFormat *src;
+	Uint8 *table;
+	SDL_PixelFormat *dst;
+} SDL_BlitInfo;
+
+/* The type definition for the low level blit functions */
+typedef void (*SDL_loblit)(SDL_BlitInfo *info);
+
+/* This is the private info structure for software accelerated blits */
+struct private_swaccel {
+	SDL_loblit blit;
+	void *aux_data;
+};
+
+/* Blit mapping definition */
+typedef struct SDL_BlitMap {
+	SDL_Surface *dst;
+	int identity;
+	Uint8 *table;
+	SDL_blit hw_blit;
+	SDL_blit sw_blit;
+	struct private_hwaccel *hw_data;
+	struct private_swaccel *sw_data;
+
+	/* the version count matches the destination; mismatch indicates
+	   an invalid mapping */
+        unsigned int format_version;
+} SDL_BlitMap;
+
+
+/* Definitions for special global blit functions */
+#include "SDL_blit_A.h"
+
+/* Functions found in SDL_blit.c */
+extern int SDL_CalculateBlit(SDL_Surface *surface);
+
+/* Functions found in SDL_blit_{0,1,N,A}.c */
+extern SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int complex);
+extern SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int complex);
+extern SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex);
+extern SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int complex);
+
+/*
+ * Useful macros for blitting routines
+ */
+
+#define FORMAT_EQUAL(A, B)						\
+    ((A)->BitsPerPixel == (B)->BitsPerPixel				\
+     && ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask))
+
+/* Load pixel of the specified format from a buffer and get its R-G-B values */
+/* FIXME: rescale values to 0..255 here? */
+#define RGB_FROM_PIXEL(pixel, fmt, r, g, b)				\
+{									\
+	r = (((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); 		\
+	g = (((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); 		\
+	b = (((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); 		\
+}
+#define RGB_FROM_RGB565(pixel, r, g, b)					\
+{									\
+	r = (((pixel&0xF800)>>11)<<3);		 			\
+	g = (((pixel&0x07E0)>>5)<<2); 					\
+	b = ((pixel&0x001F)<<3); 					\
+}
+#define RGB_FROM_RGB555(pixel, r, g, b)					\
+{									\
+	r = (((pixel&0x7C00)>>10)<<3);		 			\
+	g = (((pixel&0x03E0)>>5)<<3); 					\
+	b = ((pixel&0x001F)<<3); 					\
+}
+#define RGB_FROM_RGB888(pixel, r, g, b)					\
+{									\
+	r = ((pixel&0xFF0000)>>16);		 			\
+	g = ((pixel&0xFF00)>>8);		 			\
+	b = (pixel&0xFF);			 			\
+}
+#define RETRIEVE_RGB_PIXEL(buf, bpp, pixel)				   \
+do {									   \
+	switch (bpp) {							   \
+		case 2:							   \
+			pixel = *((Uint16 *)(buf));			   \
+		break;							   \
+									   \
+		case 3: {						   \
+		        Uint8 *B = (Uint8 *)(buf);			   \
+			if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {		   \
+			        pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
+			} else {					   \
+			        pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
+			}						   \
+		}							   \
+		break;							   \
+									   \
+		case 4:							   \
+			pixel = *((Uint32 *)(buf));			   \
+		break;							   \
+									   \
+		default:						   \
+			pixel = 0; /* appease gcc */			   \
+		break;							   \
+	}								   \
+} while(0)
+
+#define DISEMBLE_RGB(buf, bpp, fmt, pixel, r, g, b)			   \
+do {									   \
+	switch (bpp) {							   \
+		case 2:							   \
+			pixel = *((Uint16 *)(buf));			   \
+		break;							   \
+									   \
+		case 3: {						   \
+		        Uint8 *B = (Uint8 *)buf;			   \
+			if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {		   \
+			        pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
+			} else {					   \
+			        pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
+			}						   \
+		}							   \
+		break;							   \
+									   \
+		case 4:							   \
+			pixel = *((Uint32 *)(buf));			   \
+		break;							   \
+									   \
+	        default:						   \
+		        pixel = 0;	/* prevent gcc from complaining */ \
+		break;							   \
+	}								   \
+	RGB_FROM_PIXEL(pixel, fmt, r, g, b);				   \
+} while(0)
+
+/* Assemble R-G-B values into a specified pixel format and store them */
+#define PIXEL_FROM_RGB(pixel, fmt, r, g, b)				\
+{									\
+	pixel = ((r>>fmt->Rloss)<<fmt->Rshift)|				\
+		((g>>fmt->Gloss)<<fmt->Gshift)|				\
+		((b>>fmt->Bloss)<<fmt->Bshift);				\
+}
+#define RGB565_FROM_RGB(pixel, r, g, b)					\
+{									\
+	pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);			\
+}
+#define RGB555_FROM_RGB(pixel, r, g, b)					\
+{									\
+	pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3);			\
+}
+#define RGB888_FROM_RGB(pixel, r, g, b)					\
+{									\
+	pixel = (r<<16)|(g<<8)|b;					\
+}
+#define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) 				\
+{									\
+	switch (bpp) {							\
+		case 2: {						\
+			Uint16 pixel;					\
+									\
+			PIXEL_FROM_RGB(pixel, fmt, r, g, b);		\
+			*((Uint16 *)(buf)) = pixel;			\
+		}							\
+		break;							\
+									\
+		case 3: {						\
+                        if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {		\
+			        *((buf)+fmt->Rshift/8) = r;		\
+				*((buf)+fmt->Gshift/8) = g;		\
+				*((buf)+fmt->Bshift/8) = b;		\
+			} else {					\
+			        *((buf)+2-fmt->Rshift/8) = r;		\
+				*((buf)+2-fmt->Gshift/8) = g;		\
+				*((buf)+2-fmt->Bshift/8) = b;		\
+			}						\
+		}							\
+		break;							\
+									\
+		case 4: {						\
+			Uint32 pixel;					\
+									\
+			PIXEL_FROM_RGB(pixel, fmt, r, g, b);		\
+			*((Uint32 *)(buf)) = pixel;			\
+		}							\
+		break;							\
+	}								\
+}
+#define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask)		\
+{									\
+	switch (bpp) {							\
+		case 2: {						\
+			Uint16 *bufp;					\
+			Uint16 pixel;					\
+									\
+			bufp = (Uint16 *)buf;				\
+			PIXEL_FROM_RGB(pixel, fmt, r, g, b);		\
+			*bufp = pixel | (*bufp & Amask);		\
+		}							\
+		break;							\
+									\
+		case 3: {						\
+                        if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {		\
+			        *((buf)+fmt->Rshift/8) = r;		\
+				*((buf)+fmt->Gshift/8) = g;		\
+				*((buf)+fmt->Bshift/8) = b;		\
+			} else {					\
+			        *((buf)+2-fmt->Rshift/8) = r;		\
+				*((buf)+2-fmt->Gshift/8) = g;		\
+				*((buf)+2-fmt->Bshift/8) = b;		\
+			}						\
+		}							\
+		break;							\
+									\
+		case 4: {						\
+			Uint32 *bufp;					\
+			Uint32 pixel;					\
+									\
+			bufp = (Uint32 *)buf;				\
+			PIXEL_FROM_RGB(pixel, fmt, r, g, b);		\
+			*bufp = pixel | (*bufp & Amask);		\
+		}							\
+		break;							\
+	}								\
+}
+
+/* FIXME: Should we rescale alpha into 0..255 here? */
+#define RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a)				\
+{									\
+	r = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; 		\
+	g = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; 		\
+	b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; 		\
+	a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss;	 	\
+}
+#define RGBA_FROM_8888(pixel, fmt, r, g, b, a)	\
+{						\
+	r = (pixel&fmt->Rmask)>>fmt->Rshift;	\
+	g = (pixel&fmt->Gmask)>>fmt->Gshift;	\
+	b = (pixel&fmt->Bmask)>>fmt->Bshift;	\
+	a = (pixel&fmt->Amask)>>fmt->Ashift;	\
+}
+#define RGBA_FROM_RGBA8888(pixel, r, g, b, a)				\
+{									\
+	r = (pixel>>24);						\
+	g = ((pixel>>16)&0xFF);						\
+	b = ((pixel>>8)&0xFF);						\
+	a = (pixel&0xFF);						\
+}
+#define RGBA_FROM_ARGB8888(pixel, r, g, b, a)				\
+{									\
+	r = ((pixel>>16)&0xFF);						\
+	g = ((pixel>>8)&0xFF);						\
+	b = (pixel&0xFF);						\
+	a = (pixel>>24);						\
+}
+#define RGBA_FROM_ABGR8888(pixel, r, g, b, a)				\
+{									\
+	r = (pixel&0xFF);						\
+	g = ((pixel>>8)&0xFF);						\
+	b = ((pixel>>16)&0xFF);						\
+	a = (pixel>>24);						\
+}
+#define DISEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a)			   \
+do {									   \
+	switch (bpp) {							   \
+		case 2:							   \
+			pixel = *((Uint16 *)(buf));			   \
+		break;							   \
+									   \
+		case 3:	{/* FIXME: broken code (no alpha) */		   \
+		        Uint8 *b = (Uint8 *)buf;			   \
+			if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {		   \
+			        pixel = b[0] + (b[1] << 8) + (b[2] << 16); \
+			} else {					   \
+			        pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \
+			}						   \
+		}							   \
+		break;							   \
+									   \
+		case 4:							   \
+			pixel = *((Uint32 *)(buf));			   \
+		break;							   \
+									   \
+		default:						   \
+		        pixel = 0; /* stop gcc complaints */		   \
+		break;							   \
+	}								   \
+	RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a);			   \
+	pixel &= ~fmt->Amask;						   \
+} while(0)
+
+/* FIXME: this isn't correct, especially for Alpha (maximum != 255) */
+#define PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a)				\
+{									\
+	pixel = ((r>>fmt->Rloss)<<fmt->Rshift)|				\
+		((g>>fmt->Gloss)<<fmt->Gshift)|				\
+		((b>>fmt->Bloss)<<fmt->Bshift)|				\
+		((a<<fmt->Aloss)<<fmt->Ashift);				\
+}
+#define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a)			\
+{									\
+	switch (bpp) {							\
+		case 2: {						\
+			Uint16 pixel;					\
+									\
+			PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a);	\
+			*((Uint16 *)(buf)) = pixel;			\
+		}							\
+		break;							\
+									\
+		case 3: { /* FIXME: broken code (no alpha) */		\
+                        if(SDL_BYTEORDER == SDL_LIL_ENDIAN) {		\
+			        *((buf)+fmt->Rshift/8) = r;		\
+				*((buf)+fmt->Gshift/8) = g;		\
+				*((buf)+fmt->Bshift/8) = b;		\
+			} else {					\
+			        *((buf)+2-fmt->Rshift/8) = r;		\
+				*((buf)+2-fmt->Gshift/8) = g;		\
+				*((buf)+2-fmt->Bshift/8) = b;		\
+			}						\
+		}							\
+		break;							\
+									\
+		case 4: {						\
+			Uint32 pixel;					\
+									\
+			PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a);	\
+			*((Uint32 *)(buf)) = pixel;			\
+		}							\
+		break;							\
+	}								\
+}
+
+/* Blend the RGB values of two pixels based on a source alpha value */
+#define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB)	\
+do {						\
+	dR = (((sR-dR)*(A))>>8)+dR;		\
+	dG = (((sG-dG)*(A))>>8)+dG;		\
+	dB = (((sB-dB)*(A))>>8)+dB;		\
+} while(0)
+
+/* This is a very useful loop for optimizing blitters */
+#define USE_DUFFS_LOOP
+#ifdef USE_DUFFS_LOOP
+
+/* 8-times unrolled loop */
+#define DUFFS_LOOP8(pixel_copy_increment, width)			\
+{ int n = (width+7)/8;							\
+	switch (width % 8) {						\
+	case 0: do {	pixel_copy_increment;				\
+	case 7:		pixel_copy_increment;				\
+	case 6:		pixel_copy_increment;				\
+	case 5:		pixel_copy_increment;				\
+	case 4:		pixel_copy_increment;				\
+	case 3:		pixel_copy_increment;				\
+	case 2:		pixel_copy_increment;				\
+	case 1:		pixel_copy_increment;				\
+		} while ( --n > 0 );					\
+	}								\
+}
+
+/* 4-times unrolled loop */
+#define DUFFS_LOOP4(pixel_copy_increment, width)			\
+{ int n = (width+3)/4;							\
+	switch (width % 4) {						\
+	case 0: do {	pixel_copy_increment;				\
+	case 3:		pixel_copy_increment;				\
+	case 2:		pixel_copy_increment;				\
+	case 1:		pixel_copy_increment;				\
+		} while ( --n > 0 );					\
+	}								\
+}
+
+/* Use the 8-times version of the loop by default */
+#define DUFFS_LOOP(pixel_copy_increment, width)				\
+	DUFFS_LOOP8(pixel_copy_increment, width)
+
+#else
+
+/* Don't use Duff's device to unroll loops */
+#define DUFFS_LOOP(pixel_copy_increment, width)				\
+{ int n;								\
+	for ( n=width; n > 0; --n ) {					\
+		pixel_copy_increment;					\
+	}								\
+}
+#define DUFFS_LOOP8(pixel_copy_increment, width)			\
+	DUFFS_LOOP(pixel_copy_increment, width)
+#define DUFFS_LOOP4(pixel_copy_increment, width)			\
+	DUFFS_LOOP(pixel_copy_increment, width)
+
+#endif /* USE_DUFFS_LOOP */
+
+/* Prevent Visual C++ 6.0 from printing out stupid warnings */
+#if defined(_MSC_VER) && (_MSC_VER >= 600)
+#pragma warning(disable: 4550)
+#endif
+
+#endif /* _SDL_blit_h */