src/video/SDL_blit_1.c
author Sylvain Becker <sylvain.becker@gmail.com>
Mon, 14 Oct 2019 16:40:46 +0200
changeset 13117 27a1bea6bdff
parent 12503 806492103856
permissions -rw-r--r--
Fixed race condition when scaling Touch events, and changing the renderer
target.
Always read the output size of the main renderer.
(similar to bug 2107)
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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 #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 #ifndef USE_DUFFS_LOOP
    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 #endif
    82 static void
    83 Blit1to2(SDL_BlitInfo * info)
    84 {
    85 #ifndef USE_DUFFS_LOOP
    86     int c;
    87 #endif
    88     int width, height;
    89     Uint8 *src, *dst;
    90     Uint16 *map;
    91     int srcskip, dstskip;
    92 
    93     /* Set up some basic variables */
    94     width = info->dst_w;
    95     height = info->dst_h;
    96     src = info->src;
    97     srcskip = info->src_skip;
    98     dst = info->dst;
    99     dstskip = info->dst_skip;
   100     map = (Uint16 *) info->table;
   101 
   102 #ifdef USE_DUFFS_LOOP
   103     while (height--) {
   104         /* *INDENT-OFF* */
   105         DUFFS_LOOP(
   106         {
   107             *(Uint16 *)dst = map[*src++];
   108             dst += 2;
   109         },
   110         width);
   111         /* *INDENT-ON* */
   112         src += srcskip;
   113         dst += dstskip;
   114     }
   115 #else
   116     /* Memory align at 4-byte boundary, if necessary */
   117     if ((long) dst & 0x03) {
   118         /* Don't do anything if width is 0 */
   119         if (width == 0) {
   120             return;
   121         }
   122         --width;
   123 
   124         while (height--) {
   125             /* Perform copy alignment */
   126             *(Uint16 *) dst = map[*src++];
   127             dst += 2;
   128 
   129             /* Copy in 4 pixel chunks */
   130             for (c = width / 4; c; --c) {
   131                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   132                 src += 2;
   133                 dst += 4;
   134                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   135                 src += 2;
   136                 dst += 4;
   137             }
   138             /* Get any leftovers */
   139             switch (width & 3) {
   140             case 3:
   141                 *(Uint16 *) dst = map[*src++];
   142                 dst += 2;
   143             case 2:
   144                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   145                 src += 2;
   146                 dst += 4;
   147                 break;
   148             case 1:
   149                 *(Uint16 *) dst = map[*src++];
   150                 dst += 2;
   151                 break;
   152             }
   153             src += srcskip;
   154             dst += dstskip;
   155         }
   156     } else {
   157         while (height--) {
   158             /* Copy in 4 pixel chunks */
   159             for (c = width / 4; c; --c) {
   160                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   161                 src += 2;
   162                 dst += 4;
   163                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   164                 src += 2;
   165                 dst += 4;
   166             }
   167             /* Get any leftovers */
   168             switch (width & 3) {
   169             case 3:
   170                 *(Uint16 *) dst = map[*src++];
   171                 dst += 2;
   172             case 2:
   173                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
   174                 src += 2;
   175                 dst += 4;
   176                 break;
   177             case 1:
   178                 *(Uint16 *) dst = map[*src++];
   179                 dst += 2;
   180                 break;
   181             }
   182             src += srcskip;
   183             dst += dstskip;
   184         }
   185     }
   186 #endif /* USE_DUFFS_LOOP */
   187 }
   188 
   189 static void
   190 Blit1to3(SDL_BlitInfo * info)
   191 {
   192 #ifndef USE_DUFFS_LOOP
   193     int c;
   194 #endif
   195     int o;
   196     int width, height;
   197     Uint8 *src, *map, *dst;
   198     int srcskip, dstskip;
   199 
   200     /* Set up some basic variables */
   201     width = info->dst_w;
   202     height = info->dst_h;
   203     src = info->src;
   204     srcskip = info->src_skip;
   205     dst = info->dst;
   206     dstskip = info->dst_skip;
   207     map = info->table;
   208 
   209     while (height--) {
   210 #ifdef USE_DUFFS_LOOP
   211         /* *INDENT-OFF* */
   212         DUFFS_LOOP(
   213             {
   214                 o = *src * 4;
   215                 dst[0] = map[o++];
   216                 dst[1] = map[o++];
   217                 dst[2] = map[o++];
   218             }
   219             src++;
   220             dst += 3;
   221         , width);
   222         /* *INDENT-ON* */
   223 #else
   224         for (c = width; c; --c) {
   225             o = *src * 4;
   226             dst[0] = map[o++];
   227             dst[1] = map[o++];
   228             dst[2] = map[o++];
   229             src++;
   230             dst += 3;
   231         }
   232 #endif /* USE_DUFFS_LOOP */
   233         src += srcskip;
   234         dst += dstskip;
   235     }
   236 }
   237 
   238 static void
   239 Blit1to4(SDL_BlitInfo * info)
   240 {
   241 #ifndef USE_DUFFS_LOOP
   242     int c;
   243 #endif
   244     int width, height;
   245     Uint8 *src;
   246     Uint32 *map, *dst;
   247     int srcskip, dstskip;
   248 
   249     /* Set up some basic variables */
   250     width = info->dst_w;
   251     height = info->dst_h;
   252     src = info->src;
   253     srcskip = info->src_skip;
   254     dst = (Uint32 *) info->dst;
   255     dstskip = info->dst_skip / 4;
   256     map = (Uint32 *) info->table;
   257 
   258     while (height--) {
   259 #ifdef USE_DUFFS_LOOP
   260         /* *INDENT-OFF* */
   261         DUFFS_LOOP(
   262             *dst++ = map[*src++];
   263         , width);
   264         /* *INDENT-ON* */
   265 #else
   266         for (c = width / 4; c; --c) {
   267             *dst++ = map[*src++];
   268             *dst++ = map[*src++];
   269             *dst++ = map[*src++];
   270             *dst++ = map[*src++];
   271         }
   272         switch (width & 3) {
   273         case 3:
   274             *dst++ = map[*src++];
   275         case 2:
   276             *dst++ = map[*src++];
   277         case 1:
   278             *dst++ = map[*src++];
   279         }
   280 #endif /* USE_DUFFS_LOOP */
   281         src += srcskip;
   282         dst += dstskip;
   283     }
   284 }
   285 
   286 static void
   287 Blit1to1Key(SDL_BlitInfo * info)
   288 {
   289     int width = info->dst_w;
   290     int height = info->dst_h;
   291     Uint8 *src = info->src;
   292     int srcskip = info->src_skip;
   293     Uint8 *dst = info->dst;
   294     int dstskip = info->dst_skip;
   295     Uint8 *palmap = info->table;
   296     Uint32 ckey = info->colorkey;
   297 
   298     if (palmap) {
   299         while (height--) {
   300             /* *INDENT-OFF* */
   301             DUFFS_LOOP(
   302             {
   303                 if ( *src != ckey ) {
   304                   *dst = palmap[*src];
   305                 }
   306                 dst++;
   307                 src++;
   308             },
   309             width);
   310             /* *INDENT-ON* */
   311             src += srcskip;
   312             dst += dstskip;
   313         }
   314     } else {
   315         while (height--) {
   316             /* *INDENT-OFF* */
   317             DUFFS_LOOP(
   318             {
   319                 if ( *src != ckey ) {
   320                   *dst = *src;
   321                 }
   322                 dst++;
   323                 src++;
   324             },
   325             width);
   326             /* *INDENT-ON* */
   327             src += srcskip;
   328             dst += dstskip;
   329         }
   330     }
   331 }
   332 
   333 static void
   334 Blit1to2Key(SDL_BlitInfo * info)
   335 {
   336     int width = info->dst_w;
   337     int height = info->dst_h;
   338     Uint8 *src = info->src;
   339     int srcskip = info->src_skip;
   340     Uint16 *dstp = (Uint16 *) info->dst;
   341     int dstskip = info->dst_skip;
   342     Uint16 *palmap = (Uint16 *) info->table;
   343     Uint32 ckey = info->colorkey;
   344 
   345     /* Set up some basic variables */
   346     dstskip /= 2;
   347 
   348     while (height--) {
   349         /* *INDENT-OFF* */
   350         DUFFS_LOOP(
   351         {
   352             if ( *src != ckey ) {
   353                 *dstp=palmap[*src];
   354             }
   355             src++;
   356             dstp++;
   357         },
   358         width);
   359         /* *INDENT-ON* */
   360         src += srcskip;
   361         dstp += dstskip;
   362     }
   363 }
   364 
   365 static void
   366 Blit1to3Key(SDL_BlitInfo * info)
   367 {
   368     int width = info->dst_w;
   369     int height = info->dst_h;
   370     Uint8 *src = info->src;
   371     int srcskip = info->src_skip;
   372     Uint8 *dst = info->dst;
   373     int dstskip = info->dst_skip;
   374     Uint8 *palmap = info->table;
   375     Uint32 ckey = info->colorkey;
   376     int o;
   377 
   378     while (height--) {
   379         /* *INDENT-OFF* */
   380         DUFFS_LOOP(
   381         {
   382             if ( *src != ckey ) {
   383                 o = *src * 4;
   384                 dst[0] = palmap[o++];
   385                 dst[1] = palmap[o++];
   386                 dst[2] = palmap[o++];
   387             }
   388             src++;
   389             dst += 3;
   390         },
   391         width);
   392         /* *INDENT-ON* */
   393         src += srcskip;
   394         dst += dstskip;
   395     }
   396 }
   397 
   398 static void
   399 Blit1to4Key(SDL_BlitInfo * info)
   400 {
   401     int width = info->dst_w;
   402     int height = info->dst_h;
   403     Uint8 *src = info->src;
   404     int srcskip = info->src_skip;
   405     Uint32 *dstp = (Uint32 *) info->dst;
   406     int dstskip = info->dst_skip;
   407     Uint32 *palmap = (Uint32 *) info->table;
   408     Uint32 ckey = info->colorkey;
   409 
   410     /* Set up some basic variables */
   411     dstskip /= 4;
   412 
   413     while (height--) {
   414         /* *INDENT-OFF* */
   415         DUFFS_LOOP(
   416         {
   417             if ( *src != ckey ) {
   418                 *dstp = palmap[*src];
   419             }
   420             src++;
   421             dstp++;
   422         },
   423         width);
   424         /* *INDENT-ON* */
   425         src += srcskip;
   426         dstp += dstskip;
   427     }
   428 }
   429 
   430 static void
   431 Blit1toNAlpha(SDL_BlitInfo * info)
   432 {
   433     int width = info->dst_w;
   434     int height = info->dst_h;
   435     Uint8 *src = info->src;
   436     int srcskip = info->src_skip;
   437     Uint8 *dst = info->dst;
   438     int dstskip = info->dst_skip;
   439     SDL_PixelFormat *dstfmt = info->dst_fmt;
   440     const SDL_Color *srcpal = info->src_fmt->palette->colors;
   441     int dstbpp;
   442     Uint32 pixel;
   443     unsigned sR, sG, sB;
   444     unsigned dR, dG, dB, dA;
   445     const unsigned A = info->a;
   446 
   447     /* Set up some basic variables */
   448     dstbpp = dstfmt->BytesPerPixel;
   449 
   450     while (height--) {
   451         /* *INDENT-OFF* */
   452         DUFFS_LOOP4(
   453         {
   454             sR = srcpal[*src].r;
   455             sG = srcpal[*src].g;
   456             sB = srcpal[*src].b;
   457             DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
   458             ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
   459             ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
   460             src++;
   461             dst += dstbpp;
   462         },
   463         width);
   464         /* *INDENT-ON* */
   465         src += srcskip;
   466         dst += dstskip;
   467     }
   468 }
   469 
   470 static void
   471 Blit1toNAlphaKey(SDL_BlitInfo * info)
   472 {
   473     int width = info->dst_w;
   474     int height = info->dst_h;
   475     Uint8 *src = info->src;
   476     int srcskip = info->src_skip;
   477     Uint8 *dst = info->dst;
   478     int dstskip = info->dst_skip;
   479     SDL_PixelFormat *dstfmt = info->dst_fmt;
   480     const SDL_Color *srcpal = info->src_fmt->palette->colors;
   481     Uint32 ckey = info->colorkey;
   482     int dstbpp;
   483     Uint32 pixel;
   484     unsigned sR, sG, sB;
   485     unsigned dR, dG, dB, dA;
   486     const unsigned A = info->a;
   487 
   488     /* Set up some basic variables */
   489     dstbpp = dstfmt->BytesPerPixel;
   490 
   491     while (height--) {
   492         /* *INDENT-OFF* */
   493         DUFFS_LOOP(
   494         {
   495             if ( *src != ckey ) {
   496                 sR = srcpal[*src].r;
   497                 sG = srcpal[*src].g;
   498                 sB = srcpal[*src].b;
   499                 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
   500                 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
   501                   ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
   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     (SDL_BlitFunc) NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
   515 };
   516 
   517 static const SDL_BlitFunc one_blitkey[] = {
   518     (SDL_BlitFunc) 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 : (SDL_BlitFunc) NULL;
   545 
   546     case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
   547         return which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc) NULL;
   548     }
   549     return (SDL_BlitFunc) NULL;
   550 }
   551 
   552 /* vi: set ts=4 sw=4 expandtab: */