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