src/video/SDL_blit.h
author Sam Lantinga
Tue, 02 Dec 2008 17:14:04 +0000
changeset 2824 4dba7aa7ea77
parent 2267 c785543d1843
child 2853 6258fa7cd300
permissions -rw-r--r--
Added slow but complete blit fallback
Don't try to RLE encode surfaces that have alpha channel and alpha modulation
Don't turn on blending when converting an RGB surface to RGBA format
Do turn on blending when converting colorkey to alpha channel
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #ifndef _SDL_blit_h
    25 #define _SDL_blit_h
    26 
    27 #ifdef __MMX__
    28 #include <mmintrin.h>
    29 #endif
    30 #ifdef __3dNOW__
    31 #include <mm3dnow.h>
    32 #endif
    33 #ifdef __SSE__
    34 #include <xmmintrin.h>
    35 #endif
    36 #ifdef __SSE2__
    37 #include <emmintrin.h>
    38 #endif
    39 
    40 #include "SDL_cpuinfo.h"
    41 #include "SDL_endian.h"
    42 
    43 /* SDL blit copy flags */
    44 #define SDL_COPY_MODULATE_COLOR     0x00000001
    45 #define SDL_COPY_MODULATE_ALPHA     0x00000002
    46 #define SDL_COPY_MASK               0x00000010
    47 #define SDL_COPY_BLEND              0x00000020
    48 #define SDL_COPY_ADD                0x00000040
    49 #define SDL_COPY_MOD                0x00000080
    50 #define SDL_COPY_COLORKEY           0x00000100
    51 #define SDL_COPY_NEAREST            0x00000200
    52 #define SDL_COPY_RLE_DESIRED        0x00001000
    53 #define SDL_COPY_RLE_COLORKEY       0x00002000
    54 #define SDL_COPY_RLE_ALPHAKEY       0x00004000
    55 
    56 /* SDL blit CPU flags */
    57 #define SDL_CPU_ANY                 0x00000000
    58 #define SDL_CPU_MMX                 0x00000001
    59 #define SDL_CPU_3DNOW               0x00000002
    60 #define SDL_CPU_SSE                 0x00000004
    61 #define SDL_CPU_SSE2                0x00000008
    62 #define SDL_CPU_ALTIVEC_PREFETCH    0x00000010
    63 #define SDL_CPU_ALTIVEC_NOPREFETCH  0x00000020
    64 
    65 typedef struct
    66 {
    67     Uint8 *src;
    68     int src_w, src_h;
    69     int src_pitch;
    70     int src_skip;
    71     Uint8 *dst;
    72     int dst_w, dst_h;
    73     int dst_pitch;
    74     int dst_skip;
    75     SDL_PixelFormat *src_fmt;
    76     SDL_PixelFormat *dst_fmt;
    77     Uint8 *table;
    78     int flags;
    79     Uint32 colorkey;
    80     Uint8 r, g, b, a;
    81 } SDL_BlitInfo;
    82 
    83 typedef void (SDLCALL * SDL_BlitFunc) (SDL_BlitInfo * info);
    84 
    85 typedef struct
    86 {
    87     Uint32 src_format;
    88     Uint32 dst_format;
    89     int flags;
    90     int cpu;
    91     SDL_BlitFunc func;
    92 } SDL_BlitFuncEntry;
    93 
    94 /* Blit mapping definition */
    95 typedef struct SDL_BlitMap
    96 {
    97     SDL_Surface *dst;
    98     int identity;
    99     SDL_blit blit;
   100     void *data;
   101     SDL_BlitInfo info;
   102 
   103     /* the version count matches the destination; mismatch indicates
   104        an invalid mapping */
   105     unsigned int format_version;
   106 } SDL_BlitMap;
   107 
   108 /* Functions found in SDL_blit.c */
   109 extern int SDL_CalculateBlit(SDL_Surface * surface);
   110 
   111 /* Functions found in SDL_blit_*.c */
   112 extern SDL_BlitFunc SDL_CalculateBlit0(SDL_Surface * surface);
   113 extern SDL_BlitFunc SDL_CalculateBlit1(SDL_Surface * surface);
   114 extern SDL_BlitFunc SDL_CalculateBlitN(SDL_Surface * surface);
   115 extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface * surface);
   116 
   117 /*
   118  * Useful macros for blitting routines
   119  */
   120 
   121 #if defined(__GNUC__)
   122 #define DECLARE_ALIGNED(t,v,a)  t __attribute__((aligned(a))) v
   123 #elif defined(_MSC_VER)
   124 #define DECLARE_ALIGNED(t,v,a)  __declspec(align(a)) t v
   125 #else
   126 #define DECLARE_ALIGNED(t,v,a)  t v
   127 #endif
   128 
   129 #define FORMAT_EQUAL(A, B)						\
   130     ((A)->BitsPerPixel == (B)->BitsPerPixel				\
   131      && ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask))
   132 
   133 /* Load pixel of the specified format from a buffer and get its R-G-B values */
   134 /* FIXME: rescale values to 0..255 here? */
   135 #define RGB_FROM_PIXEL(Pixel, fmt, r, g, b)				\
   136 {									\
   137 	r = (((Pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); 		\
   138 	g = (((Pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); 		\
   139 	b = (((Pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); 		\
   140 }
   141 #define RGB_FROM_RGB565(Pixel, r, g, b)					\
   142 {									\
   143 	r = (((Pixel&0xF800)>>11)<<3);		 			\
   144 	g = (((Pixel&0x07E0)>>5)<<2); 					\
   145 	b = ((Pixel&0x001F)<<3); 					\
   146 }
   147 #define RGB_FROM_RGB555(Pixel, r, g, b)					\
   148 {									\
   149 	r = (((Pixel&0x7C00)>>10)<<3);		 			\
   150 	g = (((Pixel&0x03E0)>>5)<<3); 					\
   151 	b = ((Pixel&0x001F)<<3); 					\
   152 }
   153 #define RGB_FROM_RGB888(Pixel, r, g, b)					\
   154 {									\
   155 	r = ((Pixel&0xFF0000)>>16);		 			\
   156 	g = ((Pixel&0xFF00)>>8);		 			\
   157 	b = (Pixel&0xFF);			 			\
   158 }
   159 #define RETRIEVE_RGB_PIXEL(buf, bpp, Pixel)				   \
   160 do {									   \
   161 	switch (bpp) {							   \
   162 		case 2:							   \
   163 			Pixel = *((Uint16 *)(buf));			   \
   164 		break;							   \
   165 									   \
   166 		case 3: {						   \
   167 		        Uint8 *B = (Uint8 *)(buf);			   \
   168 			if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {		   \
   169 			        Pixel = B[0] + (B[1] << 8) + (B[2] << 16); \
   170 			} else {					   \
   171 			        Pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \
   172 			}						   \
   173 		}							   \
   174 		break;							   \
   175 									   \
   176 		case 4:							   \
   177 			Pixel = *((Uint32 *)(buf));			   \
   178 		break;							   \
   179 									   \
   180 		default:						   \
   181 		        Pixel; /* stop gcc complaints */		   \
   182 		break;							   \
   183 	}								   \
   184 } while (0)
   185 
   186 #define DISEMBLE_RGB(buf, bpp, fmt, Pixel, r, g, b)			   \
   187 do {									   \
   188 	switch (bpp) {							   \
   189 		case 2:							   \
   190 			Pixel = *((Uint16 *)(buf));			   \
   191 			RGB_FROM_PIXEL(Pixel, fmt, r, g, b);		   \
   192 		break;							   \
   193 									   \
   194 		case 3:	{						   \
   195                         if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {		   \
   196 			        r = *((buf)+fmt->Rshift/8);		   \
   197 				g = *((buf)+fmt->Gshift/8);		   \
   198 				b = *((buf)+fmt->Bshift/8);		   \
   199 			} else {					   \
   200 			        r = *((buf)+2-fmt->Rshift/8);		   \
   201 				g = *((buf)+2-fmt->Gshift/8);		   \
   202 				b = *((buf)+2-fmt->Bshift/8);		   \
   203 			}						   \
   204 		}							   \
   205 		break;							   \
   206 									   \
   207 		case 4:							   \
   208 			Pixel = *((Uint32 *)(buf));			   \
   209 			RGB_FROM_PIXEL(Pixel, fmt, r, g, b);		   \
   210 		break;							   \
   211 									   \
   212 		default:						   \
   213 		        Pixel; /* stop gcc complaints */		   \
   214 		break;							   \
   215 	}								   \
   216 } while (0)
   217 
   218 /* Assemble R-G-B values into a specified pixel format and store them */
   219 #define PIXEL_FROM_RGB(Pixel, fmt, r, g, b)				\
   220 {									\
   221 	Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)|				\
   222 		((g>>fmt->Gloss)<<fmt->Gshift)|				\
   223 		((b>>fmt->Bloss)<<fmt->Bshift);				\
   224 }
   225 #define RGB565_FROM_RGB(Pixel, r, g, b)					\
   226 {									\
   227 	Pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);			\
   228 }
   229 #define RGB555_FROM_RGB(Pixel, r, g, b)					\
   230 {									\
   231 	Pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3);			\
   232 }
   233 #define RGB888_FROM_RGB(Pixel, r, g, b)					\
   234 {									\
   235 	Pixel = (r<<16)|(g<<8)|b;					\
   236 }
   237 #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) 				\
   238 {									\
   239 	switch (bpp) {							\
   240 		case 2: {						\
   241 			Uint16 Pixel;					\
   242 									\
   243 			PIXEL_FROM_RGB(Pixel, fmt, r, g, b);		\
   244 			*((Uint16 *)(buf)) = Pixel;			\
   245 		}							\
   246 		break;							\
   247 									\
   248 		case 3: {						\
   249                         if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {		\
   250 			        *((buf)+fmt->Rshift/8) = r;		\
   251 				*((buf)+fmt->Gshift/8) = g;		\
   252 				*((buf)+fmt->Bshift/8) = b;		\
   253 			} else {					\
   254 			        *((buf)+2-fmt->Rshift/8) = r;		\
   255 				*((buf)+2-fmt->Gshift/8) = g;		\
   256 				*((buf)+2-fmt->Bshift/8) = b;		\
   257 			}						\
   258 		}							\
   259 		break;							\
   260 									\
   261 		case 4: {						\
   262 			Uint32 Pixel;					\
   263 									\
   264 			PIXEL_FROM_RGB(Pixel, fmt, r, g, b);		\
   265 			*((Uint32 *)(buf)) = Pixel;			\
   266 		}							\
   267 		break;							\
   268 	}								\
   269 }
   270 #define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask)		\
   271 {									\
   272 	switch (bpp) {							\
   273 		case 2: {						\
   274 			Uint16 *bufp;					\
   275 			Uint16 Pixel;					\
   276 									\
   277 			bufp = (Uint16 *)buf;				\
   278 			PIXEL_FROM_RGB(Pixel, fmt, r, g, b);		\
   279 			*bufp = Pixel | (*bufp & Amask);		\
   280 		}							\
   281 		break;							\
   282 									\
   283 		case 3: {						\
   284                         if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {		\
   285 			        *((buf)+fmt->Rshift/8) = r;		\
   286 				*((buf)+fmt->Gshift/8) = g;		\
   287 				*((buf)+fmt->Bshift/8) = b;		\
   288 			} else {					\
   289 			        *((buf)+2-fmt->Rshift/8) = r;		\
   290 				*((buf)+2-fmt->Gshift/8) = g;		\
   291 				*((buf)+2-fmt->Bshift/8) = b;		\
   292 			}						\
   293 		}							\
   294 		break;							\
   295 									\
   296 		case 4: {						\
   297 			Uint32 *bufp;					\
   298 			Uint32 Pixel;					\
   299 									\
   300 			bufp = (Uint32 *)buf;				\
   301 			PIXEL_FROM_RGB(Pixel, fmt, r, g, b);		\
   302 			*bufp = Pixel | (*bufp & Amask);		\
   303 		}							\
   304 		break;							\
   305 	}								\
   306 }
   307 
   308 /* FIXME: Should we rescale alpha into 0..255 here? */
   309 #define RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a)				\
   310 {									\
   311 	r = ((Pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; 		\
   312 	g = ((Pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; 		\
   313 	b = ((Pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; 		\
   314 	a = ((Pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss;	 	\
   315 }
   316 #define RGBA_FROM_8888(Pixel, fmt, r, g, b, a)	\
   317 {						\
   318 	r = (Pixel&fmt->Rmask)>>fmt->Rshift;	\
   319 	g = (Pixel&fmt->Gmask)>>fmt->Gshift;	\
   320 	b = (Pixel&fmt->Bmask)>>fmt->Bshift;	\
   321 	a = (Pixel&fmt->Amask)>>fmt->Ashift;	\
   322 }
   323 #define RGBA_FROM_RGBA8888(Pixel, r, g, b, a)				\
   324 {									\
   325 	r = (Pixel>>24);						\
   326 	g = ((Pixel>>16)&0xFF);						\
   327 	b = ((Pixel>>8)&0xFF);						\
   328 	a = (Pixel&0xFF);						\
   329 }
   330 #define RGBA_FROM_ARGB8888(Pixel, r, g, b, a)				\
   331 {									\
   332 	r = ((Pixel>>16)&0xFF);						\
   333 	g = ((Pixel>>8)&0xFF);						\
   334 	b = (Pixel&0xFF);						\
   335 	a = (Pixel>>24);						\
   336 }
   337 #define RGBA_FROM_ABGR8888(Pixel, r, g, b, a)				\
   338 {									\
   339 	r = (Pixel&0xFF);						\
   340 	g = ((Pixel>>8)&0xFF);						\
   341 	b = ((Pixel>>16)&0xFF);						\
   342 	a = (Pixel>>24);						\
   343 }
   344 #define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a)			   \
   345 do {									   \
   346 	switch (bpp) {							   \
   347 		case 2:							   \
   348 			Pixel = *((Uint16 *)(buf));			   \
   349 			RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a);	   \
   350 		break;							   \
   351 									   \
   352 		case 3:	{						   \
   353                         if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {		   \
   354 			        r = *((buf)+fmt->Rshift/8);		   \
   355 				g = *((buf)+fmt->Gshift/8);		   \
   356 				b = *((buf)+fmt->Bshift/8);		   \
   357 			} else {					   \
   358 			        r = *((buf)+2-fmt->Rshift/8);		   \
   359 				g = *((buf)+2-fmt->Gshift/8);		   \
   360 				b = *((buf)+2-fmt->Bshift/8);		   \
   361 			}						   \
   362 			a = 0xFF;					   \
   363 		}							   \
   364 		break;							   \
   365 									   \
   366 		case 4:							   \
   367 			Pixel = *((Uint32 *)(buf));			   \
   368 			RGBA_FROM_PIXEL(Pixel, fmt, r, g, b, a);	   \
   369 		break;							   \
   370 									   \
   371 		default:						   \
   372 		        Pixel; /* stop gcc complaints */		   \
   373 		break;							   \
   374 	}								   \
   375 } while (0)
   376 
   377 /* FIXME: this isn't correct, especially for Alpha (maximum != 255) */
   378 #define PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a)				\
   379 {									\
   380 	Pixel = ((r>>fmt->Rloss)<<fmt->Rshift)|				\
   381 		((g>>fmt->Gloss)<<fmt->Gshift)|				\
   382 		((b>>fmt->Bloss)<<fmt->Bshift)|				\
   383 		((a>>fmt->Aloss)<<fmt->Ashift);				\
   384 }
   385 #define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a)			\
   386 {									\
   387 	switch (bpp) {							\
   388 		case 2: {						\
   389 			Uint16 Pixel;					\
   390 									\
   391 			PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a);	\
   392 			*((Uint16 *)(buf)) = Pixel;			\
   393 		}							\
   394 		break;							\
   395 									\
   396 		case 3: {						\
   397                         if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {		\
   398 			        *((buf)+fmt->Rshift/8) = r;		\
   399 				*((buf)+fmt->Gshift/8) = g;		\
   400 				*((buf)+fmt->Bshift/8) = b;		\
   401 			} else {					\
   402 			        *((buf)+2-fmt->Rshift/8) = r;		\
   403 				*((buf)+2-fmt->Gshift/8) = g;		\
   404 				*((buf)+2-fmt->Bshift/8) = b;		\
   405 			}						\
   406 		}							\
   407 		break;							\
   408 									\
   409 		case 4: {						\
   410 			Uint32 Pixel;					\
   411 									\
   412 			PIXEL_FROM_RGBA(Pixel, fmt, r, g, b, a);	\
   413 			*((Uint32 *)(buf)) = Pixel;			\
   414 		}							\
   415 		break;							\
   416 	}								\
   417 }
   418 
   419 /* Blend the RGB values of two Pixels based on a source alpha value */
   420 #define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB)	\
   421 do {						\
   422 	dR = (((sR-dR)*(A))>>8)+dR;		\
   423 	dG = (((sG-dG)*(A))>>8)+dG;		\
   424 	dB = (((sB-dB)*(A))>>8)+dB;		\
   425 } while(0)
   426 
   427 /* Blend the RGB values of two Pixels based on a source alpha value */
   428 #define ACCURATE_ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB)	\
   429 do {						\
   430     unsigned tR, tG, tB, tA; \
   431     tA = 255 - sA; \
   432     tR = 1 + (sR * sA) + (dR * tA); \
   433     dR = (tR + (tR >> 8)) >> 8; \
   434     tG = 1 + (sG * sA) + (dG * tA); \
   435     dG = (tG + (tG >> 8)) >> 8; \
   436     tB = 1 + (sB * sA) + (dB * tA); \
   437     dB = (tB + (tB >> 8)) >> 8; \
   438 } while(0)
   439 
   440 
   441 /* This is a very useful loop for optimizing blitters */
   442 #if defined(_MSC_VER) && (_MSC_VER == 1300)
   443 /* There's a bug in the Visual C++ 7 optimizer when compiling this code */
   444 #else
   445 #define USE_DUFFS_LOOP
   446 #endif
   447 #ifdef USE_DUFFS_LOOP
   448 
   449 /* 8-times unrolled loop */
   450 #define DUFFS_LOOP8(pixel_copy_increment, width)			\
   451 { int n = (width+7)/8;							\
   452 	switch (width & 7) {						\
   453 	case 0: do {	pixel_copy_increment;				\
   454 	case 7:		pixel_copy_increment;				\
   455 	case 6:		pixel_copy_increment;				\
   456 	case 5:		pixel_copy_increment;				\
   457 	case 4:		pixel_copy_increment;				\
   458 	case 3:		pixel_copy_increment;				\
   459 	case 2:		pixel_copy_increment;				\
   460 	case 1:		pixel_copy_increment;				\
   461 		} while ( --n > 0 );					\
   462 	}								\
   463 }
   464 
   465 /* 4-times unrolled loop */
   466 #define DUFFS_LOOP4(pixel_copy_increment, width)			\
   467 { int n = (width+3)/4;							\
   468 	switch (width & 3) {						\
   469 	case 0: do {	pixel_copy_increment;				\
   470 	case 3:		pixel_copy_increment;				\
   471 	case 2:		pixel_copy_increment;				\
   472 	case 1:		pixel_copy_increment;				\
   473 		} while ( --n > 0 );					\
   474 	}								\
   475 }
   476 
   477 /* 2 - times unrolled loop */
   478 #define DUFFS_LOOP_DOUBLE2(pixel_copy_increment,			\
   479 				double_pixel_copy_increment, width)	\
   480 { int n, w = width;							\
   481 	if( w & 1 ) {							\
   482 	    pixel_copy_increment;					\
   483 	    w--;							\
   484 	}								\
   485 	if ( w > 0 )	{						\
   486 	    n = ( w + 2) / 4;						\
   487 	    switch( w & 2 ) {						\
   488 	    case 0: do {	double_pixel_copy_increment;		\
   489 	    case 2:		double_pixel_copy_increment;		\
   490 		    } while ( --n > 0 );					\
   491 	    }								\
   492 	}								\
   493 }
   494 
   495 /* 2 - times unrolled loop 4 pixels */
   496 #define DUFFS_LOOP_QUATRO2(pixel_copy_increment,			\
   497 				double_pixel_copy_increment,		\
   498 				quatro_pixel_copy_increment, width)	\
   499 { int n, w = width;								\
   500         if(w & 1) {							\
   501 	  pixel_copy_increment;						\
   502 	  w--;								\
   503 	}								\
   504 	if(w & 2) {							\
   505 	  double_pixel_copy_increment;					\
   506 	  w -= 2;							\
   507 	}								\
   508 	if ( w > 0 ) {							\
   509 	    n = ( w + 7 ) / 8;						\
   510 	    switch( w & 4 ) {						\
   511 	    case 0: do {	quatro_pixel_copy_increment;		\
   512 	    case 4:		quatro_pixel_copy_increment;		\
   513 		    } while ( --n > 0 );					\
   514 	    }								\
   515 	}								\
   516 }
   517 
   518 /* Use the 8-times version of the loop by default */
   519 #define DUFFS_LOOP(pixel_copy_increment, width)				\
   520 	DUFFS_LOOP8(pixel_copy_increment, width)
   521 
   522 #else
   523 
   524 /* Don't use Duff's device to unroll loops */
   525 #define DUFFS_LOOP_DOUBLE2(pixel_copy_increment,			\
   526 			 double_pixel_copy_increment, width)		\
   527 { int n = width;								\
   528     if( n & 1 ) {							\
   529 	pixel_copy_increment;						\
   530 	n--;								\
   531     }									\
   532     n=n>>1;								\
   533     for(; n > 0; --n) {   						\
   534 	double_pixel_copy_increment;					\
   535     }									\
   536 }
   537 
   538 /* Don't use Duff's device to unroll loops */
   539 #define DUFFS_LOOP_QUATRO2(pixel_copy_increment,			\
   540 				double_pixel_copy_increment,		\
   541 				quatro_pixel_copy_increment, width)	\
   542 { int n = width;								\
   543         if(n & 1) {							\
   544 	  pixel_copy_increment;						\
   545 	  n--;								\
   546 	}								\
   547 	if(n & 2) {							\
   548 	  double_pixel_copy_increment;					\
   549 	  n -= 2;							\
   550 	}								\
   551 	n=n>>2;								\
   552 	for(; n > 0; --n) {   						\
   553 	  quatro_pixel_copy_increment;					\
   554         }								\
   555 }
   556 
   557 /* Don't use Duff's device to unroll loops */
   558 #define DUFFS_LOOP(pixel_copy_increment, width)				\
   559 { int n;								\
   560 	for ( n=width; n > 0; --n ) {					\
   561 		pixel_copy_increment;					\
   562 	}								\
   563 }
   564 #define DUFFS_LOOP8(pixel_copy_increment, width)			\
   565 	DUFFS_LOOP(pixel_copy_increment, width)
   566 #define DUFFS_LOOP4(pixel_copy_increment, width)			\
   567 	DUFFS_LOOP(pixel_copy_increment, width)
   568 
   569 #endif /* USE_DUFFS_LOOP */
   570 
   571 /* Prevent Visual C++ 6.0 from printing out stupid warnings */
   572 #if defined(_MSC_VER) && (_MSC_VER >= 600)
   573 #pragma warning(disable: 4550)
   574 #endif
   575 
   576 #endif /* _SDL_blit_h */
   577 /* vi: set ts=4 sw=4 expandtab: */