From 03f8528315fa46c95991a34f3325d7b33ae5538c Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Sat, 02 May 2020 21:48:36 +0000
Subject: [PATCH] Update source to SDL2 2.0.12

---
 source/src/render/opengles/SDL_render_gles.c | 1167 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 581 insertions(+), 586 deletions(-)

diff --git a/source/src/render/opengles/SDL_render_gles.c b/source/src/render/opengles/SDL_render_gles.c
index 4007dff..044a1be 100644
--- a/source/src/render/opengles/SDL_render_gles.c
+++ b/source/src/render/opengles/SDL_render_gles.c
@@ -1,6 +1,6 @@
 /*
   Simple DirectMedia Layer
-  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -22,12 +22,13 @@
 
 #if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED
 
+#include "SDL_assert.h"
 #include "SDL_hints.h"
 #include "SDL_opengles.h"
 #include "../SDL_sysrender.h"
 
-/* To prevent unnecessary window recreation, 
- * these should match the defaults selected in SDL_GL_ResetAttributes 
+/* To prevent unnecessary window recreation,
+ * these should match the defaults selected in SDL_GL_ResetAttributes
  */
 
 #define RENDERER_CONTEXT_MAJOR 1
@@ -52,45 +53,6 @@
 
 static const float inv255f = 1.0f / 255.0f;
 
-static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
-static void GLES_WindowEvent(SDL_Renderer * renderer,
-                             const SDL_WindowEvent *event);
-static int GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
-static SDL_bool GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode);
-static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
-static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
-                              const SDL_Rect * rect, const void *pixels,
-                              int pitch);
-static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
-                            const SDL_Rect * rect, void **pixels, int *pitch);
-static void GLES_UnlockTexture(SDL_Renderer * renderer,
-                               SDL_Texture * texture);
-static int GLES_SetRenderTarget(SDL_Renderer * renderer,
-                                 SDL_Texture * texture);
-static int GLES_UpdateViewport(SDL_Renderer * renderer);
-static int GLES_UpdateClipRect(SDL_Renderer * renderer);
-static int GLES_RenderClear(SDL_Renderer * renderer);
-static int GLES_RenderDrawPoints(SDL_Renderer * renderer,
-                                 const SDL_FPoint * points, int count);
-static int GLES_RenderDrawLines(SDL_Renderer * renderer,
-                                const SDL_FPoint * points, int count);
-static int GLES_RenderFillRects(SDL_Renderer * renderer,
-                                const SDL_FRect * rects, int count);
-static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
-                           const SDL_Rect * srcrect,
-                           const SDL_FRect * dstrect);
-static int GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
-                         const SDL_Rect * srcrect, const SDL_FRect * dstrect,
-                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
-static int GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
-                    Uint32 pixel_format, void * pixels, int pitch);
-static void GLES_RenderPresent(SDL_Renderer * renderer);
-static void GLES_DestroyTexture(SDL_Renderer * renderer,
-                                SDL_Texture * texture);
-static void GLES_DestroyRenderer(SDL_Renderer * renderer);
-static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
-static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
-
 typedef struct GLES_FBOList GLES_FBOList;
 
 struct GLES_FBOList
@@ -100,26 +62,27 @@
    GLES_FBOList *next;
 };
 
-
-SDL_RenderDriver GLES_RenderDriver = {
-    GLES_CreateRenderer,
-    {
-     "opengles",
-     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
-     1,
-     {SDL_PIXELFORMAT_ABGR8888},
-     0,
-     0}
-};
+typedef struct
+{
+    SDL_Rect viewport;
+    SDL_bool viewport_dirty;
+    SDL_Texture *texture;
+    SDL_Texture *target;
+    int drawablew;
+    int drawableh;
+    SDL_BlendMode blend;
+    SDL_bool cliprect_enabled_dirty;
+    SDL_bool cliprect_enabled;
+    SDL_bool cliprect_dirty;
+    SDL_Rect cliprect;
+    SDL_bool texturing;
+    Uint32 color;
+    Uint32 clear_color;
+} GLES_DrawStateCache;
 
 typedef struct
 {
     SDL_GLContext context;
-    struct {
-        Uint32 color;
-        SDL_BlendMode blendMode;
-        SDL_bool tex_coords;
-    } current;
 
 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
 #define SDL_PROC_OES SDL_PROC
@@ -133,6 +96,8 @@
     SDL_bool GL_OES_blend_func_separate_supported;
     SDL_bool GL_OES_blend_equation_separate_supported;
     SDL_bool GL_OES_blend_subtract_supported;
+
+    GLES_DrawStateCache drawstate;
 } GLES_RenderData;
 
 typedef struct
@@ -206,7 +171,7 @@
 #define SDL_PROC_OES(ret,func,params) \
     do { \
         data->func = SDL_GL_GetProcAddress(#func); \
-    } while ( 0 );    
+    } while ( 0 );
 #endif /* __SDL_NOGETPROCADDR__ */
 
 #include "SDL_glesfuncs.h"
@@ -214,8 +179,6 @@
 #undef SDL_PROC_OES
     return 0;
 }
-
-static SDL_GLContext SDL_CurrentContext = NULL;
 
 static GLES_FBOList *
 GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h)
@@ -241,191 +204,19 @@
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
 
-    if (SDL_CurrentContext != data->context) {
+    if (SDL_GL_GetCurrentContext() != data->context) {
         if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
             return -1;
         }
-        SDL_CurrentContext = data->context;
-
-        GLES_UpdateViewport(renderer);
     }
+
     return 0;
-}
-
-/* This is called if we need to invalidate all of the SDL OpenGL state */
-static void
-GLES_ResetState(SDL_Renderer *renderer)
-{
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
-    if (SDL_CurrentContext == data->context) {
-        GLES_UpdateViewport(renderer);
-    } else {
-        GLES_ActivateRenderer(renderer);
-    }
-
-    data->current.color = 0xffffffff;
-    data->current.blendMode = SDL_BLENDMODE_INVALID;
-    data->current.tex_coords = SDL_FALSE;
-
-    data->glDisable(GL_DEPTH_TEST);
-    data->glDisable(GL_CULL_FACE);
-
-    data->glMatrixMode(GL_MODELVIEW);
-    data->glLoadIdentity();
-
-    data->glEnableClientState(GL_VERTEX_ARRAY);
-    data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-}
-
-SDL_Renderer *
-GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
-{
-
-    SDL_Renderer *renderer;
-    GLES_RenderData *data;
-    GLint value;
-    Uint32 window_flags;
-    int profile_mask = 0, major = 0, minor = 0;
-    SDL_bool changed_window = SDL_FALSE;
-
-    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
-    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
-    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
-
-    window_flags = SDL_GetWindowFlags(window);
-    if (!(window_flags & SDL_WINDOW_OPENGL) ||
-        profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
-
-        changed_window = SDL_TRUE;
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
-
-        if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
-            goto error;
-        }
-    }
-
-    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
-    if (!renderer) {
-        SDL_OutOfMemory();
-        goto error;
-    }
-
-    data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
-    if (!data) {
-        GLES_DestroyRenderer(renderer);
-        SDL_OutOfMemory();
-        goto error;
-    }
-
-    renderer->WindowEvent = GLES_WindowEvent;
-    renderer->GetOutputSize = GLES_GetOutputSize;
-    renderer->SupportsBlendMode = GLES_SupportsBlendMode;
-    renderer->CreateTexture = GLES_CreateTexture;
-    renderer->UpdateTexture = GLES_UpdateTexture;
-    renderer->LockTexture = GLES_LockTexture;
-    renderer->UnlockTexture = GLES_UnlockTexture;
-    renderer->SetRenderTarget = GLES_SetRenderTarget;
-    renderer->UpdateViewport = GLES_UpdateViewport;
-    renderer->UpdateClipRect = GLES_UpdateClipRect;
-    renderer->RenderClear = GLES_RenderClear;
-    renderer->RenderDrawPoints = GLES_RenderDrawPoints;
-    renderer->RenderDrawLines = GLES_RenderDrawLines;
-    renderer->RenderFillRects = GLES_RenderFillRects;
-    renderer->RenderCopy = GLES_RenderCopy;
-    renderer->RenderCopyEx = GLES_RenderCopyEx;
-    renderer->RenderReadPixels = GLES_RenderReadPixels;
-    renderer->RenderPresent = GLES_RenderPresent;
-    renderer->DestroyTexture = GLES_DestroyTexture;
-    renderer->DestroyRenderer = GLES_DestroyRenderer;
-    renderer->GL_BindTexture = GLES_BindTexture;
-    renderer->GL_UnbindTexture = GLES_UnbindTexture;
-    renderer->info = GLES_RenderDriver.info;
-    renderer->info.flags = SDL_RENDERER_ACCELERATED;
-    renderer->driverdata = data;
-    renderer->window = window;
-
-    data->context = SDL_GL_CreateContext(window);
-    if (!data->context) {
-        GLES_DestroyRenderer(renderer);
-        goto error;
-    }
-    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
-        GLES_DestroyRenderer(renderer);
-        goto error;
-    }
-
-    if (GLES_LoadFunctions(data) < 0) {
-        GLES_DestroyRenderer(renderer);
-        goto error;
-    }
-
-    if (flags & SDL_RENDERER_PRESENTVSYNC) {
-        SDL_GL_SetSwapInterval(1);
-    } else {
-        SDL_GL_SetSwapInterval(0);
-    }
-    if (SDL_GL_GetSwapInterval() > 0) {
-        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
-    }
-
-    value = 0;
-    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
-    renderer->info.max_texture_width = value;
-    value = 0;
-    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
-    renderer->info.max_texture_height = value;
-
-    /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
-    if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
-        data->GL_OES_framebuffer_object_supported = SDL_TRUE;
-        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
-
-        value = 0;
-        data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
-        data->window_framebuffer = (GLuint)value;
-    }
-    data->framebuffers = NULL;
-
-    if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
-        data->GL_OES_blend_func_separate_supported = SDL_TRUE;
-    }
-    if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
-        data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
-    }
-    if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
-        data->GL_OES_blend_subtract_supported = SDL_TRUE;
-    }
-
-    /* Set up parameters for rendering */
-    GLES_ResetState(renderer);
-
-    return renderer;
-
-error:
-    if (changed_window) {
-        /* Uh oh, better try to put it back... */
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
-        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
-        SDL_RecreateWindow(window, window_flags);
-    }
-    return NULL;
 }
 
 static void
 GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
-    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
-        event->event == SDL_WINDOWEVENT_SHOWN ||
-        event->event == SDL_WINDOWEVENT_HIDDEN) {
-        /* Rebind the context to the window area and update matrices */
-        SDL_CurrentContext = NULL;
-    }
 
     if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
         /* According to Apple documentation, we need to finish drawing NOW! */
@@ -561,7 +352,7 @@
         }
     }
 
-    
+
     if (texture->access == SDL_TEXTUREACCESS_TARGET) {
         if (!renderdata->GL_OES_framebuffer_object_supported) {
             SDL_free(data);
@@ -571,7 +362,7 @@
     } else {
         data->fbo = NULL;
     }
-    
+
 
     renderdata->glGetError();
     renderdata->glEnable(GL_TEXTURE_2D);
@@ -601,13 +392,15 @@
     renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
                              texture_h, 0, format, type, NULL);
     renderdata->glDisable(GL_TEXTURE_2D);
+    renderdata->drawstate.texture = texture;
+    renderdata->drawstate.texturing = SDL_FALSE;
 
     result = renderdata->glGetError();
     if (result != GL_NO_ERROR) {
         SDL_free(data);
         return GLES_SetError("glTexImage2D()", result);
     }
-    
+
     texture->driverdata = data;
     return 0;
 }
@@ -664,6 +457,9 @@
     renderdata->glDisable(data->type);
     SDL_free(blob);
 
+    renderdata->drawstate.texture = texture;
+    renderdata->drawstate.texturing = SDL_FALSE;
+
     if (renderdata->glGetError() != GL_NO_ERROR) {
         return SDL_SetError("Failed to update texture");
     }
@@ -697,6 +493,18 @@
     GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
 }
 
+static void
+GLES_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
+{
+    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
+    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
+    GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
+
+    renderdata->glBindTexture(data->type, data->texture);
+    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, glScaleMode);
+    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, glScaleMode);
+}
+
 static int
 GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
 {
@@ -707,6 +515,8 @@
     if (!data->GL_OES_framebuffer_object_supported) {
         return SDL_SetError("Can't enable render target support in this renderer");
     }
+
+    data->drawstate.viewport_dirty = SDL_TRUE;
 
     if (texture == NULL) {
         data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
@@ -725,293 +535,77 @@
     return 0;
 }
 
+
 static int
-GLES_UpdateViewport(SDL_Renderer * renderer)
+GLES_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
 {
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
-    if (SDL_CurrentContext != data->context) {
-        /* We'll update the viewport after we rebind the context */
-        return 0;
-    }
-
-    if (renderer->target) {
-        data->glViewport(renderer->viewport.x, renderer->viewport.y,
-                         renderer->viewport.w, renderer->viewport.h);
-    } else {
-        int w, h;
-
-        SDL_GL_GetDrawableSize(renderer->window, &w, &h);
-        data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
-                         renderer->viewport.w, renderer->viewport.h);
-    }
-
-    data->glMatrixMode(GL_PROJECTION);
-    data->glLoadIdentity();
-    if (renderer->viewport.w && renderer->viewport.h) {
-        if (renderer->target) {
-            data->glOrthof((GLfloat) 0,
-                           (GLfloat) renderer->viewport.w,
-                           (GLfloat) 0,
-                           (GLfloat) renderer->viewport.h,
-                           0.0, 1.0);
-        } else {
-            data->glOrthof((GLfloat) 0,
-                           (GLfloat) renderer->viewport.w,
-                           (GLfloat) renderer->viewport.h,
-                           (GLfloat) 0,
-                           0.0, 1.0);
-        }
-    }
-    data->glMatrixMode(GL_MODELVIEW);
-
-    return 0;
+    return 0;  /* nothing to do in this backend. */
 }
 
 static int
-GLES_UpdateClipRect(SDL_Renderer * renderer)
+GLES_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
 {
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
-    if (SDL_CurrentContext != data->context) {
-        /* We'll update the clip rect after we rebind the context */
-        return 0;
-    }
-
-    if (renderer->clipping_enabled) {
-        const SDL_Rect *rect = &renderer->clip_rect;
-        data->glEnable(GL_SCISSOR_TEST);
-        if (renderer->target) {
-            data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
-        } else {
-            int w, h;
-
-            SDL_GL_GetDrawableSize(renderer->window, &w, &h);
-            data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
-        }
-    } else {
-        data->glDisable(GL_SCISSOR_TEST);
-    }
-    return 0;
-}
-
-static void
-GLES_SetColor(GLES_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
-{
-    Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
-
-    if (color != data->current.color) {
-        data->glColor4f((GLfloat) r * inv255f,
-                        (GLfloat) g * inv255f,
-                        (GLfloat) b * inv255f,
-                        (GLfloat) a * inv255f);
-        data->current.color = color;
-    }
-}
-
-static void
-GLES_SetBlendMode(GLES_RenderData * data, SDL_BlendMode blendMode)
-{
-    if (blendMode != data->current.blendMode) {
-        if (blendMode == SDL_BLENDMODE_NONE) {
-            data->glDisable(GL_BLEND);
-        } else {
-            data->glEnable(GL_BLEND);
-            if (data->GL_OES_blend_func_separate_supported) {
-                data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
-                                             GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)),
-                                             GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)),
-                                             GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode)));
-            } else {
-                data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)),
-                                  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)));
-            }
-            if (data->GL_OES_blend_equation_separate_supported) {
-                data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)),
-                                                 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode)));
-            } else if (data->GL_OES_blend_subtract_supported) {
-                data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)));
-            }
-        }
-        data->current.blendMode = blendMode;
-    }
-}
-
-static void
-GLES_SetTexCoords(GLES_RenderData * data, SDL_bool enabled)
-{
-    if (enabled != data->current.tex_coords) {
-        if (enabled) {
-            data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-        } else {
-            data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-        }
-        data->current.tex_coords = enabled;
-    }
-}
-
-static void
-GLES_SetDrawingState(SDL_Renderer * renderer)
-{
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
-    GLES_ActivateRenderer(renderer);
-
-    GLES_SetColor(data, (GLfloat) renderer->r,
-                        (GLfloat) renderer->g,
-                        (GLfloat) renderer->b,
-                        (GLfloat) renderer->a);
-
-    GLES_SetBlendMode(data, renderer->blendMode);
-
-    GLES_SetTexCoords(data, SDL_FALSE);
-}
-
-static int
-GLES_RenderClear(SDL_Renderer * renderer)
-{
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-
-    GLES_ActivateRenderer(renderer);
-
-    data->glClearColor((GLfloat) renderer->r * inv255f,
-                 (GLfloat) renderer->g * inv255f,
-                 (GLfloat) renderer->b * inv255f,
-                 (GLfloat) renderer->a * inv255f);
-    
-    if (renderer->clipping_enabled) {
-        data->glDisable(GL_SCISSOR_TEST);
-    }
-
-    data->glClear(GL_COLOR_BUFFER_BIT);
-
-    if (renderer->clipping_enabled) {
-        data->glEnable(GL_SCISSOR_TEST);
-    }
-
-    return 0;
-}
-
-static int
-GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
-                      int count)
-{
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-    GLfloat *vertices;
-    int idx;
-
-    GLES_SetDrawingState(renderer);
-
-    /* Emit the specified vertices as points */
-    vertices = SDL_stack_alloc(GLfloat, count * 2);
-    for (idx = 0; idx < count; ++idx) {
-        GLfloat x = points[idx].x + 0.5f;
-        GLfloat y = points[idx].y + 0.5f;
-
-        vertices[idx * 2] = x;
-        vertices[(idx * 2) + 1] = y;
-    }
-
-    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
-    data->glDrawArrays(GL_POINTS, 0, count);
-    SDL_stack_free(vertices);
-    return 0;
-}
-
-static int
-GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
-                     int count)
-{
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
-    GLfloat *vertices;
-    int idx;
-
-    GLES_SetDrawingState(renderer);
-
-    /* Emit a line strip including the specified vertices */
-    vertices = SDL_stack_alloc(GLfloat, count * 2);
-    for (idx = 0; idx < count; ++idx) {
-        GLfloat x = points[idx].x + 0.5f;
-        GLfloat y = points[idx].y + 0.5f;
-
-        vertices[idx * 2] = x;
-        vertices[(idx * 2) + 1] = y;
-    }
-
-    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
-    if (count > 2 &&
-        points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
-        /* GL_LINE_LOOP takes care of the final segment */
-        --count;
-        data->glDrawArrays(GL_LINE_LOOP, 0, count);
-    } else {
-        data->glDrawArrays(GL_LINE_STRIP, 0, count);
-        /* We need to close the endpoint of the line */
-        data->glDrawArrays(GL_POINTS, count-1, 1);
-    }
-    SDL_stack_free(vertices);
-
-    return 0;
-}
-
-static int
-GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
-                     int count)
-{
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
     int i;
 
-    GLES_SetDrawingState(renderer);
+    if (!verts) {
+        return -1;
+    }
 
-    for (i = 0; i < count; ++i) {
-        const SDL_FRect *rect = &rects[i];
-        GLfloat minx = rect->x;
-        GLfloat maxx = rect->x + rect->w;
-        GLfloat miny = rect->y;
-        GLfloat maxy = rect->y + rect->h;
-        GLfloat vertices[8];
-        vertices[0] = minx;
-        vertices[1] = miny;
-        vertices[2] = maxx;
-        vertices[3] = miny;
-        vertices[4] = minx;
-        vertices[5] = maxy;
-        vertices[6] = maxx;
-        vertices[7] = maxy;
-
-        data->glVertexPointer(2, GL_FLOAT, 0, vertices);
-        data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+    cmd->data.draw.count = count;
+    for (i = 0; i < count; i++) {
+        *(verts++) = 0.5f + points[i].x;
+        *(verts++) = 0.5f + points[i].y;
     }
 
     return 0;
 }
 
 static int
-GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
-                const SDL_Rect * srcrect, const SDL_FRect * dstrect)
+GLES_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
 {
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
+    int i;
+
+    if (!verts) {
+        return -1;
+    }
+
+    cmd->data.draw.count = count;
+
+    for (i = 0; i < count; i++) {
+        const SDL_FRect *rect = &rects[i];
+        const GLfloat minx = rect->x;
+        const GLfloat maxx = rect->x + rect->w;
+        const GLfloat miny = rect->y;
+        const GLfloat maxy = rect->y + rect->h;
+        *(verts++) = minx;
+        *(verts++) = miny;
+        *(verts++) = maxx;
+        *(verts++) = miny;
+        *(verts++) = minx;
+        *(verts++) = maxy;
+        *(verts++) = maxx;
+        *(verts++) = maxy;
+    }
+
+    return 0;
+}
+
+static int
+GLES_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
+                          const SDL_Rect * srcrect, const SDL_FRect * dstrect)
+{
     GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
     GLfloat minx, miny, maxx, maxy;
     GLfloat minu, maxu, minv, maxv;
-    GLfloat vertices[8];
-    GLfloat texCoords[8];
+    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
 
-    GLES_ActivateRenderer(renderer);
-
-    data->glEnable(GL_TEXTURE_2D);
-
-    data->glBindTexture(texturedata->type, texturedata->texture);
-
-    if (texture->modMode) {
-        GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
-    } else {
-        GLES_SetColor(data, 255, 255, 255, 255);
+    if (!verts) {
+        return -1;
     }
 
-    GLES_SetBlendMode(data, texture->blendMode);
-
-    GLES_SetTexCoords(data, SDL_TRUE);
+    cmd->data.draw.count = 1;
 
     minx = dstrect->x;
     miny = dstrect->y;
@@ -1027,126 +621,351 @@
     maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
     maxv *= texturedata->texh;
 
-    vertices[0] = minx;
-    vertices[1] = miny;
-    vertices[2] = maxx;
-    vertices[3] = miny;
-    vertices[4] = minx;
-    vertices[5] = maxy;
-    vertices[6] = maxx;
-    vertices[7] = maxy;
+    *(verts++) = minx;
+    *(verts++) = miny;
+    *(verts++) = maxx;
+    *(verts++) = miny;
+    *(verts++) = minx;
+    *(verts++) = maxy;
+    *(verts++) = maxx;
+    *(verts++) = maxy;
 
-    texCoords[0] = minu;
-    texCoords[1] = minv;
-    texCoords[2] = maxu;
-    texCoords[3] = minv;
-    texCoords[4] = minu;
-    texCoords[5] = maxv;
-    texCoords[6] = maxu;
-    texCoords[7] = maxv;
-
-    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
-    data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
-    data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
-    data->glDisable(GL_TEXTURE_2D);
+    *(verts++) = minu;
+    *(verts++) = minv;
+    *(verts++) = maxu;
+    *(verts++) = minv;
+    *(verts++) = minu;
+    *(verts++) = maxv;
+    *(verts++) = maxu;
+    *(verts++) = maxv;
 
     return 0;
 }
 
 static int
-GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
-                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
-                const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
+GLES_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
+                        const SDL_Rect * srcquad, const SDL_FRect * dstrect,
+                        const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
 {
-
-    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
     GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
     GLfloat minx, miny, maxx, maxy;
-    GLfloat minu, maxu, minv, maxv;
     GLfloat centerx, centery;
-    GLfloat vertices[8];
-    GLfloat texCoords[8];
+    GLfloat minu, maxu, minv, maxv;
+    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 19 * sizeof (GLfloat), 0, &cmd->data.draw.first);
 
-
-    GLES_ActivateRenderer(renderer);
-
-    data->glEnable(GL_TEXTURE_2D);
-
-    data->glBindTexture(texturedata->type, texturedata->texture);
-
-    if (texture->modMode) {
-        GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
-    } else {
-        GLES_SetColor(data, 255, 255, 255, 255);
+    if (!verts) {
+        return -1;
     }
-
-    GLES_SetBlendMode(data, texture->blendMode);
-
-    GLES_SetTexCoords(data, SDL_TRUE);
 
     centerx = center->x;
     centery = center->y;
 
-    /* Rotate and translate */
-    data->glPushMatrix();
-    data->glTranslatef(dstrect->x + centerx, dstrect->y + centery, 0.0f);
-    data->glRotatef((GLfloat)angle, 0.0f, 0.0f, 1.0f);
-
     if (flip & SDL_FLIP_HORIZONTAL) {
         minx =  dstrect->w - centerx;
         maxx = -centerx;
-    } else {
+    }
+    else {
         minx = -centerx;
-        maxx = dstrect->w - centerx;
+        maxx =  dstrect->w - centerx;
     }
 
     if (flip & SDL_FLIP_VERTICAL) {
-        miny = dstrect->h - centery;
+        miny =  dstrect->h - centery;
         maxy = -centery;
-    } else {
+    }
+    else {
         miny = -centery;
-        maxy = dstrect->h - centery;
+        maxy =  dstrect->h - centery;
     }
 
-    minu = (GLfloat) srcrect->x / texture->w;
+    minu = (GLfloat) srcquad->x / texture->w;
     minu *= texturedata->texw;
-    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
+    maxu = (GLfloat) (srcquad->x + srcquad->w) / texture->w;
     maxu *= texturedata->texw;
-    minv = (GLfloat) srcrect->y / texture->h;
+    minv = (GLfloat) srcquad->y / texture->h;
     minv *= texturedata->texh;
-    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
+    maxv = (GLfloat) (srcquad->y + srcquad->h) / texture->h;
     maxv *= texturedata->texh;
 
-    vertices[0] = minx;
-    vertices[1] = miny;
-    vertices[2] = maxx;
-    vertices[3] = miny;
-    vertices[4] = minx;
-    vertices[5] = maxy;
-    vertices[6] = maxx;
-    vertices[7] = maxy;
+    cmd->data.draw.count = 1;
 
-    texCoords[0] = minu;
-    texCoords[1] = minv;
-    texCoords[2] = maxu;
-    texCoords[3] = minv;
-    texCoords[4] = minu;
-    texCoords[5] = maxv;
-    texCoords[6] = maxu;
-    texCoords[7] = maxv;
-    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
-    data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
-    data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-    data->glPopMatrix();
-    data->glDisable(GL_TEXTURE_2D);
+    *(verts++) = minx;
+    *(verts++) = miny;
+    *(verts++) = maxx;
+    *(verts++) = miny;
+    *(verts++) = minx;
+    *(verts++) = maxy;
+    *(verts++) = maxx;
+    *(verts++) = maxy;
+
+    *(verts++) = minu;
+    *(verts++) = minv;
+    *(verts++) = maxu;
+    *(verts++) = minv;
+    *(verts++) = minu;
+    *(verts++) = maxv;
+    *(verts++) = maxu;
+    *(verts++) = maxv;
+
+    *(verts++) = (GLfloat) dstrect->x + centerx;
+    *(verts++) = (GLfloat) dstrect->y + centery;
+    *(verts++) = (GLfloat) angle;
+
+    return 0;
+}
+
+static void
+SetDrawState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
+{
+    const SDL_BlendMode blend = cmd->data.draw.blend;
+    const Uint8 r = cmd->data.draw.r;
+    const Uint8 g = cmd->data.draw.g;
+    const Uint8 b = cmd->data.draw.b;
+    const Uint8 a = cmd->data.draw.a;
+    const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
+
+    if (color != data->drawstate.color) {
+        const GLfloat fr = ((GLfloat) r) * inv255f;
+        const GLfloat fg = ((GLfloat) g) * inv255f;
+        const GLfloat fb = ((GLfloat) b) * inv255f;
+        const GLfloat fa = ((GLfloat) a) * inv255f;
+        data->glColor4f(fr, fg, fb, fa);
+        data->drawstate.color = color;
+    }
+
+    if (data->drawstate.viewport_dirty) {
+        const SDL_Rect *viewport = &data->drawstate.viewport;
+        const SDL_bool istarget = (data->drawstate.target != NULL);
+        data->glMatrixMode(GL_PROJECTION);
+        data->glLoadIdentity();
+        data->glViewport(viewport->x,
+                         istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
+                         viewport->w, viewport->h);
+        if (viewport->w && viewport->h) {
+            data->glOrthof((GLfloat) 0, (GLfloat) viewport->w,
+                           (GLfloat) (istarget ? 0 : viewport->h),
+                           (GLfloat) (istarget ? viewport->h : 0),
+                           0.0, 1.0);
+        }
+        data->glMatrixMode(GL_MODELVIEW);
+        data->drawstate.viewport_dirty = SDL_FALSE;
+    }
+
+    if (data->drawstate.cliprect_enabled_dirty) {
+        if (data->drawstate.cliprect_enabled) {
+            data->glEnable(GL_SCISSOR_TEST);
+        } else {
+            data->glDisable(GL_SCISSOR_TEST);
+        }
+        data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
+    }
+
+    if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
+        const SDL_Rect *viewport = &data->drawstate.viewport;
+        const SDL_Rect *rect = &data->drawstate.cliprect;
+        const SDL_bool istarget = (data->drawstate.target != NULL);
+        data->glScissor(viewport->x + rect->x,
+                        istarget ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
+                        rect->w, rect->h);
+        data->drawstate.cliprect_dirty = SDL_FALSE;
+    }
+
+    if (blend != data->drawstate.blend) {
+        if (blend == SDL_BLENDMODE_NONE) {
+            data->glDisable(GL_BLEND);
+        } else {
+            data->glEnable(GL_BLEND);
+            if (data->GL_OES_blend_func_separate_supported) {
+                data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
+                                             GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
+                                             GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
+                                             GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
+            } else {
+                data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
+                                  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
+            }
+            if (data->GL_OES_blend_equation_separate_supported) {
+                data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
+                                                 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
+            } else if (data->GL_OES_blend_subtract_supported) {
+                data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
+            }
+        }
+        data->drawstate.blend = blend;
+    }
+
+    if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
+        if (cmd->data.draw.texture == NULL) {
+            data->glDisable(GL_TEXTURE_2D);
+            data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+            data->drawstate.texturing = SDL_FALSE;
+        } else {
+            data->glEnable(GL_TEXTURE_2D);
+            data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            data->drawstate.texturing = SDL_TRUE;
+        }
+    }
+}
+
+static void
+SetCopyState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
+{
+    SDL_Texture *texture = cmd->data.draw.texture;
+    SetDrawState(data, cmd);
+
+    if (texture != data->drawstate.texture) {
+        GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
+        data->glBindTexture(GL_TEXTURE_2D, texturedata->texture);
+        data->drawstate.texture = texture;
+    }
+}
+
+static int
+GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
+{
+    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
+    size_t i;
+
+    if (GLES_ActivateRenderer(renderer) < 0) {
+        return -1;
+    }
+
+    data->drawstate.target = renderer->target;
+
+    if (!renderer->target) {
+        SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
+    }
+
+    while (cmd) {
+        switch (cmd->command) {
+            case SDL_RENDERCMD_SETDRAWCOLOR: {
+                break;  /* not used in this render backend. */
+            }
+
+            case SDL_RENDERCMD_SETVIEWPORT: {
+                SDL_Rect *viewport = &data->drawstate.viewport;
+                if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
+                    SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
+                    data->drawstate.viewport_dirty = SDL_TRUE;
+                }
+                break;
+            }
+
+            case SDL_RENDERCMD_SETCLIPRECT: {
+                const SDL_Rect *rect = &cmd->data.cliprect.rect;
+                if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
+                    data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
+                    data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
+                }
+                if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
+                    SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
+                    data->drawstate.cliprect_dirty = SDL_TRUE;
+                }
+                break;
+            }
+
+            case SDL_RENDERCMD_CLEAR: {
+                const Uint8 r = cmd->data.color.r;
+                const Uint8 g = cmd->data.color.g;
+                const Uint8 b = cmd->data.color.b;
+                const Uint8 a = cmd->data.color.a;
+                const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
+                if (color != data->drawstate.clear_color) {
+                    const GLfloat fr = ((GLfloat) r) * inv255f;
+                    const GLfloat fg = ((GLfloat) g) * inv255f;
+                    const GLfloat fb = ((GLfloat) b) * inv255f;
+                    const GLfloat fa = ((GLfloat) a) * inv255f;
+                    data->glClearColor(fr, fg, fb, fa);
+                    data->drawstate.clear_color = color;
+                }
+
+                if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
+                    data->glDisable(GL_SCISSOR_TEST);
+                    data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
+                }
+
+                data->glClear(GL_COLOR_BUFFER_BIT);
+
+                break;
+            }
+
+            case SDL_RENDERCMD_DRAW_POINTS: {
+                const size_t count = cmd->data.draw.count;
+                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+                SetDrawState(data, cmd);
+                data->glVertexPointer(2, GL_FLOAT, 0, verts);
+                data->glDrawArrays(GL_POINTS, 0, (GLsizei) count);
+                break;
+            }
+
+            case SDL_RENDERCMD_DRAW_LINES: {
+                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+                const size_t count = cmd->data.draw.count;
+                SetDrawState(data, cmd);
+                data->glVertexPointer(2, GL_FLOAT, 0, verts);
+                if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
+                    /* GL_LINE_LOOP takes care of the final segment */
+                    data->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) (count - 1));
+                } else {
+                    data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
+                    /* We need to close the endpoint of the line */
+                    data->glDrawArrays(GL_POINTS, (GLsizei) (count - 1), 1);
+                }
+                break;
+            }
+
+            case SDL_RENDERCMD_FILL_RECTS: {
+                const size_t count = cmd->data.draw.count;
+                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+                GLsizei offset = 0;
+                SetDrawState(data, cmd);
+                data->glVertexPointer(2, GL_FLOAT, 0, verts);
+                for (i = 0; i < count; ++i, offset += 4) {
+                    data->glDrawArrays(GL_TRIANGLE_STRIP, offset, 4);
+                }
+                break;
+            }
+
+            case SDL_RENDERCMD_COPY: {
+                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+                SetCopyState(data, cmd);
+                data->glVertexPointer(2, GL_FLOAT, 0, verts);
+                data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
+                data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+                break;
+            }
+
+            case SDL_RENDERCMD_COPY_EX: {
+                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
+                const GLfloat translatex = verts[16];
+                const GLfloat translatey = verts[17];
+                const GLfloat angle = verts[18];
+                SetCopyState(data, cmd);
+                data->glVertexPointer(2, GL_FLOAT, 0, verts);
+                data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
+
+                /* Translate to flip, rotate, translate to position */
+                data->glPushMatrix();
+                data->glTranslatef(translatex, translatey, 0.0f);
+                data->glRotatef(angle, 0.0, 0.0, 1.0);
+                data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+                data->glPopMatrix();
+                break;
+            }
+
+            case SDL_RENDERCMD_NO_OP:
+                break;
+        }
+
+        cmd = cmd->next;
+    }
 
     return 0;
 }
 
 static int
 GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
-                    Uint32 pixel_format, void * pixels, int pitch)
+                      Uint32 pixel_format, void * pixels, int pitch)
 {
     GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
     Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
@@ -1173,10 +992,11 @@
 
     /* Flip the rows to be top-down if necessary */
     if (!renderer->target) {
+        SDL_bool isstack;
         length = rect->w * SDL_BYTESPERPIXEL(temp_format);
         src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
         dst = (Uint8*)temp_pixels;
-        tmp = SDL_stack_alloc(Uint8, length);
+        tmp = SDL_small_alloc(Uint8, length, &isstack);
         rows = rect->h / 2;
         while (rows--) {
             SDL_memcpy(tmp, dst, length);
@@ -1185,7 +1005,7 @@
             dst += temp_pitch;
             src -= temp_pitch;
         }
-        SDL_stack_free(tmp);
+        SDL_small_free(tmp, isstack);
     }
 
     status = SDL_ConvertPixels(rect->w, rect->h,
@@ -1212,6 +1032,13 @@
     GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
 
     GLES_ActivateRenderer(renderer);
+
+    if (renderdata->drawstate.texture == texture) {
+        renderdata->drawstate.texture = NULL;
+    }
+    if (renderdata->drawstate.target == texture) {
+        renderdata->drawstate.target = NULL;
+    }
 
     if (!data) {
         return;
@@ -1253,6 +1080,9 @@
     data->glEnable(GL_TEXTURE_2D);
     data->glBindTexture(texturedata->type, texturedata->texture);
 
+    data->drawstate.texture = texture;
+    data->drawstate.texturing = SDL_TRUE;
+
     if (texw) {
         *texw = (float)texturedata->texw;
     }
@@ -1270,9 +1100,174 @@
     GLES_ActivateRenderer(renderer);
     data->glDisable(texturedata->type);
 
+    data->drawstate.texture = NULL;
+    data->drawstate.texturing = SDL_FALSE;
+
     return 0;
 }
 
+static SDL_Renderer *
+GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+    SDL_Renderer *renderer;
+    GLES_RenderData *data;
+    GLint value;
+    Uint32 window_flags;
+    int profile_mask = 0, major = 0, minor = 0;
+    SDL_bool changed_window = SDL_FALSE;
+
+    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
+    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
+    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
+
+    window_flags = SDL_GetWindowFlags(window);
+    if (!(window_flags & SDL_WINDOW_OPENGL) ||
+        profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
+
+        changed_window = SDL_TRUE;
+        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
+        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
+        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
+
+        if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
+            goto error;
+        }
+    }
+
+    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+    if (!renderer) {
+        SDL_OutOfMemory();
+        goto error;
+    }
+
+    data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
+    if (!data) {
+        GLES_DestroyRenderer(renderer);
+        SDL_OutOfMemory();
+        goto error;
+    }
+
+    renderer->WindowEvent = GLES_WindowEvent;
+    renderer->GetOutputSize = GLES_GetOutputSize;
+    renderer->SupportsBlendMode = GLES_SupportsBlendMode;
+    renderer->CreateTexture = GLES_CreateTexture;
+    renderer->UpdateTexture = GLES_UpdateTexture;
+    renderer->LockTexture = GLES_LockTexture;
+    renderer->UnlockTexture = GLES_UnlockTexture;
+    renderer->SetTextureScaleMode = GLES_SetTextureScaleMode;
+    renderer->SetRenderTarget = GLES_SetRenderTarget;
+    renderer->QueueSetViewport = GLES_QueueSetViewport;
+    renderer->QueueSetDrawColor = GLES_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
+    renderer->QueueDrawPoints = GLES_QueueDrawPoints;
+    renderer->QueueDrawLines = GLES_QueueDrawPoints;  /* lines and points queue vertices the same way. */
+    renderer->QueueFillRects = GLES_QueueFillRects;
+    renderer->QueueCopy = GLES_QueueCopy;
+    renderer->QueueCopyEx = GLES_QueueCopyEx;
+    renderer->RunCommandQueue = GLES_RunCommandQueue;
+    renderer->RenderReadPixels = GLES_RenderReadPixels;
+    renderer->RenderPresent = GLES_RenderPresent;
+    renderer->DestroyTexture = GLES_DestroyTexture;
+    renderer->DestroyRenderer = GLES_DestroyRenderer;
+    renderer->GL_BindTexture = GLES_BindTexture;
+    renderer->GL_UnbindTexture = GLES_UnbindTexture;
+    renderer->info = GLES_RenderDriver.info;
+    renderer->info.flags = SDL_RENDERER_ACCELERATED;
+    renderer->driverdata = data;
+    renderer->window = window;
+
+    data->context = SDL_GL_CreateContext(window);
+    if (!data->context) {
+        GLES_DestroyRenderer(renderer);
+        goto error;
+    }
+    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
+        GLES_DestroyRenderer(renderer);
+        goto error;
+    }
+
+    if (GLES_LoadFunctions(data) < 0) {
+        GLES_DestroyRenderer(renderer);
+        goto error;
+    }
+
+    if (flags & SDL_RENDERER_PRESENTVSYNC) {
+        SDL_GL_SetSwapInterval(1);
+    } else {
+        SDL_GL_SetSwapInterval(0);
+    }
+    if (SDL_GL_GetSwapInterval() > 0) {
+        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
+    }
+
+    value = 0;
+    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+    renderer->info.max_texture_width = value;
+    value = 0;
+    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
+    renderer->info.max_texture_height = value;
+
+    /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
+    if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
+        data->GL_OES_framebuffer_object_supported = SDL_TRUE;
+        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
+
+        value = 0;
+        data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
+        data->window_framebuffer = (GLuint)value;
+    }
+    data->framebuffers = NULL;
+
+    if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
+        data->GL_OES_blend_func_separate_supported = SDL_TRUE;
+    }
+    if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
+        data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
+    }
+    if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
+        data->GL_OES_blend_subtract_supported = SDL_TRUE;
+    }
+
+    /* Set up parameters for rendering */
+    data->glDisable(GL_DEPTH_TEST);
+    data->glDisable(GL_CULL_FACE);
+
+    data->glMatrixMode(GL_MODELVIEW);
+    data->glLoadIdentity();
+
+    data->glEnableClientState(GL_VERTEX_ARRAY);
+    data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+    data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+
+    data->drawstate.blend = SDL_BLENDMODE_INVALID;
+    data->drawstate.color = 0xFFFFFFFF;
+    data->drawstate.clear_color = 0xFFFFFFFF;
+
+    return renderer;
+
+error:
+    if (changed_window) {
+        /* Uh oh, better try to put it back... */
+        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
+        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
+        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
+        SDL_RecreateWindow(window, window_flags);
+    }
+    return NULL;
+}
+
+SDL_RenderDriver GLES_RenderDriver = {
+    GLES_CreateRenderer,
+    {
+     "opengles",
+     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
+     1,
+     {SDL_PIXELFORMAT_ABGR8888},
+     0,
+     0
+    }
+};
+
 #endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
 
 /* vi: set ts=4 sw=4 expandtab: */

--
Gitblit v1.9.3