SDL: Move to SDL_RenderGeometryRaw prototype with separate xy/uv/color pointer parameters

From e481261173f84cd810b62a4bf4a9b208c661a21e Mon Sep 17 00:00:00 2001
From: Sylvain <[EMAIL REDACTED]>
Date: Thu, 1 Apr 2021 09:49:16 +0200
Subject: [PATCH] Move to SDL_RenderGeometryRaw prototype with separate
 xy/uv/color pointer parameters

---
 include/SDL_render.h                    | 34 ++++++------
 src/dynapi/SDL_dynapi_overrides.h       |  1 +
 src/dynapi/SDL_dynapi_procs.h           |  1 +
 src/render/SDL_render.c                 | 69 ++++++++++++++++++++-----
 src/render/SDL_sysrender.h              |  4 +-
 src/render/opengl/SDL_render_gl.c       | 35 +++++++++----
 src/render/opengles2/SDL_render_gles2.c | 37 +++++++++----
 src/render/software/SDL_render_sw.c     | 53 ++++++++++++++-----
 8 files changed, 167 insertions(+), 67 deletions(-)

diff --git a/include/SDL_render.h b/include/SDL_render.h
index 797274c078..1022f9c96d 100644
--- a/include/SDL_render.h
+++ b/include/SDL_render.h
@@ -137,17 +137,6 @@ typedef struct SDL_Renderer SDL_Renderer;
 struct SDL_Texture;
 typedef struct SDL_Texture SDL_Texture;
 
-/**
- *  \brief Vertex structure
- */
-typedef struct SDL_Vertex
-{
-    SDL_FPoint position;        /**< Vertex position, in SDL_Renderer coordinates  */
-    SDL_Color  color;           /**< Vertex color */
-    SDL_FPoint tex_coord;       /**< Normalized texture coordinates, if needed */
-} SDL_Vertex;
-
-
 /* Function prototypes */
 
 /**
@@ -1453,23 +1442,30 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer,
                                             const SDL_RendererFlip flip);
 
 /**
- *  \brief Render a list of triangles, optionally using a texture and indices into the vertex array
+ *  \brief Render a list of triangles, optionally using a texture and indices into the vertex arrays
  *  Color and alpha modulation is done per vertex (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored).
  *
  *  \param texture      (optional) The SDL texture to use.
- *  \param vertices     Vertices.
+ *  \param xy           Vertex positions
+ *  \param xy_stride    Byte size to move from one element to the next element
+ *  \param color        Vertex colors (as SDL_Color)
+ *  \param color_stride Byte size to move from one element to the next element
+ *  \param uv           Vertex normalized texture coordinates
+ *  \param uv_stride    Byte size to move from one element to the next element
  *  \param num_vertices Number of vertices.
- *  \param indices      (optional) An array of integer indices into the 'vertices' array, if NULL all vertices will be rendered in sequential order.
+ *  \param indices      (optional) An array of indices into the 'vertices' arrays, if NULL all vertices will be rendered in sequential order.
  *  \param num_indices  Number of indices.
- *
- *  \sa SDL_Vertex
+ *  \param size_indice  Indice size: 1 (byte), 2 (short), 4 (int)
  *
  *  \return 0 on success, or -1 if the operation is not supported
  */
-extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer,
+extern DECLSPEC int SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer,
                                                SDL_Texture *texture,
-                                               SDL_Vertex *vertices, int num_vertices,
-                                               int *indices, int num_indices);
+                                               const float *xy, int xy_stride,
+                                               const int *color, int color_stride,
+                                               const float *uv, int uv_stride,
+                                               int num_vertices,
+                                               const void *indices, int num_indices, int size_indice);
 
 /**
  * Read pixels from the current rendering target to an array of pixels.
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 1175365f48..6a849c4fd4 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -818,3 +818,4 @@
 #define SDL_SetTextureUserData SDL_SetTextureUserData_REAL
 #define SDL_GetTextureUserData SDL_GetTextureUserData_REAL
 #define SDL_RenderGeometry SDL_RenderGeometry_REAL
+#define SDL_RenderGeometryRaw SDL_RenderGeometryRaw_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 7c721f8ccb..88ecb994a5 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -883,3 +883,4 @@ SDL_DYNAPI_PROC(float,SDL_GameControllerGetSensorDataRate,(SDL_GameController *a
 SDL_DYNAPI_PROC(int,SDL_SetTextureUserData,(SDL_Texture *a, void *b),(a,b),return)
 SDL_DYNAPI_PROC(void*,SDL_GetTextureUserData,(SDL_Texture *a),(a),return)
 SDL_DYNAPI_PROC(int,SDL_RenderGeometry,(SDL_Renderer *a, SDL_Texture *b, SDL_Vertex *c, int d, int *e, int f),(a,b,c,d,e,f),return)
+SDL_DYNAPI_PROC(int,SDL_RenderGeometryRaw,(SDL_Renderer *a, SDL_Texture *b, const float *c, int d, const int *e, int f, const float *g, int h, int i, const void *j, int k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return)
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 746bdf04d8..d8c49ba49c 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -564,7 +564,12 @@ QueueCmdCopyEx(SDL_Renderer *renderer, SDL_Texture * texture,
 
 static int
 QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture,
-        SDL_Vertex *vertices, int num_vertices, int *indices, int num_indices, float scale_x, float scale_y)
+        const float *xy, int xy_stride,
+        const int *color, int color_stride,
+        const float *uv, int uv_stride,
+        int num_vertices,
+        const void *indices, int num_indices, int size_indice,
+        float scale_x, float scale_y)
 {
     SDL_RenderCommand *cmd;
     int retval = -1;
@@ -574,7 +579,10 @@ QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture,
         cmd = PrepQueueCmdDrawSolid(renderer, SDL_RENDERCMD_GEOMETRY);
     }
     if (cmd != NULL) {
-        retval = renderer->QueueGeometry(renderer, cmd, texture, vertices, num_vertices, indices, num_indices, scale_x, scale_y);
+        retval = renderer->QueueGeometry(renderer, cmd, texture,
+                xy, xy_stride, color, color_stride, uv, uv_stride,
+                num_vertices, indices, num_indices, size_indice,
+                scale_x, scale_y);
         if (retval < 0) {
             cmd->command = SDL_RENDERCMD_NO_OP;
         }
@@ -3323,13 +3331,16 @@ SDL_RenderCopyExF(SDL_Renderer * renderer, SDL_Texture * texture,
 }
 
 int
-SDL_RenderGeometry(SDL_Renderer *renderer,
-                   SDL_Texture *texture,
-                   SDL_Vertex *vertices, int num_vertices,
-                   int *indices, int num_indices)
+SDL_RenderGeometryRaw(SDL_Renderer *renderer,
+                                  SDL_Texture *texture,
+                                  const float *xy, int xy_stride,
+                                  const int *color, int color_stride,
+                                  const float *uv, int uv_stride,
+                                  int num_vertices,
+                                  const void *indices, int num_indices, int size_indice)
 {
     int i;
-    int retval;
+    int retval = 0;
     int count = indices ? num_indices : num_vertices;
 
     CHECK_RENDERER_MAGIC(renderer, -1);
@@ -3346,14 +3357,30 @@ SDL_RenderGeometry(SDL_Renderer *renderer,
         }
     }
 
-    if (!vertices) {
-        return SDL_InvalidParamError("points");
+    if (!xy) {
+        return SDL_InvalidParamError("xy");
+    }
+
+    if (!color) {
+        return SDL_InvalidParamError("color");
+    }
+
+    if (texture && !uv) {
+        return SDL_InvalidParamError("uv");
     }
 
     if (count % 3 != 0) {
         return SDL_InvalidParamError(indices ? "num_indices" : "num_vertices");
     }
 
+    if (indices) {
+        if (size_indice != 1 && size_indice != 2 && size_indice != 4) {
+            return SDL_InvalidParamError("size_indice");
+        }
+    } else {
+        size_indice = 0;
+    }
+
     /* Don't draw while we're hidden */
     if (renderer->hidden) {
         return 0;
@@ -3369,26 +3396,40 @@ SDL_RenderGeometry(SDL_Renderer *renderer,
 
     if (texture) {
         for (i = 0; i < num_vertices; ++i) {
-            if (vertices[i].tex_coord.x < 0.0f || vertices[i].tex_coord.y < 0.0f || vertices[i].tex_coord.x > 1.0f || vertices[i].tex_coord.y > 1.0f) {
-                return SDL_SetError("Values of 'vertices' out of bounds");
+            const float *uv_ = (const float *)((const char*)uv + i * uv_stride);
+            float u = uv_[0];
+            float v = uv_[1];
+            if (u < 0.0f || v < 0.0f || u > 1.0f || v > 1.0f) {
+                return SDL_SetError("Values of 'uv' out of bounds %f %f at %d/%d", u, v, i, num_vertices);
             }
         }
     }
 
     if (indices) {
         for (i = 0; i < num_indices; ++i) {
-            if (indices[i] < 0 || indices[i] >= num_vertices) {
+            int j;
+            if (size_indice == 4) {
+                j = ((const Uint32 *)indices)[i];
+            } else if (size_indice == 2) {
+                j = ((const Uint16 *)indices)[i];
+            } else {
+                j = ((const Uint8 *)indices)[i];
+            }
+            if (j < 0 || j >= num_vertices) {
                 return SDL_SetError("Values of 'indices' out of bounds");
             }
         }
     }
 
-
     if (texture) {
         texture->last_command_generation = renderer->render_command_generation;
     }
 
-    retval = QueueCmdGeometry(renderer, texture, vertices, num_vertices, indices, num_indices, renderer->scale.x, renderer->scale.y);
+    retval = QueueCmdGeometry(renderer, texture,
+            xy, xy_stride, color, color_stride, uv, uv_stride,
+            num_vertices,
+            indices, num_indices, size_indice,
+            renderer->scale.x, renderer->scale.y);
 
     return retval < 0 ? retval : FlushRenderCommandsIfNotBatching(renderer);
 }
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index 1beb4b248b..5c2add1f30 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -131,7 +131,9 @@ struct SDL_Renderer
                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
 
     int (*QueueGeometry) (SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
-                          SDL_Vertex *vertices, int num_vertices, int *indices, int num_indices, float scale_x, float scale_y);
+                          const float *xy, int xy_stride, const int *color, int color_stride, const float *uv, int uv_stride,
+                          int num_vertices, const void *indices, int num_indices, int size_indice,
+                          float scale_x, float scale_y);
 
     int (*RunCommandQueue) (SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize);
     int (*UpdateTexture) (SDL_Renderer * renderer, SDL_Texture * texture,
diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c
index cd531dc287..d9caf84b76 100644
--- a/src/render/opengl/SDL_render_gl.c
+++ b/src/render/opengl/SDL_render_gl.c
@@ -1054,7 +1054,9 @@ GL_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * te
 
 static int
 GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
-        SDL_Vertex *vertices, int num_vertices, int *indices, int num_indices, float scale_x, float scale_y)
+        const float *xy, int xy_stride, const int *color, int color_stride, const float *uv, int uv_stride,
+        int num_vertices, const void *indices, int num_indices, int size_indice,
+        float scale_x, float scale_y)
 {
     GL_TextureData *texturedata = NULL;
     int i;
@@ -1074,19 +1076,32 @@ GL_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *te
     cmd->data.draw.count = count;
 
     for (i = 0; i < count; i++) {
-        SDL_Vertex *v = &vertices[indices ? indices[i] : i];
+        int j;
+        if (size_indice == 4) {
+            j = ((const Uint32 *)indices)[i];
+        } else if (size_indice == 2) {
+            j = ((const Uint16 *)indices)[i];
+        } else if (size_indice == 1) {
+            j = ((const Uint8 *)indices)[i];
+        } else {
+            j = i;
+        }
+
+        float *xy_ = (float *)((char*)xy + j * xy_stride);
+        SDL_Color col_ = *(SDL_Color *)((char*)color + j * color_stride);
 
-        *(verts++) = v->position.x * scale_x;
-        *(verts++) = v->position.y * scale_y;
+        *(verts++) = xy_[0] * scale_x;
+        *(verts++) = xy_[1] * scale_y;
 
-        *(verts++) = v->color.r * inv255f;
-        *(verts++) = v->color.g * inv255f;
-        *(verts++) = v->color.b * inv255f;
-        *(verts++) = v->color.a * inv255f;
+        *(verts++) = col_.r * inv255f;
+        *(verts++) = col_.g * inv255f;
+        *(verts++) = col_.b * inv255f;
+        *(verts++) = col_.a * inv255f;
 
         if (texture) {
-            *(verts++) = v->tex_coord.x * texturedata->texw;
-            *(verts++) = v->tex_coord.y * texturedata->texh;
+            float *uv_ = (float *)((char*)uv + j * uv_stride);
+            *(verts++) = uv_[0] * texturedata->texw;
+            *(verts++) = uv_[1] * texturedata->texh;
         }
     }
     return 0;
diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c
index 775c0f4a85..6b997588be 100644
--- a/src/render/opengles2/SDL_render_gles2.c
+++ b/src/render/opengles2/SDL_render_gles2.c
@@ -960,7 +960,9 @@ GLES2_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture *
 
 static int
 GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
-        SDL_Vertex *vertices, int num_vertices, int *indices, int num_indices, float scale_x, float scale_y)
+        const float *xy, int xy_stride, const int *color, int color_stride, const float *uv, int uv_stride,
+        int num_vertices, const void *indices, int num_indices, int size_indice,
+        float scale_x, float scale_y)
 {
     int i;
     const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
@@ -976,20 +978,35 @@ GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture
     cmd->data.draw.count = count;
 
     for (i = 0; i < count; i++) {
-        SDL_Vertex *v = &vertices[indices ? indices[i] : i];
+        int j;
+        if (size_indice == 4) {
+            j = ((const Uint32 *)indices)[i];
+        } else if (size_indice == 2) {
+            j = ((const Uint16 *)indices)[i];
+        } else if (size_indice == 1) {
+            j = ((const Uint8 *)indices)[i];
+        } else {
+            j = i;
+        }
+
+        float *xy_ = (float *)((char*)xy + j * xy_stride);
+        SDL_Color col_ = *(SDL_Color *)((char*)color + j * color_stride);
 
-        *(verts++) = v->position.x * scale_x;
-        *(verts++) = v->position.y * scale_y;
-        *(verts++) = (colorswap ? v->color.b : v->color.r) * inv255f;
-        *(verts++) = v->color.g * inv255f;
-        *(verts++) = (colorswap ? v->color.r : v->color.b) * inv255f;
-        *(verts++) = v->color.a * inv255f;
+        *(verts++) = xy_[0] * scale_x;
+        *(verts++) = xy_[1] * scale_y;
+
+        *(verts++) = (colorswap ? col_.b : col_.r) * inv255f;
+        *(verts++) = col_.g * inv255f;
+        *(verts++) = (colorswap ? col_.r : col_.b) * inv255f;
+        *(verts++) = col_.a * inv255f;
 
         if (texture) {
-            *(verts++) = v->tex_coord.x;
-            *(verts++) = v->tex_coord.y;
+            float *uv_ = (float *)((char*)uv + j * uv_stride);
+            *(verts++) = uv_[0];
+            *(verts++) = uv_[1];
         }
     }
+
     return 0;
 }
 
diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c
index fbc948ecf0..0dcdc2adb5 100644
--- a/src/render/software/SDL_render_sw.c
+++ b/src/render/software/SDL_render_sw.c
@@ -577,7 +577,9 @@ typedef struct GeometryCopyData
 
 static int
 SW_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
-        SDL_Vertex *vertices, int num_vertices, int *indices, int num_indices, float scale_x, float scale_y)
+        const float *xy, int xy_stride, const int *color, int color_stride, const float *uv, int uv_stride,
+        int num_vertices, const void *indices, int num_indices, int size_indice,
+        float scale_x, float scale_y)
 {
     int i;
     int count = indices ? num_indices : num_vertices;
@@ -594,16 +596,30 @@ SW_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *te
     if (texture) {
         GeometryCopyData *ptr = (GeometryCopyData *) verts;
         for (i = 0; i < count; i++) {
-            SDL_Vertex *v = &vertices[indices ? indices[i] : i];
+            int j;
+            if (size_indice == 4) {
+                j = ((const Uint32 *)indices)[i];
+            } else if (size_indice == 2) {
+                j = ((const Uint16 *)indices)[i];
+            } else if (size_indice == 1) {
+                j = ((const Uint8 *)indices)[i];
+            } else {
+                j = i;
+            }
+
+            float *xy_ = (float *)((char*)xy + j * xy_stride);
+            SDL_Color col_ = *(SDL_Color *)((char*)color + j * color_stride);
+
+            float *uv_ = (float *)((char*)uv + j * uv_stride);
 
-            ptr->src.x = v->tex_coord.x * texture->w;
-            ptr->src.y = v->tex_coord.y * texture->h;
+            ptr->src.x = uv_[0] * texture->w;
+            ptr->src.y = uv_[1] * texture->h;
 
-            ptr->dst.x = v->position.x * scale_x + renderer->viewport.x;
-            ptr->dst.y = v->position.y * scale_y + renderer->viewport.y;
+            ptr->dst.x = xy_[0] * scale_x + renderer->viewport.x;
+            ptr->dst.y = xy_[1] * scale_y + renderer->viewport.y;
             trianglepoint_2_fixedpoint(&ptr->dst);
 
-            ptr->color = v->color;
+            ptr->color = col_;
 
             ptr++;
        }
@@ -611,18 +627,29 @@ SW_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *te
         GeometryFillData *ptr = (GeometryFillData *) verts;
 
         for (i = 0; i < count; i++) {
-            SDL_Vertex *v = &vertices[indices ? indices[i] : i];
+            int j;
+            if (size_indice == 4) {
+                j = ((const Uint32 *)indices)[i];
+            } else if (size_indice == 2) {
+                j = ((const Uint16 *)indices)[i];
+            } else if (size_indice == 1) {
+                j = ((const Uint8 *)indices)[i];
+            } else {
+                j = i;
+            }
 
-            ptr->dst.x = v->position.x * scale_x + renderer->viewport.x;
-            ptr->dst.y = v->position.y * scale_y + renderer->viewport.y;
+            float *xy_ = (float *)((char*)xy + j * xy_stride);
+            SDL_Color col_ = *(SDL_Color *)((char*)color + j * color_stride);
+
+            ptr->dst.x = xy_[0] * scale_x + renderer->viewport.x;
+            ptr->dst.y = xy_[1] * scale_y + renderer->viewport.y;
             trianglepoint_2_fixedpoint(&ptr->dst);
 
-            ptr->color = v->color;
+            ptr->color = col_;
 
             ptr++;
        }
     }
-
     return 0;
 }
 
@@ -700,7 +727,7 @@ SW_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertic
             }
 
             case SDL_RENDERCMD_SETCLIPRECT: {
-                drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;                
+                drawstate.cliprect = cmd->data.cliprect.enabled ? &cmd->data.cliprect.rect : NULL;
                 drawstate.surface_cliprect_dirty = SDL_TRUE;
                 break;
             }