SDL: - simplication and factorization around CalculateSize and Pitch, RGB/YUV

From cae6b4489d0828bd70ae4ec559bec132d5f93ca6 Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Thu, 30 Mar 2023 11:30:11 +0200
Subject: [PATCH] - simplication and factorization around CalculateSize and
 Pitch, RGB/YUV - update SDL_CalculateYUVSize pitch to size_t

---
 src/video/SDL_pixels_c.h |   1 +
 src/video/SDL_surface.c  | 122 ++++++++++++++++++++-------------------
 src/video/SDL_yuv.c      |   4 +-
 src/video/SDL_yuv_c.h    |   2 +-
 4 files changed, 67 insertions(+), 62 deletions(-)

diff --git a/src/video/SDL_pixels_c.h b/src/video/SDL_pixels_c.h
index 6ddf0276f05a..897f973d5402 100644
--- a/src/video/SDL_pixels_c.h
+++ b/src/video/SDL_pixels_c.h
@@ -30,6 +30,7 @@
 
 /* Pixel format functions */
 extern int SDL_InitFormat(SDL_PixelFormat *format, Uint32 pixel_format);
+extern int SDL_CalculateSize(Uint32 format, int width, int height, size_t *size, size_t *pitch, SDL_bool minimalPitch);
 
 /* Blit mapping functions */
 extern SDL_BlitMap *SDL_AllocBlitMap(void);
diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c
index 7d1b587e4a3e..cb0fc9361aa0 100644
--- a/src/video/SDL_surface.c
+++ b/src/video/SDL_surface.c
@@ -42,32 +42,71 @@ SDL_COMPILE_TIME_ASSERT(can_indicate_overflow, SDL_SIZE_MAX > SDL_MAX_SINT32);
  *
  * for FOURCC, use SDL_CalculateYUVSize()
  */
-static size_t
-SDL_CalculatePitch(Uint32 format, size_t width, SDL_bool minimal)
+static int
+SDL_CalculateRGBSize(Uint32 format, size_t width, size_t height, size_t *size, size_t *pitch, SDL_bool minimal)
 {
-    size_t pitch;
-
     if (SDL_BITSPERPIXEL(format) >= 8) {
-        if (SDL_size_mul_overflow(width, SDL_BYTESPERPIXEL(format), &pitch)) {
-            return SDL_SIZE_MAX;
+        if (SDL_size_mul_overflow(width, SDL_BYTESPERPIXEL(format), pitch)) {
+            return -1;
         }
     } else {
-        if (SDL_size_mul_overflow(width, SDL_BITSPERPIXEL(format), &pitch)) {
-            return SDL_SIZE_MAX;
+        if (SDL_size_mul_overflow(width, SDL_BITSPERPIXEL(format), pitch)) {
+            return -1;
         }
-        if (SDL_size_add_overflow(pitch, 7, &pitch)) {
-            return SDL_SIZE_MAX;
+        if (SDL_size_add_overflow(*pitch, 7, pitch)) {
+            return -1;
         }
-        pitch /= 8;
+        *pitch /= 8;
     }
     if (!minimal) {
         /* 4-byte aligning for speed */
-        if (SDL_size_add_overflow(pitch, 3, &pitch)) {
-            return SDL_SIZE_MAX;
+        if (SDL_size_add_overflow(*pitch, 3, pitch)) {
+            return -1;
         }
-        pitch &= ~3;
+        *pitch &= ~3;
+    }
+
+    if (SDL_size_mul_overflow(height, *pitch, size)) {
+        /* Overflow... */
+        return -1;
     }
-    return pitch;
+
+    return 0;
+}
+
+int SDL_CalculateSize(Uint32 format, int width, int height, size_t *size, size_t *pitch, SDL_bool minimalPitch)
+{
+    size_t p = 0, sz = 0;
+
+    if (size) {
+        *size = 0;
+    }
+
+    if (pitch) {
+        *pitch = 0;
+    }
+
+    if (SDL_ISPIXELFORMAT_FOURCC(format)) {
+        if (SDL_CalculateYUVSize(format, width, height, &sz, &p) < 0) {
+            /* Overflow... */
+            return -1;
+        }
+    } else {
+        if (SDL_CalculateRGBSize(format, width, height, &sz, &p, minimalPitch) < 0) {
+            /* Overflow... */
+            return -1;
+        }
+    }
+
+    if (size) {
+        *size = sz;
+    }
+
+    if (pitch) {
+        *pitch = p;
+    }
+
+    return 0;
 }
 
 /*
@@ -77,7 +116,7 @@ SDL_CalculatePitch(Uint32 format, size_t width, SDL_bool minimal)
 SDL_Surface *
 SDL_CreateSurface(int width, int height, Uint32 format)
 {
-    size_t pitch;
+    size_t pitch, size;
     SDL_Surface *surface;
 
     if (width < 0) {
@@ -90,21 +129,10 @@ SDL_CreateSurface(int width, int height, Uint32 format)
         return NULL;
     }
 
-    if (SDL_ISPIXELFORMAT_FOURCC(format)) {
-        int p;
-        if (SDL_CalculateYUVSize(format, width, height, NULL, &p) < 0) {
-            /* Overflow... */
-            SDL_OutOfMemory();
-            return NULL;
-        }
-        pitch = p;
-    } else {
-        pitch = SDL_CalculatePitch(format, width, SDL_FALSE);
-        if (pitch > SDL_MAX_SINT32) {
-            /* Overflow... */
-            SDL_OutOfMemory();
-            return NULL;
-        }
+    if (SDL_CalculateSize(format, width, height, &size, &pitch, SDL_FALSE /* not minimal pitch */) < 0) {
+        /* Overflow... */
+        SDL_OutOfMemory();
+        return NULL;
     }
 
     /* Allocate the surface */
@@ -146,25 +174,6 @@ SDL_CreateSurface(int width, int height, Uint32 format)
 
     /* Get the pixels */
     if (surface->w && surface->h) {
-        size_t size;
-        if (SDL_ISPIXELFORMAT_FOURCC(surface->format->format)) {
-            /* Get correct size and pitch for YUV formats */
-            if (SDL_CalculateYUVSize(surface->format->format, surface->w, surface->h, &size, &surface->pitch) < 0) {
-                /* Overflow... */
-                SDL_DestroySurface(surface);
-                SDL_OutOfMemory();
-                return NULL;
-            }
-        } else {
-            /* Assumptions checked in surface_size_assumptions assert above */
-            if (SDL_size_mul_overflow(surface->h, surface->pitch, &size)) {
-                /* Overflow... */
-                SDL_DestroySurface(surface);
-                SDL_OutOfMemory();
-                return NULL;
-            }
-        }
-
         surface->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), size);
         if (!surface->pixels) {
             SDL_DestroySurface(surface);
@@ -219,15 +228,10 @@ SDL_CreateSurfaceFrom(void *pixels,
     } else {
         size_t minimalPitch;
 
-        if (SDL_ISPIXELFORMAT_FOURCC(format)) {
-            int p;
-            if (SDL_CalculateYUVSize(format, width, height, NULL, &p) < 0) {
-                SDL_InvalidParamError("pitch");
-                return NULL;
-            }
-            minimalPitch = p;
-        } else {
-            minimalPitch = SDL_CalculatePitch(format, width, SDL_TRUE);
+        if (SDL_CalculateSize(format, width, height, NULL, &minimalPitch, SDL_TRUE /* minimal pitch */) < 0) {
+            /* Overflow... */
+            SDL_OutOfMemory();
+            return NULL;
         }
 
         if (pitch < 0 || (size_t)pitch < minimalPitch) {
diff --git a/src/video/SDL_yuv.c b/src/video/SDL_yuv.c
index e7d5ff6303e6..fce528e32f43 100644
--- a/src/video/SDL_yuv.c
+++ b/src/video/SDL_yuv.c
@@ -62,7 +62,7 @@ SDL_YUV_CONVERSION_MODE SDL_GetYUVConversionModeForResolution(int width, int hei
  *
  * return 0 on success, -1 on error
  */
-int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, int *pitch)
+int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitch)
 {
 #if SDL_HAVE_YUV
     int sz_plane = 0, sz_plane_chroma = 0, sz_plane_packed = 0;
@@ -141,7 +141,7 @@ int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, int *pitch)
            if (SDL_size_mul_overflow(p1, 4, &p2) < 0) {
                return -1;
            }
-           *pitch = (int) p2;
+           *pitch = p2;
         }
 
         if (size) {
diff --git a/src/video/SDL_yuv_c.h b/src/video/SDL_yuv_c.h
index 4cafc3811fe4..d0ff4463ab40 100644
--- a/src/video/SDL_yuv_c.h
+++ b/src/video/SDL_yuv_c.h
@@ -31,6 +31,6 @@ extern int SDL_ConvertPixels_RGB_to_YUV(int width, int height, Uint32 src_format
 extern int SDL_ConvertPixels_YUV_to_YUV(int width, int height, Uint32 src_format, const void *src, int src_pitch, Uint32 dst_format, void *dst, int dst_pitch);
 
 
-extern int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, int *pitch);
+extern int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitch);
 
 #endif /* SDL_yuv_c_h_ */