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