render: simplify vertex and uniform data allocation. Improves performance of various SDL_Render functions (bug #4764).
diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c
index 5b0c1bf..6e7ec61 100644
--- a/src/render/SDL_render.c
+++ b/src/render/SDL_render.c
@@ -202,8 +202,6 @@
 static int
 FlushRenderCommands(SDL_Renderer *renderer)
 {
-    SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps;
-    SDL_AllocVertGap *gap = prevgap;
     int retval;
 
     SDL_assert((renderer->render_commands == NULL) == (renderer->render_commands_tail == NULL));
@@ -217,14 +215,6 @@
 
     retval = renderer->RunCommandQueue(renderer, renderer->render_commands, renderer->vertex_data, renderer->vertex_data_used);
 
-    while (gap) {
-        prevgap = gap;
-        gap = gap->next;
-    }
-    prevgap->next = renderer->vertex_data_gaps_pool;
-    renderer->vertex_data_gaps_pool = renderer->vertex_data_gaps.next;
-    renderer->vertex_data_gaps.next = NULL;
-
     /* Move the whole render command queue to the unused pool so we can reuse them next time. */
     if (renderer->render_commands_tail != NULL) {
         renderer->render_commands_tail->next = renderer->render_commands_pool;
@@ -263,79 +253,23 @@
     return FlushRenderCommands(renderer);
 }
 
-static SDL_AllocVertGap *
-AllocateVertexGap(SDL_Renderer *renderer)
-{
-    SDL_AllocVertGap *retval = renderer->vertex_data_gaps_pool;
-    if (retval) {
-        renderer->vertex_data_gaps_pool = retval->next;
-        retval->next = NULL;
-    } else {
-        retval = (SDL_AllocVertGap *) SDL_malloc(sizeof (SDL_AllocVertGap));
-        if (!retval) {
-            SDL_OutOfMemory();
-        }
-    }
-    return retval;
-}
-
-
 void *
 SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
 {
     const size_t needed = renderer->vertex_data_used + numbytes + alignment;
-    size_t aligner, aligned;
-    void *retval;
+    size_t current_offset = renderer->vertex_data_used;
 
-    SDL_AllocVertGap *prevgap = &renderer->vertex_data_gaps;
-    SDL_AllocVertGap *gap = prevgap->next;
-    while (gap) {
-        const size_t gapoffset = gap->offset;
-        aligner = (alignment && ((gap->offset % alignment) != 0)) ? (alignment - (gap->offset % alignment)) : 0;
-        aligned = gapoffset + aligner;
+    size_t aligner = (alignment && ((current_offset & (alignment - 1)) != 0)) ? (alignment - (current_offset & (alignment - 1))) : 0;
+    size_t aligned = current_offset + aligner;
 
-        /* Can we use this gap? */
-        if ((aligner < gap->len) && ((gap->len - aligner) >= numbytes)) {
-            /* we either finished this gap off, trimmed the left, trimmed the right, or split it into two gaps. */
-            if (gap->len == numbytes) {  /* finished it off, remove it */
-                SDL_assert(aligned == gapoffset);
-                prevgap->next = gap->next;
-                gap->next = renderer->vertex_data_gaps_pool;
-                renderer->vertex_data_gaps_pool = gap;
-            } else if (aligned == gapoffset) {  /* trimmed the left */
-                gap->offset += numbytes;
-                gap->len -= numbytes;
-            } else if (((aligned - gapoffset) + numbytes) == gap->len) {  /* trimmed the right */
-                gap->len -= numbytes;
-            } else {  /* split into two gaps */
-                SDL_AllocVertGap *newgap = AllocateVertexGap(renderer);
-                if (!newgap) {
-                    return NULL;
-                }
-                newgap->offset = aligned + numbytes;
-                newgap->len = gap->len - (aligner + numbytes);
-                newgap->next = gap->next;
-                // gap->offset doesn't change.
-                gap->len = aligner;
-                gap->next = newgap;
-            }
-
-            if (offset) {
-                *offset = aligned;
-            }
-            return ((Uint8 *) renderer->vertex_data) + aligned;
-        }
-
-        /* Try the next gap */
-        prevgap = gap;
-        gap = gap->next;
-    }
-
-    /* no gaps with enough space; get a new piece of the vertex buffer */
-    while (needed > renderer->vertex_data_allocation) {
+    if (renderer->vertex_data_allocation < needed) {
         const size_t current_allocation = renderer->vertex_data ? renderer->vertex_data_allocation : 1024;
-        const size_t newsize = current_allocation * 2;
-        void *ptr = SDL_realloc(renderer->vertex_data, newsize);
+        size_t newsize = current_allocation * 2;
+        void *ptr;
+        while (newsize < needed) {
+            newsize *= 2;
+        }
+        ptr = SDL_realloc(renderer->vertex_data, newsize);
         if (ptr == NULL) {
             SDL_OutOfMemory();
             return NULL;
@@ -344,27 +278,13 @@
         renderer->vertex_data_allocation = newsize;
     }
 
-    aligner = (alignment && ((renderer->vertex_data_used % alignment) != 0)) ? (alignment - (renderer->vertex_data_used % alignment)) : 0;
-    aligned = renderer->vertex_data_used + aligner;
-
-    retval = ((Uint8 *) renderer->vertex_data) + aligned;
     if (offset) {
         *offset = aligned;
     }
 
-    if (aligner) {  /* made a new gap... */
-        SDL_AllocVertGap *newgap = AllocateVertexGap(renderer);
-        if (newgap) {  /* just let it slide as lost space if malloc fails. */
-            newgap->offset = renderer->vertex_data_used;
-            newgap->len = aligner;
-            newgap->next = NULL;
-            prevgap->next = newgap;
-        }
-    }
-
     renderer->vertex_data_used += aligner + numbytes;
 
-    return retval;
+    return ((Uint8 *) renderer->vertex_data) + aligned;
 }
 
 static SDL_RenderCommand *
@@ -3177,8 +3097,6 @@
 SDL_DestroyRenderer(SDL_Renderer * renderer)
 {
     SDL_RenderCommand *cmd;
-    SDL_AllocVertGap *gap;
-    SDL_AllocVertGap *nextgap;
 
     CHECK_RENDERER_MAGIC(renderer, );
 
@@ -3203,16 +3121,6 @@
 
     SDL_free(renderer->vertex_data);
 
-    for (gap = renderer->vertex_data_gaps.next; gap; gap = nextgap) {
-        nextgap = gap->next;
-        SDL_free(gap);
-    }
-
-    for (gap = renderer->vertex_data_gaps_pool; gap; gap = nextgap) {
-        nextgap = gap->next;
-        SDL_free(gap);
-    }
-
     /* Free existing textures for this renderer */
     while (renderer->textures) {
         SDL_Texture *tex = renderer->textures; (void) tex;
diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h
index 9386562..dedd642 100644
--- a/src/render/SDL_sysrender.h
+++ b/src/render/SDL_sysrender.h
@@ -110,13 +110,6 @@
     struct SDL_RenderCommand *next;
 } SDL_RenderCommand;
 
-typedef struct SDL_AllocVertGap
-{
-    size_t offset;
-    size_t len;
-    struct SDL_AllocVertGap *next;
-} SDL_AllocVertGap;
-
 
 /* Define the SDL renderer structure */
 struct SDL_Renderer
@@ -226,8 +219,6 @@
     void *vertex_data;
     size_t vertex_data_used;
     size_t vertex_data_allocation;
-    SDL_AllocVertGap vertex_data_gaps;
-    SDL_AllocVertGap *vertex_data_gaps_pool;
 
     void *driverdata;
 };