src/video/SDL_blit_1.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 11:28:44 -0700
changeset 7776 d4a39491577f
parent 7502 6ff02ff3cf06
child 8093 b43765095a6f
permissions -rw-r--r--
Added the platform specific messagebox function to the video function list
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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     Uint32 pixel;
   441     unsigned sR, sG, sB;
   442     unsigned dR, dG, dB, dA;
   443     const unsigned A = info->a;
   444 
   445     /* Set up some basic variables */
   446     dstbpp = dstfmt->BytesPerPixel;
   447 
   448     while (height--) {
   449         /* *INDENT-OFF* */
   450         DUFFS_LOOP4(
   451         {
   452             sR = srcpal[*src].r;
   453             sG = srcpal[*src].g;
   454             sB = srcpal[*src].b;
   455             DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
   456             ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
   457             ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
   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->dst_w;
   472     int height = info->dst_h;
   473     Uint8 *src = info->src;
   474     int srcskip = info->src_skip;
   475     Uint8 *dst = info->dst;
   476     int dstskip = info->dst_skip;
   477     SDL_PixelFormat *dstfmt = info->dst_fmt;
   478     const SDL_Color *srcpal = info->src_fmt->palette->colors;
   479     Uint32 ckey = info->colorkey;
   480     int dstbpp;
   481     Uint32 pixel;
   482     unsigned sR, sG, sB;
   483     unsigned dR, dG, dB, dA;
   484     const unsigned A = info->a;
   485 
   486     /* Set up some basic variables */
   487     dstbpp = dstfmt->BytesPerPixel;
   488 
   489     while (height--) {
   490 		/* *INDENT-OFF* */
   491 		DUFFS_LOOP(
   492 		{
   493 			if ( *src != ckey ) {
   494 				sR = srcpal[*src].r;
   495 				sG = srcpal[*src].g;
   496 				sB = srcpal[*src].b;
   497 				DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
   498 				ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
   499 			  	ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
   500 			}
   501 			src++;
   502 			dst += dstbpp;
   503 		},
   504 		width);
   505 		/* *INDENT-ON* */
   506         src += srcskip;
   507         dst += dstskip;
   508     }
   509 }
   510 
   511 static const SDL_BlitFunc one_blit[] = {
   512     (SDL_BlitFunc) NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
   513 };
   514 
   515 static const SDL_BlitFunc one_blitkey[] = {
   516     (SDL_BlitFunc) NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
   517 };
   518 
   519 SDL_BlitFunc
   520 SDL_CalculateBlit1(SDL_Surface * surface)
   521 {
   522     int which;
   523     SDL_PixelFormat *dstfmt;
   524 
   525     dstfmt = surface->map->dst->format;
   526     if (dstfmt->BitsPerPixel < 8) {
   527         which = 0;
   528     } else {
   529         which = dstfmt->BytesPerPixel;
   530     }
   531     switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) {
   532     case 0:
   533         return one_blit[which];
   534 
   535     case SDL_COPY_COLORKEY:
   536         return one_blitkey[which];
   537 
   538     case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
   539         /* Supporting 8bpp->8bpp alpha is doable but requires lots of
   540            tables which consume space and takes time to precompute,
   541            so is better left to the user */
   542         return which >= 2 ? Blit1toNAlpha : (SDL_BlitFunc) NULL;
   543 
   544     case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
   545         return which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc) NULL;
   546     }
   547     return (SDL_BlitFunc) NULL;
   548 }
   549 
   550 /* vi: set ts=4 sw=4 expandtab: */