SDL: Fixed bug #964 - SDL_RenderCopy stretch loses proportion on viewport boundaries

From a988ce55444d421850d5fb8593703b5e83b27be7 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Fri, 28 Jan 2022 17:24:59 +0100
Subject: [PATCH] Fixed bug #964 - SDL_RenderCopy stretch loses proportion on
 viewport boundaries

---
 src/render/software/SDL_render_sw.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c
index 7a2aac295c4..0eb9b513b47 100644
--- a/src/render/software/SDL_render_sw.c
+++ b/src/render/software/SDL_render_sw.c
@@ -823,7 +823,24 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
                      * to avoid potentially frequent RLE encoding/decoding.
                      */
                     SDL_SetSurfaceRLE(surface, 0);
-                    SDL_PrivateUpperBlitScaled(src, srcrect, surface, dstrect, texture->scaleMode);
+
+                    /* Prevent to do scaling + clipping on viewport boundaries as it may lose proportion */
+                    if (dstrect->x < 0 || dstrect->y < 0 || dstrect->x + dstrect->w > surface->w || dstrect->y + dstrect->h > surface->h) {
+                        SDL_Surface *tmp = SDL_CreateRGBSurfaceWithFormat(0, dstrect->w, dstrect->h, 0, src->format->format);
+                        /* Scale to an intermediate surface, then blit */
+                        if (tmp) {
+                            SDL_Rect r;
+                            r.x = 0;
+                            r.y = 0;
+                            r.w = dstrect->w;
+                            r.h = dstrect->h;
+                            SDL_PrivateUpperBlitScaled(src, srcrect, tmp, &r, texture->scaleMode);
+                            SDL_BlitSurface(tmp, NULL, surface, dstrect);
+                            SDL_FreeSurface(tmp);
+                        }
+                    } else{
+                        SDL_PrivateUpperBlitScaled(src, srcrect, surface, dstrect, texture->scaleMode);
+                    }
                 }
                 break;
             }