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