src/video/SDL_blit_1.c
changeset 0 74212992fb08
child 91 e85e03f195b4
equal deleted inserted replaced
-1:000000000000 0:74212992fb08
       
     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@devolution.com
       
    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 % 4) {
       
   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 % 4) {
       
   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 % 4 ) {
       
   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 }