Fixed bug 2976 - Fix RGBA<->RGBA blit that was broken with the optimization from Bug 11
authorSam Lantinga <slouken@libsdl.org>
Mon, 04 May 2015 21:47:40 -0700
changeset 95830bd764eb2b99
parent 9582 e0e2e94ce5ea
child 9584 fceb5503cadf
Fixed bug 2976 - Fix RGBA<->RGBA blit that was broken with the optimization from Bug 11

id.zeta

The optimization from Bug 11 added a code branch on cases where the source RGB masks match the destination RGB masks and a optimized blit function Blit4to4MaskAlpha that always overrides the source alpha info would be chosen. Unfortunately, the branch also errorneously took over the RGBA<->RGBA blitting cases where the source alpha info should be copied, while they would instead get overriden in Blit4to4MaskAlpha.

The attached patch fixes that by handling the RGBA<->RGBA cases correctly in that branch with the original BlitNtoNCopyAlpha as well as uses an optimized Blit4to4CopyAlpha along the same vein.
src/video/SDL_blit_N.c
     1.1 --- a/src/video/SDL_blit_N.c	Fri May 01 01:20:28 2015 -0400
     1.2 +++ b/src/video/SDL_blit_N.c	Mon May 04 21:47:40 2015 -0700
     1.3 @@ -2114,6 +2114,33 @@
     1.4      }
     1.5  }
     1.6  
     1.7 +/* blits 32 bit RGBA<->RGBA with both surfaces having the same R,G,B,A fields */
     1.8 +static void
     1.9 +Blit4to4CopyAlpha(SDL_BlitInfo * info)
    1.10 +{
    1.11 +    int width = info->dst_w;
    1.12 +    int height = info->dst_h;
    1.13 +    Uint32 *src = (Uint32 *) info->src;
    1.14 +    int srcskip = info->src_skip;
    1.15 +    Uint32 *dst = (Uint32 *) info->dst;
    1.16 +    int dstskip = info->dst_skip;
    1.17 +
    1.18 +    /* RGBA->RGBA, COPY_ALPHA */
    1.19 +    while (height--) {
    1.20 +        /* *INDENT-OFF* */
    1.21 +        DUFFS_LOOP(
    1.22 +        {
    1.23 +            *dst = *src;
    1.24 +            ++dst;
    1.25 +            ++src;
    1.26 +        },
    1.27 +        width);
    1.28 +        /* *INDENT-ON* */
    1.29 +        src = (Uint32 *) ((Uint8 *) src + srcskip);
    1.30 +        dst = (Uint32 *) ((Uint8 *) dst + dstskip);
    1.31 +    }
    1.32 +}
    1.33 +
    1.34  static void
    1.35  BlitNtoN(SDL_BlitInfo * info)
    1.36  {
    1.37 @@ -2562,8 +2589,17 @@
    1.38                              srcfmt->Rmask == dstfmt->Rmask &&
    1.39                              srcfmt->Gmask == dstfmt->Gmask &&
    1.40                              srcfmt->Bmask == dstfmt->Bmask) {
    1.41 -                    /* Fastpath C fallback: 32bit RGB<->RGBA blit with matching RGB */
    1.42 -                    blitfun = Blit4to4MaskAlpha;
    1.43 +                    if (a_need == COPY_ALPHA) {
    1.44 +                        if (srcfmt->Amask == dstfmt->Amask) {
    1.45 +                            /* Fastpath C fallback: 32bit RGBA<->RGBA blit with matching RGBA */
    1.46 +                            blitfun = Blit4to4CopyAlpha;
    1.47 +                        } else {
    1.48 +                            blitfun = BlitNtoNCopyAlpha;
    1.49 +                        }
    1.50 +                    } else {
    1.51 +                        /* Fastpath C fallback: 32bit RGB<->RGBA blit with matching RGB */
    1.52 +                        blitfun = Blit4to4MaskAlpha;
    1.53 +                    }
    1.54                  } else if (a_need == COPY_ALPHA) {
    1.55                      blitfun = BlitNtoNCopyAlpha;
    1.56                  }