Fixed bug 4188 - Software renderer SDL_RenderCopyEx blits corrupt image under certain cases
authorSam Lantinga <slouken@libsdl.org>
Tue, 09 Oct 2018 17:41:40 -0700
changeset 12311b19b09eb9e6d
parent 12310 18f3294b230e
child 12312 522de4f715bd
Fixed bug 4188 - Software renderer SDL_RenderCopyEx blits corrupt image under certain cases

duckgrease

SDL_RenderCopyEx blits wrong image (in some cases it's bunch of alternating horizontal lines, some cases it's image from the wrong coordinate, and in some cases it's just a bunch of garbled pixels), when the following conditions are met:
- Use software renderer.
- Enable either horizontal or vertical flip.
- source and destination rectangles must have same width and height, and must be smaller than the size of the texture.
- source rectangle's X and Y coordinates must be 0.
src/render/software/SDL_rotate.c
     1.1 --- a/src/render/software/SDL_rotate.c	Tue Oct 09 00:27:55 2018 -0400
     1.2 +++ b/src/render/software/SDL_rotate.c	Tue Oct 09 17:41:40 2018 -0700
     1.3 @@ -150,17 +150,17 @@
     1.4  /* Computes source pointer X/Y increments for a rotation that's a multiple of 90 degrees. */
     1.5  static void
     1.6  computeSourceIncrements90(SDL_Surface * src, int bpp, int angle, int flipx, int flipy,
     1.7 -                          int *sincx, int *sincy, int *signx, int *signy)
     1.8 +                          int *sincx, int *sincy, int *signx, int *signy, SDL_Surface *dst)
     1.9  {
    1.10      int pitch = flipy ? -src->pitch : src->pitch;
    1.11      if (flipx) {
    1.12          bpp = -bpp;
    1.13      }
    1.14      switch (angle) { /* 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg */
    1.15 -    case 0: *sincx = bpp; *sincy = pitch - src->w * *sincx; *signx = *signy = 1; break;
    1.16 -    case 1: *sincx = -pitch; *sincy = bpp - *sincx * src->h; *signx = 1; *signy = -1; break;
    1.17 -    case 2: *sincx = -bpp; *sincy = -src->w * *sincx - pitch; *signx = *signy = -1; break;
    1.18 -    case 3: default: *sincx = pitch; *sincy = -*sincx * src->h - bpp; *signx = -1; *signy = 1; break;
    1.19 +    case 0: *sincx = bpp; *sincy = pitch - dst->w * *sincx; *signx = *signy = 1; break;
    1.20 +    case 1: *sincx = -pitch; *sincy = bpp - *sincx * dst->h; *signx = 1; *signy = -1; break;
    1.21 +    case 2: *sincx = -bpp; *sincy = -dst->w * *sincx - pitch; *signx = *signy = -1; break;
    1.22 +    case 3: default: *sincx = pitch; *sincy = -*sincx * dst->h - bpp; *signx = -1; *signy = 1; break;
    1.23      }
    1.24      if (flipx) {
    1.25          *signx = -*signx;
    1.26 @@ -175,10 +175,9 @@
    1.27      int dy, dincy = dst->pitch - dst->w*sizeof(pixelType), sincx, sincy, signx, signy;                      \
    1.28      Uint8 *sp = (Uint8*)src->pixels, *dp = (Uint8*)dst->pixels, *de;                                        \
    1.29                                                                                                              \
    1.30 -    computeSourceIncrements90(src, sizeof(pixelType), angle, flipx, flipy, &sincx, &sincy, &signx, &signy); \
    1.31 -    if (signx < 0) sp += (src->w-1)*sizeof(pixelType);                                                      \
    1.32 -    if (signy < 0) sp += (src->h-1)*src->pitch;                                                             \
    1.33 -                                                                                                            \
    1.34 +    computeSourceIncrements90(src, sizeof(pixelType), angle, flipx, flipy, &sincx, &sincy, &signx, &signy, dst); \
    1.35 +    if (signx < 0) sp += (dst->w-1)*sizeof(pixelType);                                                      \
    1.36 +    if (signy < 0) sp += (dst->h-1)*src->pitch;                                                             \
    1.37      for (dy = 0; dy < dst->h; sp += sincy, dp += dincy, dy++) {                                             \
    1.38          if (sincx == sizeof(pixelType)) { /* if advancing src and dest equally, use memcpy */               \
    1.39              SDL_memcpy(dp, sp, dst->w*sizeof(pixelType));                                                   \