src/video/SDL_blit_1.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 25 Feb 2020 14:52:03 -0500
changeset 13553 78754c9488f6
parent 13440 ac297b67f6d9
permissions -rw-r--r--
cmake: Forgot to add this file to revision control.

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