src/video/SDL_blit_1.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Dec 2011 09:28:07 -0500
changeset 6138 4c64952a58fb
parent 5535 96594ac5fd1a
child 6885 700f1b25f77f
permissions -rwxr-xr-x
Happy New Year!
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #include "SDL_video.h"
    24 #include "SDL_blit.h"
    25 #include "SDL_sysvideo.h"
    26 #include "SDL_endian.h"
    27 
    28 /* Functions to blit from 8-bit surfaces to other surfaces */
    29 
    30 static void
    31 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->dst_w;
    42     height = info->dst_h;
    43     src = info->src;
    44     srcskip = info->src_skip;
    45     dst = info->dst;
    46     dstskip = info->dst_skip;
    47     map = info->table;
    48 
    49     while (height--) {
    50 #ifdef USE_DUFFS_LOOP
    51         /* *INDENT-OFF* */
    52 		DUFFS_LOOP(
    53 			{
    54 			  *dst = map[*src];
    55 			}
    56 			dst++;
    57 			src++;
    58 		, width);
    59         /* *INDENT-ON* */
    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 
    72 /* This is now endian dependent */
    73 #if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
    74 #define HI	1
    75 #define LO	0
    76 #else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
    77 #define HI	0
    78 #define LO	1
    79 #endif
    80 static void
    81 Blit1to2(SDL_BlitInfo * info)
    82 {
    83 #ifndef USE_DUFFS_LOOP
    84     int c;
    85 #endif
    86     int width, height;
    87     Uint8 *src, *dst;
    88     Uint16 *map;
    89     int srcskip, dstskip;
    90 
    91     /* Set up some basic variables */
    92     width = info->dst_w;
    93     height = info->dst_h;
    94     src = info->src;
    95     srcskip = info->src_skip;
    96     dst = info->dst;
    97     dstskip = info->dst_skip;
    98     map = (Uint16 *) info->table;
    99 
   100 #ifdef USE_DUFFS_LOOP
   101     while (height--) {
   102 		/* *INDENT-OFF* */
   103 		DUFFS_LOOP(
   104 		{
   105 			*(Uint16 *)dst = map[*src++];
   106 			dst += 2;
   107 		},
   108 		width);
   109 		/* *INDENT-ON* */
   110         src += srcskip;
   111         dst += dstskip;
   112     }
   113 #else
   114     /* Memory align at 4-byte boundary, if necessary */
   115     if ((long) dst & 0x03) {
   116         /* Don't do anything if width is 0 */
   117         if (width == 0) {
   118             return;
   119         }
   120         --width;
   121 
   122         while (height--) {
   123             /* Perform copy alignment */
   124             *(Uint16 *) dst = map[*src++];
   125             dst += 2;
   126 
   127             /* Copy in 4 pixel chunks */
   128             for (c = width / 4; c; --c) {
   129                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   130                 src += 2;
   131                 dst += 4;
   132                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   133                 src += 2;
   134                 dst += 4;
   135             }
   136             /* Get any leftovers */
   137             switch (width & 3) {
   138             case 3:
   139                 *(Uint16 *) dst = map[*src++];
   140                 dst += 2;
   141             case 2:
   142                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   143                 src += 2;
   144                 dst += 4;
   145                 break;
   146             case 1:
   147                 *(Uint16 *) dst = map[*src++];
   148                 dst += 2;
   149                 break;
   150             }
   151             src += srcskip;
   152             dst += dstskip;
   153         }
   154     } else {
   155         while (height--) {
   156             /* Copy in 4 pixel chunks */
   157             for (c = width / 4; c; --c) {
   158                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   159                 src += 2;
   160                 dst += 4;
   161                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   162                 src += 2;
   163                 dst += 4;
   164             }
   165             /* Get any leftovers */
   166             switch (width & 3) {
   167             case 3:
   168                 *(Uint16 *) dst = map[*src++];
   169                 dst += 2;
   170             case 2:
   171                 *(Uint32 *) dst = (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 
   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->dst_w;
   200     height = info->dst_h;
   201     src = info->src;
   202     srcskip = info->src_skip;
   203     dst = info->dst;
   204     dstskip = info->dst_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 
   236 static void
   237 Blit1to4(SDL_BlitInfo * info)
   238 {
   239 #ifndef USE_DUFFS_LOOP
   240     int c;
   241 #endif
   242     int width, height;
   243     Uint8 *src;
   244     Uint32 *map, *dst;
   245     int srcskip, dstskip;
   246 
   247     /* Set up some basic variables */
   248     width = info->dst_w;
   249     height = info->dst_h;
   250     src = info->src;
   251     srcskip = info->src_skip;
   252     dst = (Uint32 *) info->dst;
   253     dstskip = info->dst_skip / 4;
   254     map = (Uint32 *) info->table;
   255 
   256     while (height--) {
   257 #ifdef USE_DUFFS_LOOP
   258 		/* *INDENT-OFF* */
   259 		DUFFS_LOOP(
   260 			*dst++ = map[*src++];
   261 		, width);
   262 		/* *INDENT-ON* */
   263 #else
   264         for (c = width / 4; c; --c) {
   265             *dst++ = map[*src++];
   266             *dst++ = map[*src++];
   267             *dst++ = map[*src++];
   268             *dst++ = map[*src++];
   269         }
   270         switch (width & 3) {
   271         case 3:
   272             *dst++ = map[*src++];
   273         case 2:
   274             *dst++ = map[*src++];
   275         case 1:
   276             *dst++ = map[*src++];
   277         }
   278 #endif /* USE_DUFFS_LOOP */
   279         src += srcskip;
   280         dst += dstskip;
   281     }
   282 }
   283 
   284 static void
   285 Blit1to1Key(SDL_BlitInfo * info)
   286 {
   287     int width = info->dst_w;
   288     int height = info->dst_h;
   289     Uint8 *src = info->src;
   290     int srcskip = info->src_skip;
   291     Uint8 *dst = info->dst;
   292     int dstskip = info->dst_skip;
   293     Uint8 *palmap = info->table;
   294     Uint32 ckey = info->colorkey;
   295 
   296     if (palmap) {
   297         while (height--) {
   298 			/* *INDENT-OFF* */
   299 			DUFFS_LOOP(
   300 			{
   301 				if ( *src != ckey ) {
   302 				  *dst = palmap[*src];
   303 				}
   304 				dst++;
   305 				src++;
   306 			},
   307 			width);
   308 			/* *INDENT-ON* */
   309             src += srcskip;
   310             dst += dstskip;
   311         }
   312     } else {
   313         while (height--) {
   314 			/* *INDENT-OFF* */
   315 			DUFFS_LOOP(
   316 			{
   317 				if ( *src != ckey ) {
   318 				  *dst = *src;
   319 				}
   320 				dst++;
   321 				src++;
   322 			},
   323 			width);
   324 			/* *INDENT-ON* */
   325             src += srcskip;
   326             dst += dstskip;
   327         }
   328     }
   329 }
   330 
   331 static void
   332 Blit1to2Key(SDL_BlitInfo * info)
   333 {
   334     int width = info->dst_w;
   335     int height = info->dst_h;
   336     Uint8 *src = info->src;
   337     int srcskip = info->src_skip;
   338     Uint16 *dstp = (Uint16 *) info->dst;
   339     int dstskip = info->dst_skip;
   340     Uint16 *palmap = (Uint16 *) info->table;
   341     Uint32 ckey = info->colorkey;
   342 
   343     /* Set up some basic variables */
   344     dstskip /= 2;
   345 
   346     while (height--) {
   347 		/* *INDENT-OFF* */
   348 		DUFFS_LOOP(
   349 		{
   350 			if ( *src != ckey ) {
   351 				*dstp=palmap[*src];
   352 			}
   353 			src++;
   354 			dstp++;
   355 		},
   356 		width);
   357 		/* *INDENT-ON* */
   358         src += srcskip;
   359         dstp += dstskip;
   360     }
   361 }
   362 
   363 static void
   364 Blit1to3Key(SDL_BlitInfo * info)
   365 {
   366     int width = info->dst_w;
   367     int height = info->dst_h;
   368     Uint8 *src = info->src;
   369     int srcskip = info->src_skip;
   370     Uint8 *dst = info->dst;
   371     int dstskip = info->dst_skip;
   372     Uint8 *palmap = info->table;
   373     Uint32 ckey = info->colorkey;
   374     int o;
   375 
   376     while (height--) {
   377 		/* *INDENT-OFF* */
   378 		DUFFS_LOOP(
   379 		{
   380 			if ( *src != ckey ) {
   381 				o = *src * 4;
   382 				dst[0] = palmap[o++];
   383 				dst[1] = palmap[o++];
   384 				dst[2] = palmap[o++];
   385 			}
   386 			src++;
   387 			dst += 3;
   388 		},
   389 		width);
   390 		/* *INDENT-ON* */
   391         src += srcskip;
   392         dst += dstskip;
   393     }
   394 }
   395 
   396 static void
   397 Blit1to4Key(SDL_BlitInfo * info)
   398 {
   399     int width = info->dst_w;
   400     int height = info->dst_h;
   401     Uint8 *src = info->src;
   402     int srcskip = info->src_skip;
   403     Uint32 *dstp = (Uint32 *) info->dst;
   404     int dstskip = info->dst_skip;
   405     Uint32 *palmap = (Uint32 *) info->table;
   406     Uint32 ckey = info->colorkey;
   407 
   408     /* Set up some basic variables */
   409     dstskip /= 4;
   410 
   411     while (height--) {
   412 		/* *INDENT-OFF* */
   413 		DUFFS_LOOP(
   414 		{
   415 			if ( *src != ckey ) {
   416 				*dstp = palmap[*src];
   417 			}
   418 			src++;
   419 			dstp++;
   420 		},
   421 		width);
   422 		/* *INDENT-ON* */
   423         src += srcskip;
   424         dstp += dstskip;
   425     }
   426 }
   427 
   428 static void
   429 Blit1toNAlpha(SDL_BlitInfo * info)
   430 {
   431     int width = info->dst_w;
   432     int height = info->dst_h;
   433     Uint8 *src = info->src;
   434     int srcskip = info->src_skip;
   435     Uint8 *dst = info->dst;
   436     int dstskip = info->dst_skip;
   437     SDL_PixelFormat *dstfmt = info->dst_fmt;
   438     const SDL_Color *srcpal = info->src_fmt->palette->colors;
   439     int dstbpp;
   440     const int A = info->a;
   441 
   442     /* Set up some basic variables */
   443     dstbpp = dstfmt->BytesPerPixel;
   444 
   445     while (height--) {
   446         int sR, sG, sB;
   447         int dR, dG, dB;
   448 	    	/* *INDENT-OFF* */
   449 	    	DUFFS_LOOP4(
   450 			{
   451 			        Uint32 pixel;
   452 				sR = srcpal[*src].r;
   453 				sG = srcpal[*src].g;
   454 				sB = srcpal[*src].b;
   455 				DISEMBLE_RGB(dst, dstbpp, dstfmt,
   456 					     pixel, dR, dG, dB);
   457 				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
   458 			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
   459 				src++;
   460 				dst += dstbpp;
   461 			},
   462 			width);
   463 	    	/* *INDENT-ON* */
   464         src += srcskip;
   465         dst += dstskip;
   466     }
   467 }
   468 
   469 static void
   470 Blit1toNAlphaKey(SDL_BlitInfo * info)
   471 {
   472     int width = info->dst_w;
   473     int height = info->dst_h;
   474     Uint8 *src = info->src;
   475     int srcskip = info->src_skip;
   476     Uint8 *dst = info->dst;
   477     int dstskip = info->dst_skip;
   478     SDL_PixelFormat *dstfmt = info->dst_fmt;
   479     const SDL_Color *srcpal = info->src_fmt->palette->colors;
   480     Uint32 ckey = info->colorkey;
   481     int dstbpp;
   482     const int A = info->a;
   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 const SDL_BlitFunc one_blit[] = {
   514     NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
   515 };
   516 
   517 static const SDL_BlitFunc one_blitkey[] = {
   518     NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
   519 };
   520 
   521 SDL_BlitFunc
   522 SDL_CalculateBlit1(SDL_Surface * surface)
   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 (surface->map->info.flags & ~SDL_COPY_RLE_MASK) {
   534     case 0:
   535         return one_blit[which];
   536 
   537     case SDL_COPY_COLORKEY:
   538         return one_blitkey[which];
   539 
   540     case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
   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 SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
   547         return which >= 2 ? Blit1toNAlphaKey : NULL;
   548     }
   549     return NULL;
   550 }
   551 
   552 /* vi: set ts=4 sw=4 expandtab: */