src/video/SDL_blit_1.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1402 d910939febfa
child 2257 340942cfda48
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
     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 #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
    32 Blit1to1(SDL_BlitInfo * info)
    33 {
    34 #ifndef USE_DUFFS_LOOP
    35     int c;
    36 #endif
    37     int width, height;
    38     Uint8 *src, *map, *dst;
    39     int srcskip, dstskip;
    40 
    41     /* Set up some basic variables */
    42     width = info->d_width;
    43     height = info->d_height;
    44     src = info->s_pixels;
    45     srcskip = info->s_skip;
    46     dst = info->d_pixels;
    47     dstskip = info->d_skip;
    48     map = info->table;
    49 
    50     while (height--) {
    51 #ifdef USE_DUFFS_LOOP
    52         /* *INDENT-OFF* */
    53 		DUFFS_LOOP(
    54 			{
    55 			  *dst = map[*src];
    56 			}
    57 			dst++;
    58 			src++;
    59 		, width);
    60         /* *INDENT-ON* */
    61 #else
    62         for (c = width; c; --c) {
    63             *dst = map[*src];
    64             dst++;
    65             src++;
    66         }
    67 #endif
    68         src += srcskip;
    69         dst += dstskip;
    70     }
    71 }
    72 
    73 /* This is now endian dependent */
    74 #if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
    75 #define HI	1
    76 #define LO	0
    77 #else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
    78 #define HI	0
    79 #define LO	1
    80 #endif
    81 static void
    82 Blit1to2(SDL_BlitInfo * info)
    83 {
    84 #ifndef USE_DUFFS_LOOP
    85     int c;
    86 #endif
    87     int width, height;
    88     Uint8 *src, *dst;
    89     Uint16 *map;
    90     int srcskip, dstskip;
    91 
    92     /* Set up some basic variables */
    93     width = info->d_width;
    94     height = info->d_height;
    95     src = info->s_pixels;
    96     srcskip = info->s_skip;
    97     dst = info->d_pixels;
    98     dstskip = info->d_skip;
    99     map = (Uint16 *) info->table;
   100 
   101 #ifdef USE_DUFFS_LOOP
   102     while (height--) {
   103 		/* *INDENT-OFF* */
   104 		DUFFS_LOOP(
   105 		{
   106 			*(Uint16 *)dst = map[*src++];
   107 			dst += 2;
   108 		},
   109 		width);
   110 		/* *INDENT-ON* */
   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 = (map[src[HI]] << 16) | (map[src[LO]]);
   131                 src += 2;
   132                 dst += 4;
   133                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   134                 src += 2;
   135                 dst += 4;
   136             }
   137             /* Get any leftovers */
   138             switch (width & 3) {
   139             case 3:
   140                 *(Uint16 *) dst = map[*src++];
   141                 dst += 2;
   142             case 2:
   143                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   144                 src += 2;
   145                 dst += 4;
   146                 break;
   147             case 1:
   148                 *(Uint16 *) dst = map[*src++];
   149                 dst += 2;
   150                 break;
   151             }
   152             src += srcskip;
   153             dst += dstskip;
   154         }
   155     } else {
   156         while (height--) {
   157             /* Copy in 4 pixel chunks */
   158             for (c = width / 4; c; --c) {
   159                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   160                 src += 2;
   161                 dst += 4;
   162                 *(Uint32 *) dst = (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 = (map[src[HI]] << 16) | (map[src[LO]]);
   173                 src += 2;
   174                 dst += 4;
   175                 break;
   176             case 1:
   177                 *(Uint16 *) dst = map[*src++];
   178                 dst += 2;
   179                 break;
   180             }
   181             src += srcskip;
   182             dst += dstskip;
   183         }
   184     }
   185 #endif /* USE_DUFFS_LOOP */
   186 }
   187 static void
   188 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 		/* *INDENT-OFF* */
   210 		DUFFS_LOOP(
   211 			{
   212 				o = *src * 4;
   213 				dst[0] = map[o++];
   214 				dst[1] = map[o++];
   215 				dst[2] = map[o++];
   216 			}
   217 			src++;
   218 			dst += 3;
   219 		, width);
   220 		/* *INDENT-ON* */
   221 #else
   222         for (c = width; c; --c) {
   223             o = *src * 4;
   224             dst[0] = map[o++];
   225             dst[1] = map[o++];
   226             dst[2] = map[o++];
   227             src++;
   228             dst += 3;
   229         }
   230 #endif /* USE_DUFFS_LOOP */
   231         src += srcskip;
   232         dst += dstskip;
   233     }
   234 }
   235 static void
   236 Blit1to4(SDL_BlitInfo * info)
   237 {
   238 #ifndef USE_DUFFS_LOOP
   239     int c;
   240 #endif
   241     int width, height;
   242     Uint8 *src;
   243     Uint32 *map, *dst;
   244     int srcskip, dstskip;
   245 
   246     /* Set up some basic variables */
   247     width = info->d_width;
   248     height = info->d_height;
   249     src = info->s_pixels;
   250     srcskip = info->s_skip;
   251     dst = (Uint32 *) info->d_pixels;
   252     dstskip = info->d_skip / 4;
   253     map = (Uint32 *) info->table;
   254 
   255     while (height--) {
   256 #ifdef USE_DUFFS_LOOP
   257 		/* *INDENT-OFF* */
   258 		DUFFS_LOOP(
   259 			*dst++ = map[*src++];
   260 		, width);
   261 		/* *INDENT-ON* */
   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
   284 Blit1to1Key(SDL_BlitInfo * info)
   285 {
   286     int width = info->d_width;
   287     int height = info->d_height;
   288     Uint8 *src = info->s_pixels;
   289     int srcskip = info->s_skip;
   290     Uint8 *dst = info->d_pixels;
   291     int dstskip = info->d_skip;
   292     Uint8 *palmap = info->table;
   293     Uint32 ckey = info->src->colorkey;
   294 
   295     if (palmap) {
   296         while (height--) {
   297 			/* *INDENT-OFF* */
   298 			DUFFS_LOOP(
   299 			{
   300 				if ( *src != ckey ) {
   301 				  *dst = palmap[*src];
   302 				}
   303 				dst++;
   304 				src++;
   305 			},
   306 			width);
   307 			/* *INDENT-ON* */
   308             src += srcskip;
   309             dst += dstskip;
   310         }
   311     } else {
   312         while (height--) {
   313 			/* *INDENT-OFF* */
   314 			DUFFS_LOOP(
   315 			{
   316 				if ( *src != ckey ) {
   317 				  *dst = *src;
   318 				}
   319 				dst++;
   320 				src++;
   321 			},
   322 			width);
   323 			/* *INDENT-ON* */
   324             src += srcskip;
   325             dst += dstskip;
   326         }
   327     }
   328 }
   329 
   330 static void
   331 Blit1to2Key(SDL_BlitInfo * info)
   332 {
   333     int width = info->d_width;
   334     int height = info->d_height;
   335     Uint8 *src = info->s_pixels;
   336     int srcskip = info->s_skip;
   337     Uint16 *dstp = (Uint16 *) info->d_pixels;
   338     int dstskip = info->d_skip;
   339     Uint16 *palmap = (Uint16 *) info->table;
   340     Uint32 ckey = info->src->colorkey;
   341 
   342     /* Set up some basic variables */
   343     dstskip /= 2;
   344 
   345     while (height--) {
   346 		/* *INDENT-OFF* */
   347 		DUFFS_LOOP(
   348 		{
   349 			if ( *src != ckey ) {
   350 				*dstp=palmap[*src];
   351 			}
   352 			src++;
   353 			dstp++;
   354 		},
   355 		width);
   356 		/* *INDENT-ON* */
   357         src += srcskip;
   358         dstp += dstskip;
   359     }
   360 }
   361 
   362 static void
   363 Blit1to3Key(SDL_BlitInfo * info)
   364 {
   365     int width = info->d_width;
   366     int height = info->d_height;
   367     Uint8 *src = info->s_pixels;
   368     int srcskip = info->s_skip;
   369     Uint8 *dst = info->d_pixels;
   370     int dstskip = info->d_skip;
   371     Uint8 *palmap = info->table;
   372     Uint32 ckey = info->src->colorkey;
   373     int o;
   374 
   375     while (height--) {
   376 		/* *INDENT-OFF* */
   377 		DUFFS_LOOP(
   378 		{
   379 			if ( *src != ckey ) {
   380 				o = *src * 4;
   381 				dst[0] = palmap[o++];
   382 				dst[1] = palmap[o++];
   383 				dst[2] = palmap[o++];
   384 			}
   385 			src++;
   386 			dst += 3;
   387 		},
   388 		width);
   389 		/* *INDENT-ON* */
   390         src += srcskip;
   391         dst += dstskip;
   392     }
   393 }
   394 
   395 static void
   396 Blit1to4Key(SDL_BlitInfo * info)
   397 {
   398     int width = info->d_width;
   399     int height = info->d_height;
   400     Uint8 *src = info->s_pixels;
   401     int srcskip = info->s_skip;
   402     Uint32 *dstp = (Uint32 *) info->d_pixels;
   403     int dstskip = info->d_skip;
   404     Uint32 *palmap = (Uint32 *) info->table;
   405     Uint32 ckey = info->src->colorkey;
   406 
   407     /* Set up some basic variables */
   408     dstskip /= 4;
   409 
   410     while (height--) {
   411 		/* *INDENT-OFF* */
   412 		DUFFS_LOOP(
   413 		{
   414 			if ( *src != ckey ) {
   415 				*dstp = palmap[*src];
   416 			}
   417 			src++;
   418 			dstp++;
   419 		},
   420 		width);
   421 		/* *INDENT-ON* */
   422         src += srcskip;
   423         dstp += dstskip;
   424     }
   425 }
   426 
   427 static void
   428 Blit1toNAlpha(SDL_BlitInfo * info)
   429 {
   430     int width = info->d_width;
   431     int height = info->d_height;
   432     Uint8 *src = info->s_pixels;
   433     int srcskip = info->s_skip;
   434     Uint8 *dst = info->d_pixels;
   435     int dstskip = info->d_skip;
   436     SDL_PixelFormat *dstfmt = info->dst;
   437     const SDL_Color *srcpal = info->src->palette->colors;
   438     int dstbpp;
   439     const int A = info->src->alpha;
   440 
   441     /* Set up some basic variables */
   442     dstbpp = dstfmt->BytesPerPixel;
   443 
   444     while (height--) {
   445         int sR, sG, sB;
   446         int dR, dG, dB;
   447 	    	/* *INDENT-OFF* */
   448 	    	DUFFS_LOOP4(
   449 			{
   450 			        Uint32 pixel;
   451 				sR = srcpal[*src].r;
   452 				sG = srcpal[*src].g;
   453 				sB = srcpal[*src].b;
   454 				DISEMBLE_RGB(dst, dstbpp, dstfmt,
   455 					     pixel, dR, dG, dB);
   456 				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
   457 			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
   458 				src++;
   459 				dst += dstbpp;
   460 			},
   461 			width);
   462 	    	/* *INDENT-ON* */
   463         src += srcskip;
   464         dst += dstskip;
   465     }
   466 }
   467 
   468 static void
   469 Blit1toNAlphaKey(SDL_BlitInfo * info)
   470 {
   471     int width = info->d_width;
   472     int height = info->d_height;
   473     Uint8 *src = info->s_pixels;
   474     int srcskip = info->s_skip;
   475     Uint8 *dst = info->d_pixels;
   476     int dstskip = info->d_skip;
   477     SDL_PixelFormat *srcfmt = info->src;
   478     SDL_PixelFormat *dstfmt = info->dst;
   479     const SDL_Color *srcpal = info->src->palette->colors;
   480     Uint32 ckey = srcfmt->colorkey;
   481     int dstbpp;
   482     const int A = srcfmt->alpha;
   483 
   484     /* Set up some basic variables */
   485     dstbpp = dstfmt->BytesPerPixel;
   486 
   487     while (height--) {
   488         int sR, sG, sB;
   489         int dR, dG, dB;
   490 		/* *INDENT-OFF* */
   491 		DUFFS_LOOP(
   492 		{
   493 			if ( *src != ckey ) {
   494 			        Uint32 pixel;
   495 				sR = srcpal[*src].r;
   496 				sG = srcpal[*src].g;
   497 				sB = srcpal[*src].b;
   498 				DISEMBLE_RGB(dst, dstbpp, dstfmt,
   499 							pixel, dR, dG, dB);
   500 				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
   501 			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
   502 			}
   503 			src++;
   504 			dst += dstbpp;
   505 		},
   506 		width);
   507 		/* *INDENT-ON* */
   508         src += srcskip;
   509         dst += dstskip;
   510     }
   511 }
   512 
   513 static SDL_loblit one_blit[] = {
   514     NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
   515 };
   516 
   517 static SDL_loblit one_blitkey[] = {
   518     NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
   519 };
   520 
   521 SDL_loblit
   522 SDL_CalculateBlit1(SDL_Surface * surface, int blit_index)
   523 {
   524     int which;
   525     SDL_PixelFormat *dstfmt;
   526 
   527     dstfmt = surface->map->dst->format;
   528     if (dstfmt->BitsPerPixel < 8) {
   529         which = 0;
   530     } else {
   531         which = dstfmt->BytesPerPixel;
   532     }
   533     switch (blit_index) {
   534     case 0:                    /* copy */
   535         return one_blit[which];
   536 
   537     case 1:                    /* colorkey */
   538         return one_blitkey[which];
   539 
   540     case 2:                    /* alpha */
   541         /* Supporting 8bpp->8bpp alpha is doable but requires lots of
   542            tables which consume space and takes time to precompute,
   543            so is better left to the user */
   544         return which >= 2 ? Blit1toNAlpha : NULL;
   545 
   546     case 3:                    /* alpha + colorkey */
   547         return which >= 2 ? Blit1toNAlphaKey : NULL;
   548 
   549     }
   550     return NULL;
   551 }
   552 
   553 /* vi: set ts=4 sw=4 expandtab: */