src/video/SDL_blit_1.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 10 Feb 2006 06:48:43 +0000
changeset 1358 c71e05b4dc2e
parent 1330 450721ad5436
child 1402 d910939febfa
permissions -rw-r--r--
More header massaging... works great on Windows. ;-)
     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 
    23 #include "SDL_video.h"
    24 #include "SDL_blit.h"
    25 #include "SDL_sysvideo.h"
    26 #include "SDL_endian.h"
    27 
    28 /* Functions to blit from 8-bit surfaces to other surfaces */
    29 
    30 static void Blit1to1(SDL_BlitInfo *info)
    31 {
    32 #ifndef USE_DUFFS_LOOP
    33 	int c;
    34 #endif
    35 	int width, height;
    36 	Uint8 *src, *map, *dst;
    37 	int srcskip, dstskip;
    38 
    39 	/* Set up some basic variables */
    40 	width = info->d_width;
    41 	height = info->d_height;
    42 	src = info->s_pixels;
    43 	srcskip = info->s_skip;
    44 	dst = info->d_pixels;
    45 	dstskip = info->d_skip;
    46 	map = info->table;
    47 
    48 	while ( height-- ) {
    49 #ifdef USE_DUFFS_LOOP
    50 		DUFFS_LOOP(
    51 			{
    52 			  *dst = map[*src];
    53 			}
    54 			dst++;
    55 			src++;
    56 		, width);
    57 #else
    58 		for ( c=width; c; --c ) {
    59 		        *dst = map[*src];
    60 			dst++;
    61 			src++;
    62 		}
    63 #endif
    64 		src += srcskip;
    65 		dst += dstskip;
    66 	}
    67 }
    68 /* This is now endian dependent */
    69 #if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
    70 #define HI	1
    71 #define LO	0
    72 #else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
    73 #define HI	0
    74 #define LO	1
    75 #endif
    76 static void Blit1to2(SDL_BlitInfo *info)
    77 {
    78 #ifndef USE_DUFFS_LOOP
    79 	int c;
    80 #endif
    81 	int width, height;
    82 	Uint8 *src, *dst;
    83 	Uint16 *map;
    84 	int srcskip, dstskip;
    85 
    86 	/* Set up some basic variables */
    87 	width = info->d_width;
    88 	height = info->d_height;
    89 	src = info->s_pixels;
    90 	srcskip = info->s_skip;
    91 	dst = info->d_pixels;
    92 	dstskip = info->d_skip;
    93 	map = (Uint16 *)info->table;
    94 
    95 #ifdef USE_DUFFS_LOOP
    96 	while ( height-- ) {
    97 		DUFFS_LOOP(
    98 		{
    99 			*(Uint16 *)dst = map[*src++];
   100 			dst += 2;
   101 		},
   102 		width);
   103 		src += srcskip;
   104 		dst += dstskip;
   105 	}
   106 #else
   107 	/* Memory align at 4-byte boundary, if necessary */
   108 	if ( (long)dst & 0x03 ) {
   109 		/* Don't do anything if width is 0 */
   110 		if ( width == 0 ) {
   111 			return;
   112 		}
   113 		--width;
   114 
   115 		while ( height-- ) {
   116 			/* Perform copy alignment */
   117 			*(Uint16 *)dst = map[*src++];
   118 			dst += 2;
   119 
   120 			/* Copy in 4 pixel chunks */
   121 			for ( c=width/4; c; --c ) {
   122 				*(Uint32 *)dst =
   123 					(map[src[HI]]<<16)|(map[src[LO]]);
   124 				src += 2;
   125 				dst += 4;
   126 				*(Uint32 *)dst =
   127 					(map[src[HI]]<<16)|(map[src[LO]]);
   128 				src += 2;
   129 				dst += 4;
   130 			}
   131 			/* Get any leftovers */
   132 			switch (width & 3) {
   133 				case 3:
   134 					*(Uint16 *)dst = map[*src++];
   135 					dst += 2;
   136 				case 2:
   137 					*(Uint32 *)dst =
   138 					  (map[src[HI]]<<16)|(map[src[LO]]);
   139 					src += 2;
   140 					dst += 4;
   141 					break;
   142 				case 1:
   143 					*(Uint16 *)dst = map[*src++];
   144 					dst += 2;
   145 					break;
   146 			}
   147 			src += srcskip;
   148 			dst += dstskip;
   149 		}
   150 	} else { 
   151 		while ( height-- ) {
   152 			/* Copy in 4 pixel chunks */
   153 			for ( c=width/4; c; --c ) {
   154 				*(Uint32 *)dst =
   155 					(map[src[HI]]<<16)|(map[src[LO]]);
   156 				src += 2;
   157 				dst += 4;
   158 				*(Uint32 *)dst =
   159 					(map[src[HI]]<<16)|(map[src[LO]]);
   160 				src += 2;
   161 				dst += 4;
   162 			}
   163 			/* Get any leftovers */
   164 			switch (width & 3) {
   165 				case 3:
   166 					*(Uint16 *)dst = map[*src++];
   167 					dst += 2;
   168 				case 2:
   169 					*(Uint32 *)dst =
   170 					  (map[src[HI]]<<16)|(map[src[LO]]);
   171 					src += 2;
   172 					dst += 4;
   173 					break;
   174 				case 1:
   175 					*(Uint16 *)dst = map[*src++];
   176 					dst += 2;
   177 					break;
   178 			}
   179 			src += srcskip;
   180 			dst += dstskip;
   181 		}
   182 	}
   183 #endif /* USE_DUFFS_LOOP */
   184 }
   185 static void Blit1to3(SDL_BlitInfo *info)
   186 {
   187 #ifndef USE_DUFFS_LOOP
   188 	int c;
   189 #endif
   190 	int o;
   191 	int width, height;
   192 	Uint8 *src, *map, *dst;
   193 	int srcskip, dstskip;
   194 
   195 	/* Set up some basic variables */
   196 	width = info->d_width;
   197 	height = info->d_height;
   198 	src = info->s_pixels;
   199 	srcskip = info->s_skip;
   200 	dst = info->d_pixels;
   201 	dstskip = info->d_skip;
   202 	map = info->table;
   203 
   204 	while ( height-- ) {
   205 #ifdef USE_DUFFS_LOOP
   206 		DUFFS_LOOP(
   207 			{
   208 				o = *src * 4;
   209 				dst[0] = map[o++];
   210 				dst[1] = map[o++];
   211 				dst[2] = map[o++];
   212 			}
   213 			src++;
   214 			dst += 3;
   215 		, width);
   216 #else
   217 		for ( c=width; c; --c ) {
   218 			o = *src * 4;
   219 			dst[0] = map[o++];
   220 			dst[1] = map[o++];
   221 			dst[2] = map[o++];
   222 			src++;
   223 			dst += 3;
   224 		}
   225 #endif /* USE_DUFFS_LOOP */
   226 		src += srcskip;
   227 		dst += dstskip;
   228 	}
   229 }
   230 static void Blit1to4(SDL_BlitInfo *info)
   231 {
   232 #ifndef USE_DUFFS_LOOP
   233 	int c;
   234 #endif
   235 	int width, height;
   236 	Uint8 *src;
   237 	Uint32 *map, *dst;
   238 	int srcskip, dstskip;
   239 
   240 	/* Set up some basic variables */
   241 	width = info->d_width;
   242 	height = info->d_height;
   243 	src = info->s_pixels;
   244 	srcskip = info->s_skip;
   245 	dst = (Uint32 *)info->d_pixels;
   246 	dstskip = info->d_skip/4;
   247 	map = (Uint32 *)info->table;
   248 
   249 	while ( height-- ) {
   250 #ifdef USE_DUFFS_LOOP
   251 		DUFFS_LOOP(
   252 			*dst++ = map[*src++];
   253 		, width);
   254 #else
   255 		for ( c=width/4; c; --c ) {
   256 			*dst++ = map[*src++];
   257 			*dst++ = map[*src++];
   258 			*dst++ = map[*src++];
   259 			*dst++ = map[*src++];
   260 		}
   261 		switch ( width & 3 ) {
   262 			case 3:
   263 				*dst++ = map[*src++];
   264 			case 2:
   265 				*dst++ = map[*src++];
   266 			case 1:
   267 				*dst++ = map[*src++];
   268 		}
   269 #endif /* USE_DUFFS_LOOP */
   270 		src += srcskip;
   271 		dst += dstskip;
   272 	}
   273 }
   274 
   275 static void Blit1to1Key(SDL_BlitInfo *info)
   276 {
   277 	int width = info->d_width;
   278 	int height = info->d_height;
   279 	Uint8 *src = info->s_pixels;
   280 	int srcskip = info->s_skip;
   281 	Uint8 *dst = info->d_pixels;
   282 	int dstskip = info->d_skip;
   283 	Uint8 *palmap = info->table;
   284 	Uint32 ckey = info->src->colorkey;
   285         
   286 	if ( palmap ) {
   287 		while ( height-- ) {
   288 			DUFFS_LOOP(
   289 			{
   290 				if ( *src != ckey ) {
   291 				  *dst = palmap[*src];
   292 				}
   293 				dst++;
   294 				src++;
   295 			},
   296 			width);
   297 			src += srcskip;
   298 			dst += dstskip;
   299 		}
   300 	} else {
   301 		while ( height-- ) {
   302 			DUFFS_LOOP(
   303 			{
   304 				if ( *src != ckey ) {
   305 				  *dst = *src;
   306 				}
   307 				dst++;
   308 				src++;
   309 			},
   310 			width);
   311 			src += srcskip;
   312 			dst += dstskip;
   313 		}
   314 	}
   315 }
   316 
   317 static void Blit1to2Key(SDL_BlitInfo *info)
   318 {
   319 	int width = info->d_width;
   320 	int height = info->d_height;
   321 	Uint8 *src = info->s_pixels;
   322 	int srcskip = info->s_skip;
   323 	Uint16 *dstp = (Uint16 *)info->d_pixels;
   324 	int dstskip = info->d_skip;
   325 	Uint16 *palmap = (Uint16 *)info->table;
   326 	Uint32 ckey = info->src->colorkey;
   327 
   328 	/* Set up some basic variables */
   329 	dstskip /= 2;
   330 
   331 	while ( height-- ) {
   332 		DUFFS_LOOP(
   333 		{
   334 			if ( *src != ckey ) {
   335 				*dstp=palmap[*src];
   336 			}
   337 			src++;
   338 			dstp++;
   339 		},
   340 		width);
   341 		src += srcskip;
   342 		dstp += dstskip;
   343 	}
   344 }
   345 
   346 static void Blit1to3Key(SDL_BlitInfo *info)
   347 {
   348 	int width = info->d_width;
   349 	int height = info->d_height;
   350 	Uint8 *src = info->s_pixels;
   351 	int srcskip = info->s_skip;
   352 	Uint8 *dst = info->d_pixels;
   353 	int dstskip = info->d_skip;
   354 	Uint8 *palmap = info->table;
   355 	Uint32 ckey = info->src->colorkey;
   356 	int o;
   357 
   358 	while ( height-- ) {
   359 		DUFFS_LOOP(
   360 		{
   361 			if ( *src != ckey ) {
   362 				o = *src * 4;
   363 				dst[0] = palmap[o++];
   364 				dst[1] = palmap[o++];
   365 				dst[2] = palmap[o++];
   366 			}
   367 			src++;
   368 			dst += 3;
   369 		},
   370 		width);
   371 		src += srcskip;
   372 		dst += dstskip;
   373 	}
   374 }
   375 
   376 static void Blit1to4Key(SDL_BlitInfo *info)
   377 {
   378 	int width = info->d_width;
   379 	int height = info->d_height;
   380 	Uint8 *src = info->s_pixels;
   381 	int srcskip = info->s_skip;
   382 	Uint32 *dstp = (Uint32 *)info->d_pixels;
   383 	int dstskip = info->d_skip;
   384 	Uint32 *palmap = (Uint32 *)info->table;
   385 	Uint32 ckey = info->src->colorkey;
   386 
   387 	/* Set up some basic variables */
   388 	dstskip /= 4;
   389 
   390 	while ( height-- ) {
   391 		DUFFS_LOOP(
   392 		{
   393 			if ( *src != ckey ) {
   394 				*dstp = palmap[*src];
   395 			}
   396 			src++;
   397 			dstp++;
   398 		},
   399 		width);
   400 		src += srcskip;
   401 		dstp += dstskip;
   402 	}
   403 }
   404 
   405 static void Blit1toNAlpha(SDL_BlitInfo *info)
   406 {
   407 	int width = info->d_width;
   408 	int height = info->d_height;
   409 	Uint8 *src = info->s_pixels;
   410 	int srcskip = info->s_skip;
   411 	Uint8 *dst = info->d_pixels;
   412 	int dstskip = info->d_skip;
   413 	SDL_PixelFormat *dstfmt = info->dst;
   414 	const SDL_Color *srcpal	= info->src->palette->colors;
   415 	int dstbpp;
   416 	const int A = info->src->alpha;
   417 
   418 	/* Set up some basic variables */
   419 	dstbpp = dstfmt->BytesPerPixel;
   420 
   421 	while ( height-- ) {
   422 	        int sR, sG, sB;
   423 		int dR, dG, dB;
   424 	    	DUFFS_LOOP4(
   425 			{
   426 			        Uint32 pixel;
   427 				sR = srcpal[*src].r;
   428 				sG = srcpal[*src].g;
   429 				sB = srcpal[*src].b;
   430 				DISEMBLE_RGB(dst, dstbpp, dstfmt,
   431 					     pixel, dR, dG, dB);
   432 				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
   433 			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
   434 				src++;
   435 				dst += dstbpp;
   436 			},
   437 			width);
   438 		src += srcskip;
   439 		dst += dstskip;
   440 	}
   441 }
   442 
   443 static void Blit1toNAlphaKey(SDL_BlitInfo *info)
   444 {
   445 	int width = info->d_width;
   446 	int height = info->d_height;
   447 	Uint8 *src = info->s_pixels;
   448 	int srcskip = info->s_skip;
   449 	Uint8 *dst = info->d_pixels;
   450 	int dstskip = info->d_skip;
   451 	SDL_PixelFormat *srcfmt = info->src;
   452 	SDL_PixelFormat *dstfmt = info->dst;
   453 	const SDL_Color *srcpal	= info->src->palette->colors;
   454 	Uint32 ckey = srcfmt->colorkey;
   455 	int dstbpp;
   456 	const int A = srcfmt->alpha;
   457 
   458 	/* Set up some basic variables */
   459 	dstbpp = dstfmt->BytesPerPixel;
   460 
   461 	while ( height-- ) {
   462 	        int sR, sG, sB;
   463 		int dR, dG, dB;
   464 		DUFFS_LOOP(
   465 		{
   466 			if ( *src != ckey ) {
   467 			        Uint32 pixel;
   468 				sR = srcpal[*src].r;
   469 				sG = srcpal[*src].g;
   470 				sB = srcpal[*src].b;
   471 				DISEMBLE_RGB(dst, dstbpp, dstfmt,
   472 							pixel, dR, dG, dB);
   473 				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
   474 			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
   475 			}
   476 			src++;
   477 			dst += dstbpp;
   478 		},
   479 		width);
   480 		src += srcskip;
   481 		dst += dstskip;
   482 	}
   483 }
   484 
   485 static SDL_loblit one_blit[] = {
   486 	NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
   487 };
   488 
   489 static SDL_loblit one_blitkey[] = {
   490         NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
   491 };
   492 
   493 SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index)
   494 {
   495 	int which;
   496 	SDL_PixelFormat *dstfmt;
   497 
   498 	dstfmt = surface->map->dst->format;
   499 	if ( dstfmt->BitsPerPixel < 8 ) {
   500 		which = 0;
   501 	} else {
   502 		which = dstfmt->BytesPerPixel;
   503 	}
   504 	switch(blit_index) {
   505 	case 0:			/* copy */
   506 	    return one_blit[which];
   507 
   508 	case 1:			/* colorkey */
   509 	    return one_blitkey[which];
   510 
   511 	case 2:			/* alpha */
   512 	    /* Supporting 8bpp->8bpp alpha is doable but requires lots of
   513 	       tables which consume space and takes time to precompute,
   514 	       so is better left to the user */
   515 	    return which >= 2 ? Blit1toNAlpha : NULL;
   516 
   517 	case 3:			/* alpha + colorkey */
   518 	    return which >= 2 ? Blit1toNAlphaKey : NULL;
   519 
   520 	}
   521 	return NULL;
   522 }