render: moved opengles2 over to new interface. SDL-ryan-batching-renderer
authorRyan C. Gordon <icculus@icculus.org>
Fri, 28 Sep 2018 19:47:44 -0400
branchSDL-ryan-batching-renderer
changeset 122622a34f0026a8d
parent 12261 4e77fde5bbc7
child 12263 b16e5f26d6bd
render: moved opengles2 over to new interface.
src/render/SDL_render.c
src/render/opengles2/SDL_render_gles2.c
     1.1 --- a/src/render/SDL_render.c	Wed Sep 26 20:10:32 2018 -0400
     1.2 +++ b/src/render/SDL_render.c	Fri Sep 28 19:47:44 2018 -0400
     1.3 @@ -497,6 +497,7 @@
     1.4  static SDL_RenderCommand *
     1.5  PrepQueueCmdDrawSolid(SDL_Renderer *renderer, const SDL_RenderCommandType cmdtype)
     1.6  {
     1.7 +    /* !!! FIXME: drop this draw if viewport w or h is zero. */
     1.8      SDL_RenderCommand *cmd = NULL;
     1.9      if (PrepQueueCmdDraw(renderer, renderer->r, renderer->g, renderer->b, renderer->a) == 0) {
    1.10          cmd = AllocateRenderCommand(renderer);
    1.11 @@ -560,6 +561,7 @@
    1.12  static SDL_RenderCommand *
    1.13  PrepQueueCmdDrawTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_RenderCommandType cmdtype)
    1.14  {
    1.15 +    /* !!! FIXME: drop this draw if viewport w or h is zero. */
    1.16      SDL_RenderCommand *cmd = NULL;
    1.17      if (PrepQueueCmdDraw(renderer, texture->r, texture->g, texture->b, texture->a) == 0) {
    1.18          cmd = AllocateRenderCommand(renderer);
     2.1 --- a/src/render/opengles2/SDL_render_gles2.c	Wed Sep 26 20:10:32 2018 -0400
     2.2 +++ b/src/render/opengles2/SDL_render_gles2.c	Fri Sep 28 19:47:44 2018 -0400
     2.3 @@ -39,29 +39,6 @@
     2.4  extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
     2.5  
     2.6  /*************************************************************************************************
     2.7 - * Bootstrap data                                                                                *
     2.8 - *************************************************************************************************/
     2.9 -
    2.10 -static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags);
    2.11 -
    2.12 -SDL_RenderDriver GLES2_RenderDriver = {
    2.13 -    GLES2_CreateRenderer,
    2.14 -    {
    2.15 -        "opengles2",
    2.16 -        (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
    2.17 -        4,
    2.18 -        {
    2.19 -        SDL_PIXELFORMAT_ARGB8888,
    2.20 -        SDL_PIXELFORMAT_ABGR8888,
    2.21 -        SDL_PIXELFORMAT_RGB888,
    2.22 -        SDL_PIXELFORMAT_BGR888
    2.23 -        },
    2.24 -        0,
    2.25 -        0
    2.26 -    }
    2.27 -};
    2.28 -
    2.29 -/*************************************************************************************************
    2.30   * Context structures                                                                            *
    2.31   *************************************************************************************************/
    2.32  
    2.33 @@ -88,7 +65,6 @@
    2.34      GLenum texture_v;
    2.35      GLenum texture_u;
    2.36      GLES2_FBOList *fbo;
    2.37 -    Uint32 last_cmd_generation; /* last command queue generation this texture was in. */
    2.38  } GLES2_TextureData;
    2.39  
    2.40  typedef struct GLES2_ShaderCacheEntry
    2.41 @@ -97,7 +73,6 @@
    2.42      GLES2_ShaderType type;
    2.43      const GLES2_ShaderInstance *instance;
    2.44      int references;
    2.45 -    Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
    2.46      struct GLES2_ShaderCacheEntry *prev;
    2.47      struct GLES2_ShaderCacheEntry *next;
    2.48  } GLES2_ShaderCacheEntry;
    2.49 @@ -114,8 +89,7 @@
    2.50      GLES2_ShaderCacheEntry *vertex_shader;
    2.51      GLES2_ShaderCacheEntry *fragment_shader;
    2.52      GLuint uniform_locations[16];
    2.53 -    Uint8 color_r, color_g, color_b, color_a;
    2.54 -    Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
    2.55 +    Uint32 color;
    2.56      GLfloat projection[4][4];
    2.57      struct GLES2_ProgramCacheEntry *prev;
    2.58      struct GLES2_ProgramCacheEntry *next;
    2.59 @@ -159,47 +133,22 @@
    2.60      GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES
    2.61  } GLES2_ImageSource;
    2.62  
    2.63 -typedef enum
    2.64 +typedef struct
    2.65  {
    2.66 -    GLES2_RENDERCMD_VIEWPORT,
    2.67 -    GLES2_RENDERCMD_CLIPRECT,
    2.68 -    GLES2_RENDERCMD_CLEAR,
    2.69 -    GLES2_RENDERCMD_ATTR,
    2.70 -    GLES2_RENDERCMD_DRAW
    2.71 -} GLES2_RenderCommandType;
    2.72 +    SDL_Rect viewport;
    2.73 +    SDL_Texture *texture;
    2.74 +    SDL_BlendMode blend;
    2.75 +    SDL_bool cliprect_enabled;
    2.76 +    SDL_Rect cliprect;
    2.77 +    SDL_bool texturing;
    2.78 +    SDL_bool is_copy_ex;
    2.79 +    Uint32 color;
    2.80 +    Uint32 clear_color;
    2.81 +    GLES2_ProgramCacheEntry *program;
    2.82 +    GLfloat projection[4][4];
    2.83 +} GLES2_DrawStateCache;
    2.84  
    2.85 -typedef struct GLES2_RenderCommand
    2.86 -{
    2.87 -    GLES2_RenderCommandType cmd;
    2.88 -    union {
    2.89 -        SDL_Rect viewport;
    2.90 -        struct {
    2.91 -            SDL_bool enabled;
    2.92 -            SDL_Rect rect;
    2.93 -        } cliprect;
    2.94 -        struct {
    2.95 -            Uint8 r, g, b, a;
    2.96 -        } clear;
    2.97 -        struct {
    2.98 -            GLES2_Attribute attr;
    2.99 -            GLsizei offset;
   2.100 -            GLsizei count;
   2.101 -        } attr;
   2.102 -        struct {
   2.103 -            GLenum mode;
   2.104 -            GLint first;
   2.105 -            GLsizei count;
   2.106 -            Uint8 attrs;
   2.107 -            Uint8 r, g, b, a;
   2.108 -            SDL_BlendMode blend;
   2.109 -            GLES2_ImageSource imgsrc;
   2.110 -            SDL_Texture *texture;
   2.111 -        } draw;
   2.112 -    } data;
   2.113 -    struct GLES2_RenderCommand *next;
   2.114 -} GLES2_RenderCommand;
   2.115 -
   2.116 -typedef struct GLES2_DriverContext
   2.117 +typedef struct GLES2_RenderData
   2.118  {
   2.119      SDL_GLContext *context;
   2.120  
   2.121 @@ -215,65 +164,18 @@
   2.122      GLenum *shader_formats;
   2.123      GLES2_ShaderCache shader_cache;
   2.124      GLES2_ProgramCache program_cache;
   2.125 -    GLES2_ProgramCacheEntry *current_program;
   2.126      Uint8 clear_r, clear_g, clear_b, clear_a;
   2.127  
   2.128 -    GLuint vertex_buffers[4];
   2.129 -    GLsizeiptr vertex_buffer_size[4];
   2.130 +    GLuint vertex_buffers[8];
   2.131 +    GLsizeiptr vertex_buffer_size[8];
   2.132      int current_vertex_buffer;
   2.133 -    GLES2_RenderCommand *render_commands;
   2.134 -    GLES2_RenderCommand *render_commands_tail;
   2.135 -    GLES2_RenderCommand *render_commands_pool;
   2.136 -    int current_vertex_data;
   2.137 -    Uint32 command_generation;
   2.138 -    GLfloat *vertex_data;
   2.139 -    GLsizeiptr vertex_data_allocation;
   2.140 -} GLES2_DriverContext;
   2.141 +    GLES2_DrawStateCache drawstate;
   2.142 +} GLES2_RenderData;
   2.143  
   2.144  #define GLES2_MAX_CACHED_PROGRAMS 8
   2.145  
   2.146  static const float inv255f = 1.0f / 255.0f;
   2.147  
   2.148 -static GLES2_RenderCommand *
   2.149 -GLES2_AllocateRenderCommand(SDL_Renderer *renderer)
   2.150 -{
   2.151 -    GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
   2.152 -    GLES2_RenderCommand *retval = NULL;
   2.153 -
   2.154 -    /* !!! FIXME: are there threading limitations in SDL's render API? */
   2.155 -    retval = data->render_commands_pool;
   2.156 -    if (retval != NULL) {
   2.157 -        data->render_commands_pool = retval->next;
   2.158 -        retval->next = NULL;
   2.159 -    } else {
   2.160 -        retval = SDL_calloc(1, sizeof (*retval));
   2.161 -        if (!retval) {
   2.162 -            SDL_OutOfMemory();
   2.163 -            return NULL;
   2.164 -        }
   2.165 -    }
   2.166 -
   2.167 -    SDL_assert((data->render_commands == NULL) == (data->render_commands_tail == NULL));
   2.168 -    if (data->render_commands_tail != NULL) {
   2.169 -        data->render_commands_tail->next = retval;
   2.170 -    } else {
   2.171 -        data->render_commands = retval;
   2.172 -    }
   2.173 -    data->render_commands_tail = retval;
   2.174 -
   2.175 -    return retval;
   2.176 -}
   2.177 -
   2.178 -static SDL_bool
   2.179 -CompareColors(const Uint8 r1, const Uint8 g1, const Uint8 b1, const Uint8 a1,
   2.180 -              const Uint8 r2, const Uint8 g2, const Uint8 b2, const Uint8 a2)
   2.181 -{
   2.182 -    Uint32 Pixel1, Pixel2;
   2.183 -    RGBA8888_FROM_RGBA(Pixel1, r1, g1, b1, a1);
   2.184 -    RGBA8888_FROM_RGBA(Pixel2, r2, g2, b2, a2);
   2.185 -    return (Pixel1 == Pixel2);
   2.186 -}
   2.187 -
   2.188  
   2.189  SDL_FORCE_INLINE const char*
   2.190  GL_TranslateError (GLenum error)
   2.191 @@ -294,7 +196,7 @@
   2.192  SDL_FORCE_INLINE void
   2.193  GL_ClearErrors(SDL_Renderer *renderer)
   2.194  {
   2.195 -    GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
   2.196 +    GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
   2.197  
   2.198      if (!data->debug_enabled) {
   2.199          return;
   2.200 @@ -307,7 +209,7 @@
   2.201  SDL_FORCE_INLINE int
   2.202  GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
   2.203  {
   2.204 -    GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
   2.205 +    GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
   2.206      int ret = 0;
   2.207  
   2.208      if (!data->debug_enabled) {
   2.209 @@ -340,16 +242,7 @@
   2.210   * Renderer state APIs                                                                           *
   2.211   *************************************************************************************************/
   2.212  
   2.213 -static int GLES2_ActivateRenderer(SDL_Renderer *renderer);
   2.214 -static void GLES2_WindowEvent(SDL_Renderer * renderer,
   2.215 -                              const SDL_WindowEvent *event);
   2.216 -static int GLES2_UpdateViewport(SDL_Renderer * renderer);
   2.217 -static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
   2.218 -
   2.219 -
   2.220 -static SDL_GLContext SDL_CurrentContext = NULL;
   2.221 -
   2.222 -static int GLES2_LoadFunctions(GLES2_DriverContext * data)
   2.223 +static int GLES2_LoadFunctions(GLES2_RenderData * data)
   2.224  {
   2.225  #if SDL_VIDEO_DRIVER_UIKIT
   2.226  #define __SDL_NOGETPROCADDR__
   2.227 @@ -377,7 +270,7 @@
   2.228  }
   2.229  
   2.230  static GLES2_FBOList *
   2.231 -GLES2_GetFBO(GLES2_DriverContext *data, Uint32 w, Uint32 h)
   2.232 +GLES2_GetFBO(GLES2_RenderData *data, Uint32 w, Uint32 h)
   2.233  {
   2.234     GLES2_FBOList *result = data->framebuffers;
   2.235     while ((result) && ((result->w != w) || (result->h != h)) ) {
   2.236 @@ -397,18 +290,15 @@
   2.237  static int
   2.238  GLES2_ActivateRenderer(SDL_Renderer * renderer)
   2.239  {
   2.240 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   2.241 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   2.242  
   2.243 -    if (SDL_CurrentContext != data->context) {
   2.244 +    if (SDL_GL_GetCurrentContext() != data->context) {
   2.245          /* Null out the current program to ensure we set it again */
   2.246 -        data->current_program = NULL;
   2.247 +        data->drawstate.program = NULL;
   2.248  
   2.249          if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
   2.250              return -1;
   2.251          }
   2.252 -        SDL_CurrentContext = data->context;
   2.253 -
   2.254 -        GLES2_UpdateViewport(renderer);
   2.255      }
   2.256  
   2.257      GL_ClearErrors(renderer);
   2.258 @@ -419,14 +309,7 @@
   2.259  static void
   2.260  GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
   2.261  {
   2.262 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   2.263 -
   2.264 -    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
   2.265 -        event->event == SDL_WINDOWEVENT_SHOWN ||
   2.266 -        event->event == SDL_WINDOWEVENT_HIDDEN) {
   2.267 -        /* Rebind the context to the window area */
   2.268 -        SDL_CurrentContext = NULL;
   2.269 -    }
   2.270 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   2.271  
   2.272      if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
   2.273          /* According to Apple documentation, we need to finish drawing NOW! */
   2.274 @@ -504,805 +387,31 @@
   2.275      return SDL_TRUE;
   2.276  }
   2.277  
   2.278 -static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, int w, int h);
   2.279  
   2.280 -static int
   2.281 -GLES2_FlushCommands(SDL_Renderer *renderer)
   2.282 +static void
   2.283 +GLES2_EvictShader(GLES2_RenderData *data, GLES2_ShaderCacheEntry *entry)
   2.284  {
   2.285 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   2.286 -    const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
   2.287 -    const int vboidx = data->current_vertex_buffer;
   2.288 -    const GLuint vbo = data->vertex_buffers[vboidx];
   2.289 -    const GLsizeiptr dataSizeInBytes = data->current_vertex_data * sizeof (float);
   2.290 -    Uint8 enabled_attrs = (1 << GLES2_ATTRIBUTE_POSITION);
   2.291 -    GLES2_RenderCommand *cmd;
   2.292 -    GLES2_RenderCommand *next;
   2.293 -    SDL_Rect viewport;
   2.294 -    SDL_Texture *bound_texture = NULL;
   2.295 -    SDL_BlendMode blend = SDL_BLENDMODE_INVALID;
   2.296 -    Uint8 clear_r, clear_g, clear_b, clear_a;
   2.297 -    int drawablew = 0, drawableh = 0;
   2.298 -    GLfloat projection[4][4];
   2.299 -    SDL_bool cliprect_enabled = SDL_FALSE;
   2.300 -    SDL_Rect cliprect;
   2.301 +    /* Unlink the shader from the cache */
   2.302 +    if (entry->next) {
   2.303 +        entry->next->prev = entry->prev;
   2.304 +    }
   2.305 +    if (entry->prev) {
   2.306 +        entry->prev->next = entry->next;
   2.307 +    }
   2.308 +    if (data->shader_cache.head == entry) {
   2.309 +        data->shader_cache.head = entry->next;
   2.310 +    }
   2.311 +    --data->shader_cache.count;
   2.312  
   2.313 -    GLES2_ActivateRenderer(renderer);
   2.314 -
   2.315 -    if (data->render_commands == NULL) {  /* nothing to do! */
   2.316 -        SDL_assert(data->current_vertex_data == 0);
   2.317 -        return 0;
   2.318 -    }
   2.319 -
   2.320 -    /* cycle through a few VBOs so the GL has some time with the data before we replace it. */
   2.321 -    data->current_vertex_buffer++;
   2.322 -    if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
   2.323 -        data->current_vertex_buffer = 0;
   2.324 -    }
   2.325 -    data->current_vertex_data = 0;  /* start next VBO at start. */
   2.326 -    cmd = data->render_commands;
   2.327 -    data->render_commands = NULL;
   2.328 -    data->render_commands_tail = NULL;
   2.329 -
   2.330 -    SDL_zero(projection);
   2.331 -    projection[3][0] = -1.0f;
   2.332 -    projection[3][1] = renderer->target ? -1.0f : 1.0f;
   2.333 -    projection[3][3] = 1.0f;
   2.334 -
   2.335 -    if (!renderer->target) {
   2.336 -        SDL_GL_GetDrawableSize(renderer->window, &drawablew, &drawableh);
   2.337 -    }
   2.338 -
   2.339 -    /* upload the new VBO data for this set of commands. */
   2.340 -    data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
   2.341 -    if (data->vertex_buffer_size[vboidx] < dataSizeInBytes) {
   2.342 -        data->glBufferData(GL_ARRAY_BUFFER, dataSizeInBytes, data->vertex_data, GL_STREAM_DRAW);
   2.343 -        data->vertex_buffer_size[vboidx] = dataSizeInBytes;
   2.344 -    } else {
   2.345 -        data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, data->vertex_data);
   2.346 -    }
   2.347 -
   2.348 -    data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   2.349 -    data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
   2.350 -    data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
   2.351 -    data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
   2.352 -
   2.353 -    clear_r = renderer->r;
   2.354 -    clear_g = renderer->g;
   2.355 -    clear_b = renderer->b;
   2.356 -    clear_a = renderer->a;
   2.357 -    data->glClearColor(clear_r * inv255f, clear_g * inv255f, clear_b * inv255f, clear_a * inv255f);
   2.358 -
   2.359 -    SDL_memcpy(&viewport, &renderer->viewport, sizeof (viewport));
   2.360 -    data->glViewport(viewport.x,
   2.361 -            (renderer->target) ? viewport.y : (drawableh - viewport.y - viewport.h),
   2.362 -            viewport.w, viewport.h);
   2.363 -
   2.364 -    SDL_memcpy(&cliprect, &renderer->clip_rect, sizeof (cliprect));
   2.365 -    cliprect_enabled = renderer->clipping_enabled;
   2.366 -    if (cliprect_enabled) {
   2.367 -        data->glEnable(GL_SCISSOR_TEST);
   2.368 -    } else {
   2.369 -        data->glDisable(GL_SCISSOR_TEST);
   2.370 -    }
   2.371 -    if (renderer->target) {
   2.372 -        data->glScissor(viewport.x + cliprect.x, viewport.y + cliprect.y, cliprect.w, cliprect.h);
   2.373 -    } else {
   2.374 -        data->glScissor(viewport.x + cliprect.x, drawableh - viewport.y - cliprect.y - cliprect.h, cliprect.w, cliprect.h);
   2.375 -    }
   2.376 -
   2.377 -    while (cmd != NULL) {
   2.378 -        switch (cmd->cmd) {
   2.379 -            case GLES2_RENDERCMD_VIEWPORT:
   2.380 -                if (SDL_memcmp(&cmd->data.viewport, &viewport, sizeof (SDL_Rect)) != 0) {
   2.381 -                    SDL_memcpy(&viewport, &cmd->data.viewport, sizeof (SDL_Rect));
   2.382 -                    data->glViewport(viewport.x,
   2.383 -                        (renderer->target) ? viewport.y : (drawableh - viewport.y - viewport.h),
   2.384 -                        viewport.w, viewport.h);
   2.385 -                }
   2.386 -                break;
   2.387 -
   2.388 -            case GLES2_RENDERCMD_CLIPRECT: {
   2.389 -                const SDL_Rect *rect = &cmd->data.cliprect.rect;
   2.390 -                const SDL_bool changed = (SDL_memcmp(&cliprect, rect, sizeof (SDL_Rect)) != 0);
   2.391 -                if (cliprect_enabled != cmd->data.cliprect.enabled) {
   2.392 -                    cliprect_enabled = cmd->data.cliprect.enabled;
   2.393 -                    if (cliprect_enabled) {
   2.394 -                        data->glEnable(GL_SCISSOR_TEST);
   2.395 -                    } else {
   2.396 -                        data->glDisable(GL_SCISSOR_TEST);
   2.397 -                    }
   2.398 -                }
   2.399 -
   2.400 -                if (cliprect_enabled && changed) {
   2.401 -                    SDL_memcpy(&cliprect, rect, sizeof (SDL_Rect));
   2.402 -                    if (renderer->target) {
   2.403 -                        data->glScissor(viewport.x + rect->x, viewport.y + rect->y, rect->w, rect->h);
   2.404 -                    } else {
   2.405 -                        data->glScissor(viewport.x + rect->x, drawableh - viewport.y - rect->y - rect->h, rect->w, rect->h);
   2.406 -                    }
   2.407 -                }
   2.408 -                break;
   2.409 -            }
   2.410 -
   2.411 -            case GLES2_RENDERCMD_CLEAR:
   2.412 -                if (!CompareColors(clear_r, clear_g, clear_b, clear_a, cmd->data.clear.r, cmd->data.clear.g, cmd->data.clear.b, cmd->data.clear.a)) {
   2.413 -                    GLfloat r, g, b, a;
   2.414 -
   2.415 -                    clear_r = cmd->data.clear.r;
   2.416 -                    clear_g = cmd->data.clear.g;
   2.417 -                    clear_b = cmd->data.clear.b;
   2.418 -                    clear_a = cmd->data.clear.a;
   2.419 -
   2.420 -                    r = ((GLfloat) (colorswap ? clear_b : clear_r)) * inv255f;
   2.421 -                    g = ((GLfloat) clear_g) * inv255f;
   2.422 -                    b = ((GLfloat) (colorswap ? clear_r : clear_b)) * inv255f;
   2.423 -                    a = ((GLfloat) clear_a) * inv255f;
   2.424 -
   2.425 -                    data->glClearColor(r, g, b, a);
   2.426 -                }
   2.427 -
   2.428 -                if (cliprect_enabled) {
   2.429 -                    data->glDisable(GL_SCISSOR_TEST);
   2.430 -                }
   2.431 -
   2.432 -                data->glClear(GL_COLOR_BUFFER_BIT);
   2.433 -
   2.434 -                if (cliprect_enabled) {
   2.435 -                    data->glEnable(GL_SCISSOR_TEST);
   2.436 -                }
   2.437 -                break;
   2.438 -
   2.439 -            case GLES2_RENDERCMD_ATTR:
   2.440 -                data->glVertexAttribPointer(cmd->data.attr.attr, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.attr.offset);
   2.441 -                break;
   2.442 -
   2.443 -            case GLES2_RENDERCMD_DRAW: {
   2.444 -                const SDL_bool iscopy = (cmd->data.draw.imgsrc != GLES2_IMAGESOURCE_SOLID);
   2.445 -                if (!viewport.w || !viewport.h) {
   2.446 -                    break;  /* nothing to draw to. */
   2.447 -                }
   2.448 -
   2.449 -                if (iscopy && (bound_texture != cmd->data.draw.texture)) {
   2.450 -                    GLES2_TextureData *tdata = (GLES2_TextureData *)cmd->data.draw.texture->driverdata;
   2.451 -                    if (tdata->yuv) {
   2.452 -                        data->glActiveTexture(GL_TEXTURE2);
   2.453 -                        data->glBindTexture(tdata->texture_type, tdata->texture_v);
   2.454 -
   2.455 -                        data->glActiveTexture(GL_TEXTURE1);
   2.456 -                        data->glBindTexture(tdata->texture_type, tdata->texture_u);
   2.457 -
   2.458 -                        data->glActiveTexture(GL_TEXTURE0);
   2.459 -                    }
   2.460 -                    if (tdata->nv12) {
   2.461 -                        data->glActiveTexture(GL_TEXTURE1);
   2.462 -                        data->glBindTexture(tdata->texture_type, tdata->texture_u);
   2.463 -
   2.464 -                        data->glActiveTexture(GL_TEXTURE0);
   2.465 -                    }
   2.466 -                    data->glBindTexture(tdata->texture_type, tdata->texture);
   2.467 -                    bound_texture = cmd->data.draw.texture;
   2.468 -                }
   2.469 -
   2.470 -                if (GLES2_SelectProgram(renderer, cmd->data.draw.imgsrc, iscopy ? bound_texture->w : 0, iscopy ? bound_texture->h : 0) == 0) {
   2.471 -                    GLES2_ProgramCacheEntry *program = data->current_program;
   2.472 -
   2.473 -                    if (enabled_attrs != cmd->data.draw.attrs) {
   2.474 -                        const Uint8 xored = enabled_attrs ^ cmd->data.draw.attrs;
   2.475 -                        int attr;
   2.476 -                        for (attr = 0; attr < GLES2_ATTRIBUTE_CENTER; attr++) {
   2.477 -                            if ((xored & (1 << attr)) != 0) {  /* if changed */
   2.478 -                                if (cmd->data.draw.attrs & (1 << attr)) {
   2.479 -                                    data->glEnableVertexAttribArray((GLenum) attr);
   2.480 -                                } else {
   2.481 -                                    data->glDisableVertexAttribArray((GLenum) attr);
   2.482 -                                }
   2.483 -                            }
   2.484 -                        }
   2.485 -                        enabled_attrs = cmd->data.draw.attrs;
   2.486 -                    }
   2.487 -
   2.488 -                    if (blend != cmd->data.draw.blend) {
   2.489 -                        const SDL_BlendMode bm = cmd->data.draw.blend;
   2.490 -                        if (bm == SDL_BLENDMODE_NONE) {
   2.491 -                            data->glDisable(GL_BLEND);
   2.492 -                        } else {
   2.493 -                            data->glEnable(GL_BLEND);
   2.494 -                            data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(bm)),
   2.495 -                                          GetBlendFunc(SDL_GetBlendModeDstColorFactor(bm)),
   2.496 -                                          GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(bm)),
   2.497 -                                          GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(bm)));
   2.498 -                            data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(bm)),
   2.499 -                                          GetBlendEquation(SDL_GetBlendModeAlphaOperation(bm)));
   2.500 -                        }
   2.501 -                        blend = bm;
   2.502 -                    }
   2.503 -
   2.504 -                    if (program->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
   2.505 -                        projection[0][0] = 2.0f / viewport.w;
   2.506 -                        projection[1][1] = (renderer->target ? 2.0f : -2.0f) / viewport.h;
   2.507 -                        if (SDL_memcmp(program->projection, projection, sizeof (projection)) != 0) {
   2.508 -                            data->glUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)projection);
   2.509 -                            SDL_memcpy(program->projection, projection, sizeof (projection));
   2.510 -                        }
   2.511 -                    }
   2.512 -
   2.513 -                    if (program->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
   2.514 -                        const Uint8 r = colorswap ? cmd->data.draw.b : cmd->data.draw.r;
   2.515 -                        const Uint8 g = cmd->data.draw.g;
   2.516 -                        const Uint8 b = colorswap ? cmd->data.draw.r : cmd->data.draw.b;
   2.517 -                        const Uint8 a = cmd->data.draw.a;
   2.518 -                        if (!CompareColors(program->color_r, program->color_g, program->color_b, program->color_a, r, g, b, a)) {
   2.519 -                            data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
   2.520 -                            program->color_r = r;
   2.521 -                            program->color_g = g;
   2.522 -                            program->color_b = b;
   2.523 -                            program->color_a = a;
   2.524 -                        }
   2.525 -                    }
   2.526 -
   2.527 -                    data->glDrawArrays(cmd->data.draw.mode, cmd->data.draw.first, cmd->data.draw.count);
   2.528 -                }
   2.529 -                break;
   2.530 -            }
   2.531 -
   2.532 -            default: SDL_assert(!"Unknown rendering command"); break;
   2.533 -        }
   2.534 -
   2.535 -        /* put this command in the pool for reuse, move on to next one. */
   2.536 -        next = cmd->next;
   2.537 -        cmd->next = data->render_commands_pool;
   2.538 -        data->render_commands_pool = cmd;
   2.539 -        cmd = next;
   2.540 -    }
   2.541 -
   2.542 -    data->command_generation++;
   2.543 -
   2.544 -    return GL_CheckError("", renderer);
   2.545 +    /* Deallocate the shader */
   2.546 +    data->glDeleteShader(entry->id);
   2.547 +    SDL_free(entry);
   2.548  }
   2.549  
   2.550 -static void
   2.551 -GLES2_FlushCommandsIfTextureNeeded(SDL_Renderer *renderer, SDL_Texture *texture)
   2.552 -{
   2.553 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   2.554 -    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   2.555 -    if (tdata->last_cmd_generation == data->command_generation) {
   2.556 -        /* the current command queue depends on this texture, flush the queue now before it changes */
   2.557 -        GLES2_FlushCommands(renderer);
   2.558 -    }
   2.559 -}
   2.560 -
   2.561 -static int
   2.562 -GLES2_UpdateViewport(SDL_Renderer * renderer)
   2.563 -{
   2.564 -    GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
   2.565 -    if (cmd == NULL) {
   2.566 -        return -1;
   2.567 -    }
   2.568 -    cmd->cmd = GLES2_RENDERCMD_VIEWPORT;
   2.569 -    SDL_memcpy(&cmd->data.viewport, &renderer->viewport, sizeof (SDL_Rect));
   2.570 -    return 0;
   2.571 -}
   2.572 -
   2.573 -static int
   2.574 -GLES2_UpdateClipRect(SDL_Renderer * renderer)
   2.575 -{
   2.576 -    GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
   2.577 -    if (cmd == NULL) {
   2.578 -        return -1;
   2.579 -    }
   2.580 -    cmd->cmd = GLES2_RENDERCMD_CLIPRECT;
   2.581 -    cmd->data.cliprect.enabled = renderer->clipping_enabled;
   2.582 -    SDL_memcpy(&cmd->data.cliprect.rect, &renderer->clip_rect, sizeof (SDL_Rect));
   2.583 -    return 0;
   2.584 -}
   2.585 -
   2.586 -static void
   2.587 -GLES2_DestroyRenderer(SDL_Renderer *renderer)
   2.588 -{
   2.589 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   2.590 -
   2.591 -    /* Deallocate everything */
   2.592 -    if (data) {
   2.593 -        GLES2_RenderCommand *cmd;
   2.594 -
   2.595 -        GLES2_ActivateRenderer(renderer);
   2.596 -
   2.597 -        if (data->render_commands_tail != NULL) {
   2.598 -            data->render_commands_tail->next = data->render_commands_pool;
   2.599 -        } else {
   2.600 -            data->render_commands = data->render_commands_pool;
   2.601 -        }
   2.602 -
   2.603 -        cmd = data->render_commands;
   2.604 -        while (cmd != NULL) {
   2.605 -            GLES2_RenderCommand *next = cmd->next;
   2.606 -            SDL_free(cmd);
   2.607 -            cmd = next;
   2.608 -        }
   2.609 -
   2.610 -        SDL_free(data->vertex_data);
   2.611 -
   2.612 -        {
   2.613 -            GLES2_ShaderCacheEntry *entry;
   2.614 -            GLES2_ShaderCacheEntry *next;
   2.615 -            entry = data->shader_cache.head;
   2.616 -            while (entry) {
   2.617 -                data->glDeleteShader(entry->id);
   2.618 -                next = entry->next;
   2.619 -                SDL_free(entry);
   2.620 -                entry = next;
   2.621 -            }
   2.622 -        }
   2.623 -        {
   2.624 -            GLES2_ProgramCacheEntry *entry;
   2.625 -            GLES2_ProgramCacheEntry *next;
   2.626 -            entry = data->program_cache.head;
   2.627 -            while (entry) {
   2.628 -                data->glDeleteProgram(entry->id);
   2.629 -                next = entry->next;
   2.630 -                SDL_free(entry);
   2.631 -                entry = next;
   2.632 -            }
   2.633 -        }
   2.634 -        if (data->context) {
   2.635 -            while (data->framebuffers) {
   2.636 -                GLES2_FBOList *nextnode = data->framebuffers->next;
   2.637 -                data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
   2.638 -                GL_CheckError("", renderer);
   2.639 -                SDL_free(data->framebuffers);
   2.640 -                data->framebuffers = nextnode;
   2.641 -            }
   2.642 -
   2.643 -            data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
   2.644 -            GL_CheckError("", renderer);
   2.645 -
   2.646 -            SDL_GL_DeleteContext(data->context);
   2.647 -        }
   2.648 -
   2.649 -        SDL_free(data->shader_formats);
   2.650 -        SDL_free(data);
   2.651 -    }
   2.652 -    SDL_free(renderer);
   2.653 -}
   2.654 -
   2.655 -/*************************************************************************************************
   2.656 - * Texture APIs                                                                                  *
   2.657 - *************************************************************************************************/
   2.658 -
   2.659 -static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
   2.660 -static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
   2.661 -                               const void *pixels, int pitch);
   2.662 -static int GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
   2.663 -                               const SDL_Rect * rect,
   2.664 -                               const Uint8 *Yplane, int Ypitch,
   2.665 -                               const Uint8 *Uplane, int Upitch,
   2.666 -                               const Uint8 *Vplane, int Vpitch);
   2.667 -static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
   2.668 -                             void **pixels, int *pitch);
   2.669 -static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
   2.670 -static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
   2.671 -static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
   2.672 -
   2.673 -static int
   2.674 -GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
   2.675 -{
   2.676 -    GLES2_DriverContext *renderdata = (GLES2_DriverContext *)renderer->driverdata;
   2.677 -    GLES2_TextureData *data;
   2.678 -    GLenum format;
   2.679 -    GLenum type;
   2.680 -    GLenum scaleMode;
   2.681 -
   2.682 -    GLES2_ActivateRenderer(renderer);
   2.683 -
   2.684 -    /* Determine the corresponding GLES texture format params */
   2.685 -    switch (texture->format)
   2.686 -    {
   2.687 -    case SDL_PIXELFORMAT_ARGB8888:
   2.688 -    case SDL_PIXELFORMAT_ABGR8888:
   2.689 -    case SDL_PIXELFORMAT_RGB888:
   2.690 -    case SDL_PIXELFORMAT_BGR888:
   2.691 -        format = GL_RGBA;
   2.692 -        type = GL_UNSIGNED_BYTE;
   2.693 -        break;
   2.694 -    case SDL_PIXELFORMAT_IYUV:
   2.695 -    case SDL_PIXELFORMAT_YV12:
   2.696 -    case SDL_PIXELFORMAT_NV12:
   2.697 -    case SDL_PIXELFORMAT_NV21:
   2.698 -        format = GL_LUMINANCE;
   2.699 -        type = GL_UNSIGNED_BYTE;
   2.700 -        break;
   2.701 -#ifdef GL_TEXTURE_EXTERNAL_OES
   2.702 -    case SDL_PIXELFORMAT_EXTERNAL_OES:
   2.703 -        format = GL_NONE;
   2.704 -        type = GL_NONE;
   2.705 -        break;
   2.706 -#endif
   2.707 -    default:
   2.708 -        return SDL_SetError("Texture format not supported");
   2.709 -    }
   2.710 -
   2.711 -    if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES &&
   2.712 -        texture->access != SDL_TEXTUREACCESS_STATIC) {
   2.713 -        return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES");
   2.714 -    }
   2.715 -
   2.716 -    /* Allocate a texture struct */
   2.717 -    data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
   2.718 -    if (!data) {
   2.719 -        return SDL_OutOfMemory();
   2.720 -    }
   2.721 -    data->texture = 0;
   2.722 -#ifdef GL_TEXTURE_EXTERNAL_OES
   2.723 -    data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
   2.724 -#else
   2.725 -    data->texture_type = GL_TEXTURE_2D;
   2.726 -#endif
   2.727 -    data->pixel_format = format;
   2.728 -    data->pixel_type = type;
   2.729 -    data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
   2.730 -    data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
   2.731 -    data->texture_u = 0;
   2.732 -    data->texture_v = 0;
   2.733 -    scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
   2.734 -
   2.735 -    /* Allocate a blob for image renderdata */
   2.736 -    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   2.737 -        size_t size;
   2.738 -        data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
   2.739 -        size = texture->h * data->pitch;
   2.740 -        if (data->yuv) {
   2.741 -            /* Need to add size for the U and V planes */
   2.742 -            size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
   2.743 -        }
   2.744 -        if (data->nv12) {
   2.745 -            /* Need to add size for the U/V plane */
   2.746 -            size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
   2.747 -        }
   2.748 -        data->pixel_data = SDL_calloc(1, size);
   2.749 -        if (!data->pixel_data) {
   2.750 -            SDL_free(data);
   2.751 -            return SDL_OutOfMemory();
   2.752 -        }
   2.753 -    }
   2.754 -
   2.755 -    /* Allocate the texture */
   2.756 -    GL_CheckError("", renderer);
   2.757 -
   2.758 -    if (data->yuv) {
   2.759 -        renderdata->glGenTextures(1, &data->texture_v);
   2.760 -        if (GL_CheckError("glGenTexures()", renderer) < 0) {
   2.761 -            return -1;
   2.762 -        }
   2.763 -        renderdata->glActiveTexture(GL_TEXTURE2);
   2.764 -        renderdata->glBindTexture(data->texture_type, data->texture_v);
   2.765 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   2.766 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   2.767 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   2.768 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   2.769 -        renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
   2.770 -
   2.771 -        renderdata->glGenTextures(1, &data->texture_u);
   2.772 -        if (GL_CheckError("glGenTexures()", renderer) < 0) {
   2.773 -            return -1;
   2.774 -        }
   2.775 -        renderdata->glActiveTexture(GL_TEXTURE1);
   2.776 -        renderdata->glBindTexture(data->texture_type, data->texture_u);
   2.777 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   2.778 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   2.779 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   2.780 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   2.781 -        renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
   2.782 -        if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   2.783 -            return -1;
   2.784 -        }
   2.785 -    }
   2.786 -
   2.787 -    if (data->nv12) {
   2.788 -        renderdata->glGenTextures(1, &data->texture_u);
   2.789 -        if (GL_CheckError("glGenTexures()", renderer) < 0) {
   2.790 -            return -1;
   2.791 -        }
   2.792 -        renderdata->glActiveTexture(GL_TEXTURE1);
   2.793 -        renderdata->glBindTexture(data->texture_type, data->texture_u);
   2.794 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   2.795 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   2.796 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   2.797 -        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   2.798 -        renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
   2.799 -        if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   2.800 -            return -1;
   2.801 -        }
   2.802 -    }
   2.803 -
   2.804 -    renderdata->glGenTextures(1, &data->texture);
   2.805 -    if (GL_CheckError("glGenTexures()", renderer) < 0) {
   2.806 -        return -1;
   2.807 -    }
   2.808 -    texture->driverdata = data;
   2.809 -    renderdata->glActiveTexture(GL_TEXTURE0);
   2.810 -    renderdata->glBindTexture(data->texture_type, data->texture);
   2.811 -    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   2.812 -    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   2.813 -    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   2.814 -    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   2.815 -    if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
   2.816 -        renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
   2.817 -        if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   2.818 -            return -1;
   2.819 -        }
   2.820 -    }
   2.821 -
   2.822 -    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
   2.823 -       data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
   2.824 -    } else {
   2.825 -       data->fbo = NULL;
   2.826 -    }
   2.827 -
   2.828 -    return GL_CheckError("", renderer);
   2.829 -}
   2.830 -
   2.831 -static int
   2.832 -GLES2_TexSubImage2D(GLES2_DriverContext *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
   2.833 -{
   2.834 -    Uint8 *blob = NULL;
   2.835 -    Uint8 *src;
   2.836 -    int src_pitch;
   2.837 -    int y;
   2.838 -
   2.839 -    if ((width == 0) || (height == 0) || (bpp == 0)) {
   2.840 -        return 0;  /* nothing to do */
   2.841 -    }
   2.842 -
   2.843 -    /* Reformat the texture data into a tightly packed array */
   2.844 -    src_pitch = width * bpp;
   2.845 -    src = (Uint8 *)pixels;
   2.846 -    if (pitch != src_pitch) {
   2.847 -        blob = (Uint8 *)SDL_malloc(src_pitch * height);
   2.848 -        if (!blob) {
   2.849 -            return SDL_OutOfMemory();
   2.850 -        }
   2.851 -        src = blob;
   2.852 -        for (y = 0; y < height; ++y)
   2.853 -        {
   2.854 -            SDL_memcpy(src, pixels, src_pitch);
   2.855 -            src += src_pitch;
   2.856 -            pixels = (Uint8 *)pixels + pitch;
   2.857 -        }
   2.858 -        src = blob;
   2.859 -    }
   2.860 -
   2.861 -    data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
   2.862 -    if (blob) {
   2.863 -        SDL_free(blob);
   2.864 -    }
   2.865 -    return 0;
   2.866 -}
   2.867 -
   2.868 -static int
   2.869 -GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
   2.870 -                    const void *pixels, int pitch)
   2.871 -{
   2.872 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   2.873 -    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   2.874 -
   2.875 -    GLES2_ActivateRenderer(renderer);
   2.876 -
   2.877 -    GLES2_FlushCommandsIfTextureNeeded(renderer, texture);
   2.878 -
   2.879 -    /* Bail out if we're supposed to update an empty rectangle */
   2.880 -    if (rect->w <= 0 || rect->h <= 0) {
   2.881 -        return 0;
   2.882 -    }
   2.883 -
   2.884 -    /* Create a texture subimage with the supplied data */
   2.885 -    data->glBindTexture(tdata->texture_type, tdata->texture);
   2.886 -    GLES2_TexSubImage2D(data, tdata->texture_type,
   2.887 -                    rect->x,
   2.888 -                    rect->y,
   2.889 -                    rect->w,
   2.890 -                    rect->h,
   2.891 -                    tdata->pixel_format,
   2.892 -                    tdata->pixel_type,
   2.893 -                    pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
   2.894 -
   2.895 -    if (tdata->yuv) {
   2.896 -        /* Skip to the correct offset into the next texture */
   2.897 -        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
   2.898 -        if (texture->format == SDL_PIXELFORMAT_YV12) {
   2.899 -            data->glBindTexture(tdata->texture_type, tdata->texture_v);
   2.900 -        } else {
   2.901 -            data->glBindTexture(tdata->texture_type, tdata->texture_u);
   2.902 -        }
   2.903 -        GLES2_TexSubImage2D(data, tdata->texture_type,
   2.904 -                rect->x / 2,
   2.905 -                rect->y / 2,
   2.906 -                (rect->w + 1) / 2,
   2.907 -                (rect->h + 1) / 2,
   2.908 -                tdata->pixel_format,
   2.909 -                tdata->pixel_type,
   2.910 -                pixels, (pitch + 1) / 2, 1);
   2.911 -
   2.912 -
   2.913 -        /* Skip to the correct offset into the next texture */
   2.914 -        pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2));
   2.915 -        if (texture->format == SDL_PIXELFORMAT_YV12) {
   2.916 -            data->glBindTexture(tdata->texture_type, tdata->texture_u);
   2.917 -        } else {
   2.918 -            data->glBindTexture(tdata->texture_type, tdata->texture_v);
   2.919 -        }
   2.920 -        GLES2_TexSubImage2D(data, tdata->texture_type,
   2.921 -                rect->x / 2,
   2.922 -                rect->y / 2,
   2.923 -                (rect->w + 1) / 2,
   2.924 -                (rect->h + 1) / 2,
   2.925 -                tdata->pixel_format,
   2.926 -                tdata->pixel_type,
   2.927 -                pixels, (pitch + 1) / 2, 1);
   2.928 -    }
   2.929 -
   2.930 -    if (tdata->nv12) {
   2.931 -        /* Skip to the correct offset into the next texture */
   2.932 -        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
   2.933 -        data->glBindTexture(tdata->texture_type, tdata->texture_u);
   2.934 -        GLES2_TexSubImage2D(data, tdata->texture_type,
   2.935 -                rect->x / 2,
   2.936 -                rect->y / 2,
   2.937 -                (rect->w + 1) / 2,
   2.938 -                (rect->h + 1) / 2,
   2.939 -                GL_LUMINANCE_ALPHA,
   2.940 -                GL_UNSIGNED_BYTE,
   2.941 -                pixels, 2 * ((pitch + 1) / 2), 2);
   2.942 -    }
   2.943 -
   2.944 -    return GL_CheckError("glTexSubImage2D()", renderer);
   2.945 -}
   2.946 -
   2.947 -static int
   2.948 -GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
   2.949 -                    const SDL_Rect * rect,
   2.950 -                    const Uint8 *Yplane, int Ypitch,
   2.951 -                    const Uint8 *Uplane, int Upitch,
   2.952 -                    const Uint8 *Vplane, int Vpitch)
   2.953 -{
   2.954 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
   2.955 -    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   2.956 -
   2.957 -    GLES2_ActivateRenderer(renderer);
   2.958 -
   2.959 -    GLES2_FlushCommandsIfTextureNeeded(renderer, texture);
   2.960 -
   2.961 -    /* Bail out if we're supposed to update an empty rectangle */
   2.962 -    if (rect->w <= 0 || rect->h <= 0) {
   2.963 -        return 0;
   2.964 -    }
   2.965 -
   2.966 -    data->glBindTexture(tdata->texture_type, tdata->texture_v);
   2.967 -    GLES2_TexSubImage2D(data, tdata->texture_type,
   2.968 -                    rect->x / 2,
   2.969 -                    rect->y / 2,
   2.970 -                    (rect->w + 1) / 2,
   2.971 -                    (rect->h + 1) / 2,
   2.972 -                    tdata->pixel_format,
   2.973 -                    tdata->pixel_type,
   2.974 -                    Vplane, Vpitch, 1);
   2.975 -
   2.976 -    data->glBindTexture(tdata->texture_type, tdata->texture_u);
   2.977 -    GLES2_TexSubImage2D(data, tdata->texture_type,
   2.978 -                    rect->x / 2,
   2.979 -                    rect->y / 2,
   2.980 -                    (rect->w + 1) / 2,
   2.981 -                    (rect->h + 1) / 2,
   2.982 -                    tdata->pixel_format,
   2.983 -                    tdata->pixel_type,
   2.984 -                    Uplane, Upitch, 1);
   2.985 -
   2.986 -    data->glBindTexture(tdata->texture_type, tdata->texture);
   2.987 -    GLES2_TexSubImage2D(data, tdata->texture_type,
   2.988 -                    rect->x,
   2.989 -                    rect->y,
   2.990 -                    rect->w,
   2.991 -                    rect->h,
   2.992 -                    tdata->pixel_format,
   2.993 -                    tdata->pixel_type,
   2.994 -                    Yplane, Ypitch, 1);
   2.995 -
   2.996 -    return GL_CheckError("glTexSubImage2D()", renderer);
   2.997 -}
   2.998 -
   2.999 -static int
  2.1000 -GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  2.1001 -                  void **pixels, int *pitch)
  2.1002 -{
  2.1003 -    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.1004 -
  2.1005 -    /* Retrieve the buffer/pitch for the specified region */
  2.1006 -    *pixels = (Uint8 *)tdata->pixel_data +
  2.1007 -              (tdata->pitch * rect->y) +
  2.1008 -              (rect->x * SDL_BYTESPERPIXEL(texture->format));
  2.1009 -    *pitch = tdata->pitch;
  2.1010 -
  2.1011 -    return 0;
  2.1012 -}
  2.1013 -
  2.1014 -static void
  2.1015 -GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  2.1016 -{
  2.1017 -    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.1018 -    SDL_Rect rect;
  2.1019 -
  2.1020 -    /* We do whole texture updates, at least for now */
  2.1021 -    rect.x = 0;
  2.1022 -    rect.y = 0;
  2.1023 -    rect.w = texture->w;
  2.1024 -    rect.h = texture->h;
  2.1025 -    GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
  2.1026 -}
  2.1027 -
  2.1028 -static int
  2.1029 -GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
  2.1030 -{
  2.1031 -    GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
  2.1032 -    GLES2_TextureData *texturedata = NULL;
  2.1033 -    GLenum status;
  2.1034 -
  2.1035 -    GLES2_FlushCommands(renderer);  /* time to send everything to the GPU! */
  2.1036 -
  2.1037 -    if (texture == NULL) {
  2.1038 -        data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
  2.1039 -    } else {
  2.1040 -        texturedata = (GLES2_TextureData *) texture->driverdata;
  2.1041 -        data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
  2.1042 -        /* TODO: check if texture pixel format allows this operation */
  2.1043 -        data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
  2.1044 -        /* Check FBO status */
  2.1045 -        status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
  2.1046 -        if (status != GL_FRAMEBUFFER_COMPLETE) {
  2.1047 -            return SDL_SetError("glFramebufferTexture2D() failed");
  2.1048 -        }
  2.1049 -    }
  2.1050 -    return 0;
  2.1051 -}
  2.1052 -
  2.1053 -static void
  2.1054 -GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  2.1055 -{
  2.1056 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.1057 -    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.1058 -
  2.1059 -    GLES2_ActivateRenderer(renderer);
  2.1060 -
  2.1061 -    GLES2_FlushCommandsIfTextureNeeded(renderer, texture);
  2.1062 -
  2.1063 -    /* Destroy the texture */
  2.1064 -    if (tdata) {
  2.1065 -        data->glDeleteTextures(1, &tdata->texture);
  2.1066 -        if (tdata->texture_v) {
  2.1067 -            data->glDeleteTextures(1, &tdata->texture_v);
  2.1068 -        }
  2.1069 -        if (tdata->texture_u) {
  2.1070 -            data->glDeleteTextures(1, &tdata->texture_u);
  2.1071 -        }
  2.1072 -        SDL_free(tdata->pixel_data);
  2.1073 -        SDL_free(tdata);
  2.1074 -        texture->driverdata = NULL;
  2.1075 -    }
  2.1076 -}
  2.1077 -
  2.1078 -/*************************************************************************************************
  2.1079 - * Shader management functions                                                                   *
  2.1080 - *************************************************************************************************/
  2.1081 -
  2.1082 -static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type);
  2.1083 -static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
  2.1084 -static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer,
  2.1085 -                                                   GLES2_ShaderCacheEntry *vertex,
  2.1086 -                                                   GLES2_ShaderCacheEntry *fragment);
  2.1087 -
  2.1088  static GLES2_ProgramCacheEntry *
  2.1089 -GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
  2.1090 +GLES2_CacheProgram(GLES2_RenderData *data, GLES2_ShaderCacheEntry *vertex,
  2.1091                     GLES2_ShaderCacheEntry *fragment)
  2.1092  {
  2.1093 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.1094      GLES2_ProgramCacheEntry *entry;
  2.1095      GLES2_ShaderCacheEntry *shaderEntry;
  2.1096      GLint linkSuccessful;
  2.1097 @@ -1369,8 +478,7 @@
  2.1098      entry->uniform_locations[GLES2_UNIFORM_COLOR] =
  2.1099          data->glGetUniformLocation(entry->id, "u_color");
  2.1100  
  2.1101 -    entry->modulation_r = entry->modulation_g = entry->modulation_b = entry->modulation_a = 255;
  2.1102 -    entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255;
  2.1103 +    entry->color = 0;
  2.1104  
  2.1105      data->glUseProgram(entry->id);
  2.1106      if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] != -1) {
  2.1107 @@ -1386,7 +494,7 @@
  2.1108          data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
  2.1109      }
  2.1110      if (entry->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
  2.1111 -        data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
  2.1112 +        data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 0.0f, 0.0f, 0.0f, 0.0f);
  2.1113      }
  2.1114  
  2.1115      /* Cache the linked program */
  2.1116 @@ -1407,11 +515,11 @@
  2.1117      if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
  2.1118          shaderEntry = data->program_cache.tail->vertex_shader;
  2.1119          if (--shaderEntry->references <= 0) {
  2.1120 -            GLES2_EvictShader(renderer, shaderEntry);
  2.1121 +            GLES2_EvictShader(data, shaderEntry);
  2.1122          }
  2.1123          shaderEntry = data->program_cache.tail->fragment_shader;
  2.1124          if (--shaderEntry->references <= 0) {
  2.1125 -            GLES2_EvictShader(renderer, shaderEntry);
  2.1126 +            GLES2_EvictShader(data, shaderEntry);
  2.1127          }
  2.1128          data->glDeleteProgram(data->program_cache.tail->id);
  2.1129          data->program_cache.tail = data->program_cache.tail->prev;
  2.1130 @@ -1423,9 +531,8 @@
  2.1131  }
  2.1132  
  2.1133  static GLES2_ShaderCacheEntry *
  2.1134 -GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type)
  2.1135 +GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type)
  2.1136  {
  2.1137 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.1138      const GLES2_Shader *shader;
  2.1139      const GLES2_ShaderInstance *instance = NULL;
  2.1140      GLES2_ShaderCacheEntry *entry = NULL;
  2.1141 @@ -1519,32 +626,9 @@
  2.1142      return entry;
  2.1143  }
  2.1144  
  2.1145 -static void
  2.1146 -GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
  2.1147 +static int
  2.1148 +GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int h)
  2.1149  {
  2.1150 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.1151 -
  2.1152 -    /* Unlink the shader from the cache */
  2.1153 -    if (entry->next) {
  2.1154 -        entry->next->prev = entry->prev;
  2.1155 -    }
  2.1156 -    if (entry->prev) {
  2.1157 -        entry->prev->next = entry->next;
  2.1158 -    }
  2.1159 -    if (data->shader_cache.head == entry) {
  2.1160 -        data->shader_cache.head = entry->next;
  2.1161 -    }
  2.1162 -    --data->shader_cache.count;
  2.1163 -
  2.1164 -    /* Deallocate the shader */
  2.1165 -    data->glDeleteShader(entry->id);
  2.1166 -    SDL_free(entry);
  2.1167 -}
  2.1168 -
  2.1169 -static int
  2.1170 -GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, int w, int h)
  2.1171 -{
  2.1172 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.1173      GLES2_ShaderCacheEntry *vertex = NULL;
  2.1174      GLES2_ShaderCacheEntry *fragment = NULL;
  2.1175      GLES2_ShaderType vtype, ftype;
  2.1176 @@ -1624,24 +708,24 @@
  2.1177      }
  2.1178  
  2.1179      /* Load the requested shaders */
  2.1180 -    vertex = GLES2_CacheShader(renderer, vtype);
  2.1181 +    vertex = GLES2_CacheShader(data, vtype);
  2.1182      if (!vertex) {
  2.1183          goto fault;
  2.1184      }
  2.1185 -    fragment = GLES2_CacheShader(renderer, ftype);
  2.1186 +    fragment = GLES2_CacheShader(data, ftype);
  2.1187      if (!fragment) {
  2.1188          goto fault;
  2.1189      }
  2.1190  
  2.1191      /* Check if we need to change programs at all */
  2.1192 -    if (data->current_program &&
  2.1193 -        data->current_program->vertex_shader == vertex &&
  2.1194 -        data->current_program->fragment_shader == fragment) {
  2.1195 +    if (data->drawstate.program &&
  2.1196 +        data->drawstate.program->vertex_shader == vertex &&
  2.1197 +        data->drawstate.program->fragment_shader == fragment) {
  2.1198          return 0;
  2.1199      }
  2.1200  
  2.1201      /* Generate a matching program */
  2.1202 -    program = GLES2_CacheProgram(renderer, vertex, fragment);
  2.1203 +    program = GLES2_CacheProgram(data, vertex, fragment);
  2.1204      if (!program) {
  2.1205          goto fault;
  2.1206      }
  2.1207 @@ -1650,205 +734,314 @@
  2.1208      data->glUseProgram(program->id);
  2.1209  
  2.1210      /* Set the current program */
  2.1211 -    data->current_program = program;
  2.1212 +    data->drawstate.program = program;
  2.1213  
  2.1214      /* Clean up and return */
  2.1215      return 0;
  2.1216  fault:
  2.1217      if (vertex && vertex->references <= 0) {
  2.1218 -        GLES2_EvictShader(renderer, vertex);
  2.1219 +        GLES2_EvictShader(data, vertex);
  2.1220      }
  2.1221      if (fragment && fragment->references <= 0) {
  2.1222 -        GLES2_EvictShader(renderer, fragment);
  2.1223 +        GLES2_EvictShader(data, fragment);
  2.1224      }
  2.1225 -    data->current_program = NULL;
  2.1226 +    data->drawstate.program = NULL;
  2.1227      return -1;
  2.1228  }
  2.1229  
  2.1230 -
  2.1231 -/*************************************************************************************************
  2.1232 - * Rendering functions                                                                           *
  2.1233 - *************************************************************************************************/
  2.1234 -
  2.1235 -static int GLES2_RenderClear(SDL_Renderer *renderer);
  2.1236 -static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
  2.1237 -static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
  2.1238 -static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count);
  2.1239 -static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  2.1240 -                            const SDL_FRect *dstrect);
  2.1241 -static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
  2.1242 -                         const SDL_Rect * srcrect, const SDL_FRect * dstrect,
  2.1243 -                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
  2.1244 -static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  2.1245 -                    Uint32 pixel_format, void * pixels, int pitch);
  2.1246 -static void GLES2_RenderPresent(SDL_Renderer *renderer);
  2.1247 -
  2.1248  static int
  2.1249 -GLES2_RenderClear(SDL_Renderer * renderer)
  2.1250 +GLES2_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
  2.1251  {
  2.1252 -    GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
  2.1253 -    if (cmd == NULL) {
  2.1254 -        return -1;
  2.1255 -    }
  2.1256 -    cmd->cmd = GLES2_RENDERCMD_CLEAR;
  2.1257 -    cmd->data.clear.r = renderer->r;
  2.1258 -    cmd->data.clear.g = renderer->g;
  2.1259 -    cmd->data.clear.b = renderer->b;
  2.1260 -    cmd->data.clear.a = renderer->a;
  2.1261 -    return 0;
  2.1262 +    return 0;  /* nothing to do in this backend. */
  2.1263  }
  2.1264  
  2.1265  static int
  2.1266 -GLES2_AddVertices(SDL_Renderer *renderer, const GLES2_Attribute attr, const float *vertexData, size_t dataSizeInElements)
  2.1267 +GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
  2.1268  {
  2.1269 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.1270 -    const GLsizeiptr needed = data->current_vertex_data + dataSizeInElements;
  2.1271 -    GLES2_RenderCommand *cmd;
  2.1272 -    GLfloat *vdata;
  2.1273 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
  2.1274 +    size_t i;
  2.1275  
  2.1276 -    if (needed > data->vertex_data_allocation) {
  2.1277 -        const GLsizeiptr newsize = data->vertex_data_allocation * 2;
  2.1278 -printf("realloc'ing %p to %d\n", data->vertex_data, (int) newsize);
  2.1279 -        void *ptr = SDL_realloc(data->vertex_data, newsize * sizeof (GLfloat));
  2.1280 -        if (ptr == NULL) {
  2.1281 -            SDL_OutOfMemory();
  2.1282 -            return -1;
  2.1283 -        }
  2.1284 -        data->vertex_data = (GLfloat *) ptr;
  2.1285 -        data->vertex_data_allocation = newsize;
  2.1286 -    }
  2.1287 -
  2.1288 -    cmd = GLES2_AllocateRenderCommand(renderer);
  2.1289 -    if (cmd == NULL) {
  2.1290 +    if (!verts) {
  2.1291          return -1;
  2.1292      }
  2.1293  
  2.1294 -    vdata = &data->vertex_data[data->current_vertex_data];
  2.1295 -    SDL_memcpy(vdata, vertexData, dataSizeInElements * sizeof (GLfloat));
  2.1296 -    cmd->cmd = GLES2_RENDERCMD_ATTR;
  2.1297 -    cmd->data.attr.attr = attr;
  2.1298 -    cmd->data.attr.offset = data->current_vertex_data * sizeof (GLfloat);
  2.1299 -    cmd->data.attr.count = dataSizeInElements;
  2.1300 -    data->current_vertex_data += dataSizeInElements;
  2.1301 -    return 0;
  2.1302 -}
  2.1303 -
  2.1304 -static int
  2.1305 -GLES2_AddSolidDrawCommand(SDL_Renderer *renderer, const GLenum mode, const GLint first, const GLsizei count)
  2.1306 -{
  2.1307 -    GLES2_RenderCommand *cmd = GLES2_AllocateRenderCommand(renderer);
  2.1308 -    if (cmd == NULL) {
  2.1309 -        return -1;
  2.1310 -    }
  2.1311 -    cmd->cmd = GLES2_RENDERCMD_DRAW;
  2.1312 -    cmd->data.draw.mode = mode;
  2.1313 -    cmd->data.draw.first = first;
  2.1314      cmd->data.draw.count = count;
  2.1315 -    cmd->data.draw.attrs = (1 << GLES2_ATTRIBUTE_POSITION);
  2.1316 -    cmd->data.draw.r = renderer->r;
  2.1317 -    cmd->data.draw.g = renderer->g;
  2.1318 -    cmd->data.draw.b = renderer->b;
  2.1319 -    cmd->data.draw.a = renderer->a;
  2.1320 -    cmd->data.draw.blend = renderer->blendMode;
  2.1321 -    cmd->data.draw.imgsrc = GLES2_IMAGESOURCE_SOLID;
  2.1322 -    cmd->data.draw.texture = NULL;
  2.1323 -    return 0;
  2.1324 -}
  2.1325 -
  2.1326 -static int
  2.1327 -GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
  2.1328 -{
  2.1329 -    GLfloat *vertices = SDL_stack_alloc(GLfloat, count * 2);  /* !!! FIXME: We could do this without a stack_alloc... */
  2.1330 -    int idx;
  2.1331 -    int rc;
  2.1332 -
  2.1333 -    /* Emit the specified vertices as points */
  2.1334 -    for (idx = 0; idx < count; ++idx) {
  2.1335 -        vertices[idx * 2] = points[idx].x + 0.5f;
  2.1336 -        vertices[(idx * 2) + 1] = points[idx].y + 0.5f;
  2.1337 -    }
  2.1338 -
  2.1339 -    rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2);
  2.1340 -    SDL_stack_free(vertices);
  2.1341 -
  2.1342 -    if (rc == 0) {
  2.1343 -        rc = GLES2_AddSolidDrawCommand(renderer, GL_POINTS, 0, count);
  2.1344 -    }
  2.1345 -
  2.1346 -    return rc;
  2.1347 -}
  2.1348 -
  2.1349 -static int
  2.1350 -GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
  2.1351 -{
  2.1352 -    GLfloat *vertices = SDL_stack_alloc(GLfloat, count * 2);  /* !!! FIXME: We could do this without a stack_alloc... */
  2.1353 -    int idx;
  2.1354 -    int rc;
  2.1355 -
  2.1356 -    /* Emit a line strip including the specified vertices */
  2.1357 -    for (idx = 0; idx < count; ++idx) {
  2.1358 -        vertices[idx * 2] = points[idx].x + 0.5f;
  2.1359 -        vertices[(idx * 2) + 1] = points[idx].y + 0.5f;
  2.1360 -    }
  2.1361 -
  2.1362 -    rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2);
  2.1363 -    if (rc == 0) {
  2.1364 -        rc = GLES2_AddSolidDrawCommand(renderer, GL_LINE_STRIP, 0, count);
  2.1365 -    }
  2.1366 -
  2.1367 -#if 0  /* !!! FIXME: ugh */
  2.1368 -    /* We need to close the endpoint of the line */
  2.1369 -    if (count == 2 ||
  2.1370 -        points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
  2.1371 -        GLES2_DrawVertices(GL_POINTS, count-1, 1);
  2.1372 -    }
  2.1373 -#endif
  2.1374 -
  2.1375 -    SDL_stack_free(vertices);
  2.1376 -    return rc;
  2.1377 -}
  2.1378 -
  2.1379 -static int
  2.1380 -GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
  2.1381 -{
  2.1382 -    GLfloat vertices[8];
  2.1383 -    int idx;
  2.1384 -    int rc = 0;
  2.1385 -
  2.1386 -    /* Emit a line loop for each rectangle */
  2.1387 -    for (idx = 0; (rc == 0) && (idx < count); ++idx) {
  2.1388 -        const SDL_FRect *rect = &rects[idx];
  2.1389 -
  2.1390 -        GLfloat xMin = rect->x;
  2.1391 -        GLfloat xMax = (rect->x + rect->w);
  2.1392 -        GLfloat yMin = rect->y;
  2.1393 -        GLfloat yMax = (rect->y + rect->h);
  2.1394 -
  2.1395 -        vertices[0] = xMin;
  2.1396 -        vertices[1] = yMin;
  2.1397 -        vertices[2] = xMax;
  2.1398 -        vertices[3] = yMin;
  2.1399 -        vertices[4] = xMin;
  2.1400 -        vertices[5] = yMax;
  2.1401 -        vertices[6] = xMax;
  2.1402 -        vertices[7] = yMax;
  2.1403 -
  2.1404 -        rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
  2.1405 -        if (rc == 0) {
  2.1406 -            rc = GLES2_AddSolidDrawCommand(renderer, GL_TRIANGLE_STRIP, 0, 4);
  2.1407 -        }
  2.1408 +    for (i = 0; i < count; i++) {
  2.1409 +        *(verts++) = 0.5f + points[i].x;
  2.1410 +        *(verts++) = 0.5f + points[i].y;
  2.1411      }
  2.1412  
  2.1413      return 0;
  2.1414  }
  2.1415  
  2.1416 +static int
  2.1417 +GLES2_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
  2.1418 +{
  2.1419 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
  2.1420 +    size_t i;
  2.1421 +
  2.1422 +    if (!verts) {
  2.1423 +        return -1;
  2.1424 +    }
  2.1425 +
  2.1426 +    cmd->data.draw.count = count;
  2.1427 +
  2.1428 +    for (i = 0; i < count; i++) {
  2.1429 +        const SDL_FRect *rect = &rects[i];
  2.1430 +        const GLfloat minx = rect->x;
  2.1431 +        const GLfloat maxx = rect->x + rect->w;
  2.1432 +        const GLfloat miny = rect->y;
  2.1433 +        const GLfloat maxy = rect->y + rect->h;
  2.1434 +        *(verts++) = minx;
  2.1435 +        *(verts++) = miny;
  2.1436 +        *(verts++) = maxx;
  2.1437 +        *(verts++) = miny;
  2.1438 +        *(verts++) = minx;
  2.1439 +        *(verts++) = maxy;
  2.1440 +        *(verts++) = maxx;
  2.1441 +        *(verts++) = maxy;
  2.1442 +    }
  2.1443 +
  2.1444 +    return 0;
  2.1445 +}
  2.1446  
  2.1447  static int
  2.1448 -GLES2_AddCopyDrawCommand(SDL_Renderer *renderer, SDL_Texture *texture, const Uint8 attrs)
  2.1449 +GLES2_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
  2.1450 +                          const SDL_Rect * srcrect, const SDL_FRect * dstrect)
  2.1451  {
  2.1452 -    GLES2_RenderCommand *cmd = NULL;
  2.1453 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.1454 +    GLfloat minx, miny, maxx, maxy;
  2.1455 +    GLfloat minu, maxu, minv, maxv;
  2.1456 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
  2.1457 +
  2.1458 +    if (!verts) {
  2.1459 +        return -1;
  2.1460 +    }
  2.1461 +
  2.1462 +    cmd->data.draw.count = 1;
  2.1463 +
  2.1464 +    minx = dstrect->x;
  2.1465 +    miny = dstrect->y;
  2.1466 +    maxx = dstrect->x + dstrect->w;
  2.1467 +    maxy = dstrect->y + dstrect->h;
  2.1468 +
  2.1469 +    minu = (GLfloat) srcrect->x / texture->w;
  2.1470 +    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
  2.1471 +    minv = (GLfloat) srcrect->y / texture->h;
  2.1472 +    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
  2.1473 +
  2.1474 +    *(verts++) = minx;
  2.1475 +    *(verts++) = miny;
  2.1476 +    *(verts++) = maxx;
  2.1477 +    *(verts++) = miny;
  2.1478 +    *(verts++) = minx;
  2.1479 +    *(verts++) = maxy;
  2.1480 +    *(verts++) = maxx;
  2.1481 +    *(verts++) = maxy;
  2.1482 +
  2.1483 +    *(verts++) = minu;
  2.1484 +    *(verts++) = minv;
  2.1485 +    *(verts++) = maxu;
  2.1486 +    *(verts++) = minv;
  2.1487 +    *(verts++) = minu;
  2.1488 +    *(verts++) = maxv;
  2.1489 +    *(verts++) = maxu;
  2.1490 +    *(verts++) = maxv;
  2.1491 +
  2.1492 +    return 0;
  2.1493 +}
  2.1494 +
  2.1495 +static int
  2.1496 +GLES2_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
  2.1497 +                        const SDL_Rect * srcquad, const SDL_FRect * dstrect,
  2.1498 +                        const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
  2.1499 +{
  2.1500 +    /* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
  2.1501 +    const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
  2.1502 +    const GLfloat s = (GLfloat) SDL_sin(radian_angle);
  2.1503 +    const GLfloat c = (GLfloat) SDL_cos(radian_angle) - 1.0f;
  2.1504 +    const GLfloat centerx = center->x + dstrect->x;
  2.1505 +    const GLfloat centery = center->y + dstrect->y;
  2.1506 +    GLfloat minx, miny, maxx, maxy;
  2.1507 +    GLfloat minu, maxu, minv, maxv;
  2.1508 +    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 32 * sizeof (GLfloat), 0, &cmd->data.draw.first);
  2.1509 +
  2.1510 +    if (!verts) {
  2.1511 +        return -1;
  2.1512 +    }
  2.1513 +
  2.1514 +    if (flip & SDL_FLIP_HORIZONTAL) {
  2.1515 +        minx = dstrect->x + dstrect->w;
  2.1516 +        maxx = dstrect->x;
  2.1517 +    }
  2.1518 +    else {
  2.1519 +        minx = dstrect->x;
  2.1520 +        maxx = dstrect->x + dstrect->w;
  2.1521 +    }
  2.1522 +
  2.1523 +    if (flip & SDL_FLIP_VERTICAL) {
  2.1524 +        miny = dstrect->y + dstrect->h;
  2.1525 +        maxy = dstrect->y;
  2.1526 +    }
  2.1527 +    else {
  2.1528 +        miny = dstrect->y;
  2.1529 +        maxy = dstrect->y + dstrect->h;
  2.1530 +    }
  2.1531 +
  2.1532 +    minu = (GLfloat) (srcquad->x / texture->w);
  2.1533 +    maxu = (GLfloat) ((srcquad->x + srcquad->w) / texture->w);
  2.1534 +    minv = (GLfloat) (srcquad->y / texture->h);
  2.1535 +    maxv = (GLfloat) ((srcquad->y + srcquad->h) / texture->h);
  2.1536 +
  2.1537 +    cmd->data.draw.count = 1;
  2.1538 +
  2.1539 +    *(verts++) = minx;
  2.1540 +    *(verts++) = miny;
  2.1541 +    *(verts++) = maxx;
  2.1542 +    *(verts++) = miny;
  2.1543 +    *(verts++) = minx;
  2.1544 +    *(verts++) = maxy;
  2.1545 +    *(verts++) = maxx;
  2.1546 +    *(verts++) = maxy;
  2.1547 +
  2.1548 +    *(verts++) = minu;
  2.1549 +    *(verts++) = minv;
  2.1550 +    *(verts++) = maxu;
  2.1551 +    *(verts++) = minv;
  2.1552 +    *(verts++) = minu;
  2.1553 +    *(verts++) = maxv;
  2.1554 +    *(verts++) = maxu;
  2.1555 +    *(verts++) = maxv;
  2.1556 +
  2.1557 +    *(verts++) = s;
  2.1558 +    *(verts++) = c;
  2.1559 +    *(verts++) = s;
  2.1560 +    *(verts++) = c;
  2.1561 +    *(verts++) = s;
  2.1562 +    *(verts++) = c;
  2.1563 +    *(verts++) = s;
  2.1564 +    *(verts++) = c;
  2.1565 +
  2.1566 +    *(verts++) = centerx;
  2.1567 +    *(verts++) = centery;
  2.1568 +    *(verts++) = centerx;
  2.1569 +    *(verts++) = centery;
  2.1570 +    *(verts++) = centerx;
  2.1571 +    *(verts++) = centery;
  2.1572 +    *(verts++) = centerx;
  2.1573 +    *(verts++) = centery;
  2.1574 +
  2.1575 +    return 0;
  2.1576 +}
  2.1577 +
  2.1578 +static int
  2.1579 +SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc)
  2.1580 +{
  2.1581 +    const SDL_bool was_copy_ex = data->drawstate.is_copy_ex;
  2.1582 +    const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX);
  2.1583 +    SDL_Texture *texture = cmd->data.draw.texture;
  2.1584 +    GLES2_ProgramCacheEntry *program;
  2.1585 +
  2.1586 +    SDL_assert((texture != NULL) == (imgsrc != GLES2_IMAGESOURCE_SOLID));
  2.1587 +
  2.1588 +    if (texture != data->drawstate.texture) {
  2.1589 +        if ((texture != NULL) != data->drawstate.texturing) {
  2.1590 +            if (texture == NULL) {
  2.1591 +                data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
  2.1592 +                data->drawstate.texturing = SDL_FALSE;
  2.1593 +            } else {
  2.1594 +                data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
  2.1595 +                data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first + (sizeof (GLfloat) * 8));
  2.1596 +                data->drawstate.texturing = SDL_TRUE;
  2.1597 +            }
  2.1598 +        }
  2.1599 +
  2.1600 +        if (texture) {
  2.1601 +            GLES2_TextureData *tdata = (GLES2_TextureData *) texture->driverdata;
  2.1602 +            if (tdata->yuv) {
  2.1603 +                data->glActiveTexture(GL_TEXTURE2);
  2.1604 +                data->glBindTexture(tdata->texture_type, tdata->texture_v);
  2.1605 +
  2.1606 +                data->glActiveTexture(GL_TEXTURE1);
  2.1607 +                data->glBindTexture(tdata->texture_type, tdata->texture_u);
  2.1608 +
  2.1609 +                data->glActiveTexture(GL_TEXTURE0);
  2.1610 +            } else if (tdata->nv12) {
  2.1611 +                data->glActiveTexture(GL_TEXTURE1);
  2.1612 +                data->glBindTexture(tdata->texture_type, tdata->texture_u);
  2.1613 +
  2.1614 +                data->glActiveTexture(GL_TEXTURE0);
  2.1615 +            }
  2.1616 +            data->glBindTexture(tdata->texture_type, tdata->texture);
  2.1617 +        }
  2.1618 +
  2.1619 +        data->drawstate.texture = texture;
  2.1620 +    }
  2.1621 +
  2.1622 +    if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
  2.1623 +        return -1;
  2.1624 +    }
  2.1625 +
  2.1626 +    program = data->drawstate.program;
  2.1627 +
  2.1628 +    if (program->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
  2.1629 +        if (SDL_memcmp(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)) != 0) {
  2.1630 +            data->glUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection);
  2.1631 +            SDL_memcpy(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection));
  2.1632 +        }
  2.1633 +    }
  2.1634 +
  2.1635 +    if (program->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
  2.1636 +        if (data->drawstate.color != program->color) {
  2.1637 +            const Uint8 r = (data->drawstate.color >> 16) & 0xFF;
  2.1638 +            const Uint8 g = (data->drawstate.color >> 8) & 0xFF;
  2.1639 +            const Uint8 b = (data->drawstate.color >> 0) & 0xFF;
  2.1640 +            const Uint8 a = (data->drawstate.color >> 24) & 0xFF;
  2.1641 +            data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
  2.1642 +            program->color = data->drawstate.color;
  2.1643 +        }
  2.1644 +    }
  2.1645 +
  2.1646 +    const SDL_BlendMode blend = cmd->data.draw.blend;
  2.1647 +    if (blend != data->drawstate.blend) {
  2.1648 +        if (blend == SDL_BLENDMODE_NONE) {
  2.1649 +            data->glDisable(GL_BLEND);
  2.1650 +        } else {
  2.1651 +            data->glEnable(GL_BLEND);
  2.1652 +            data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
  2.1653 +                                      GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
  2.1654 +                                      GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
  2.1655 +                                      GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
  2.1656 +            data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
  2.1657 +                                          GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
  2.1658 +        }
  2.1659 +        data->drawstate.blend = blend;
  2.1660 +    }
  2.1661 +
  2.1662 +    /* all drawing commands use this */
  2.1663 +    data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first);
  2.1664 +
  2.1665 +    if (is_copy_ex != was_copy_ex) {
  2.1666 +        if (is_copy_ex) {
  2.1667 +            data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
  2.1668 +            data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
  2.1669 +            data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 16)));
  2.1670 +            data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 24)));
  2.1671 +        } else {
  2.1672 +            data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
  2.1673 +            data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
  2.1674 +        }
  2.1675 +        data->drawstate.is_copy_ex = is_copy_ex;
  2.1676 +    }
  2.1677 +
  2.1678 +    return 0;
  2.1679 +}
  2.1680 +
  2.1681 +static int
  2.1682 +SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
  2.1683 +{
  2.1684 +    GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
  2.1685      GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  2.1686 +    SDL_Texture *texture = cmd->data.draw.texture;
  2.1687  
  2.1688      /* Pick an appropriate shader */
  2.1689      if (renderer->target) {
  2.1690 @@ -1954,132 +1147,619 @@
  2.1691          }
  2.1692      }
  2.1693  
  2.1694 -    ((GLES2_TextureData *)texture->driverdata)->last_cmd_generation = data->command_generation;
  2.1695 +    return SetDrawState(data, cmd, sourceType);
  2.1696 +}
  2.1697  
  2.1698 -    cmd = GLES2_AllocateRenderCommand(renderer);
  2.1699 -    if (cmd == NULL) {
  2.1700 +static int
  2.1701 +GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
  2.1702 +{
  2.1703 +    GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
  2.1704 +    const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
  2.1705 +    const int vboidx = data->current_vertex_buffer;
  2.1706 +    const GLuint vbo = data->vertex_buffers[vboidx];
  2.1707 +    int drawablew = 0, drawableh = 0;
  2.1708 +    const SDL_bool istarget = renderer->target != NULL;
  2.1709 +    size_t i;
  2.1710 +
  2.1711 +    if (GLES2_ActivateRenderer(renderer) < 0) {
  2.1712          return -1;
  2.1713      }
  2.1714 -    cmd->cmd = GLES2_RENDERCMD_DRAW;
  2.1715 -    cmd->data.draw.mode = GL_TRIANGLE_STRIP;
  2.1716 -    cmd->data.draw.first = 0;
  2.1717 -    cmd->data.draw.count = 4;
  2.1718 -    cmd->data.draw.attrs = attrs | (1 << GLES2_ATTRIBUTE_POSITION) | (1 << GLES2_ATTRIBUTE_TEXCOORD);
  2.1719 -    cmd->data.draw.r = texture->r;
  2.1720 -    cmd->data.draw.g = texture->g;
  2.1721 -    cmd->data.draw.b = texture->b;
  2.1722 -    cmd->data.draw.a = texture->a;
  2.1723 -    cmd->data.draw.blend = texture->blendMode;
  2.1724 -    cmd->data.draw.imgsrc = sourceType;
  2.1725 -    cmd->data.draw.texture = texture;
  2.1726 +
  2.1727 +    if (!istarget) {
  2.1728 +        SDL_GL_GetDrawableSize(renderer->window, &drawablew, &drawableh);
  2.1729 +    }
  2.1730 +
  2.1731 +    /* upload the new VBO data for this set of commands. */
  2.1732 +    data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
  2.1733 +    if (data->vertex_buffer_size[vboidx] < vertsize) {
  2.1734 +        data->glBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_STREAM_DRAW);
  2.1735 +        data->vertex_buffer_size[vboidx] = vertsize;
  2.1736 +    } else {
  2.1737 +        data->glBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices);
  2.1738 +    }
  2.1739 +
  2.1740 +    /* cycle through a few VBOs so the GL has some time with the data before we replace it. */
  2.1741 +    data->current_vertex_buffer++;
  2.1742 +    if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
  2.1743 +        data->current_vertex_buffer = 0;
  2.1744 +    }
  2.1745 +
  2.1746 +    while (cmd) {
  2.1747 +        switch (cmd->command) {
  2.1748 +            case SDL_RENDERCMD_SETDRAWCOLOR: {
  2.1749 +                const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
  2.1750 +                const Uint8 g = cmd->data.color.g;
  2.1751 +                const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
  2.1752 +                const Uint8 a = cmd->data.color.a;
  2.1753 +                data->drawstate.color = ((a << 24) | (r << 16) | (g << 8) | b);
  2.1754 +                break;
  2.1755 +            }
  2.1756 +
  2.1757 +            case SDL_RENDERCMD_SETVIEWPORT: {
  2.1758 +                SDL_Rect *viewport = &data->drawstate.viewport;
  2.1759 +                if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
  2.1760 +                    SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
  2.1761 +                    data->glViewport(viewport->x,
  2.1762 +                            istarget ? viewport->y : (drawableh - viewport->y - viewport->h),
  2.1763 +                            viewport->w, viewport->h);
  2.1764 +                    if (viewport->w && viewport->h) {
  2.1765 +                        data->drawstate.projection[0][0] = 2.0f / viewport->w;
  2.1766 +                        data->drawstate.projection[1][1] = (renderer->target ? 2.0f : -2.0f) / viewport->h;
  2.1767 +                        data->drawstate.projection[3][1] = renderer->target ? -1.0f : 1.0f;
  2.1768 +                    }
  2.1769 +                }
  2.1770 +                break;
  2.1771 +            }
  2.1772 +
  2.1773 +            case SDL_RENDERCMD_SETCLIPRECT: {
  2.1774 +                const SDL_Rect *rect = &cmd->data.cliprect.rect;
  2.1775 +                if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
  2.1776 +                    data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
  2.1777 +                    if (!data->drawstate.cliprect_enabled) {
  2.1778 +                        data->glDisable(GL_SCISSOR_TEST);
  2.1779 +                    } else {
  2.1780 +                        const SDL_Rect *viewport = &data->drawstate.viewport;
  2.1781 +                        data->glEnable(GL_SCISSOR_TEST);
  2.1782 +                        if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
  2.1783 +                            data->glScissor(viewport->x + rect->x,
  2.1784 +                                            istarget ? viewport->y + rect->y : drawableh - viewport->y - rect->y - rect->h,
  2.1785 +                                            rect->w, rect->h);
  2.1786 +                            SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
  2.1787 +                        }
  2.1788 +                    }
  2.1789 +                }
  2.1790 +                break;
  2.1791 +            }
  2.1792 +
  2.1793 +            case SDL_RENDERCMD_CLEAR: {
  2.1794 +                const Uint8 r = cmd->data.color.r;
  2.1795 +                const Uint8 g = cmd->data.color.g;
  2.1796 +                const Uint8 b = cmd->data.color.b;
  2.1797 +                const Uint8 a = cmd->data.color.a;
  2.1798 +                const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
  2.1799 +                if (color != data->drawstate.clear_color) {
  2.1800 +                    const GLfloat fr = ((GLfloat) colorswap ? b : r) * inv255f;
  2.1801 +                    const GLfloat fg = ((GLfloat) g) * inv255f;
  2.1802 +                    const GLfloat fb = ((GLfloat) colorswap ? r : b) * inv255f;
  2.1803 +                    const GLfloat fa = ((GLfloat) a) * inv255f;
  2.1804 +                    data->glClearColor(fr, fg, fb, fa);
  2.1805 +                    data->drawstate.clear_color = color;
  2.1806 +                }
  2.1807 +
  2.1808 +                if (data->drawstate.cliprect_enabled) {
  2.1809 +                    data->glDisable(GL_SCISSOR_TEST);
  2.1810 +                }
  2.1811 +
  2.1812 +                data->glClear(GL_COLOR_BUFFER_BIT);
  2.1813 +
  2.1814 +                if (data->drawstate.cliprect_enabled) {
  2.1815 +                    data->glEnable(GL_SCISSOR_TEST);
  2.1816 +                }
  2.1817 +                break;
  2.1818 +            }
  2.1819 +
  2.1820 +            case SDL_RENDERCMD_DRAW_POINTS: {
  2.1821 +                if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
  2.1822 +                    data->glDrawArrays(GL_POINTS, 0, cmd->data.draw.count);
  2.1823 +                }
  2.1824 +                break;
  2.1825 +            }
  2.1826 +
  2.1827 +            case SDL_RENDERCMD_DRAW_LINES: {
  2.1828 +                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
  2.1829 +                const size_t count = cmd->data.draw.count;
  2.1830 +                if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
  2.1831 +                    if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
  2.1832 +                        /* GL_LINE_LOOP takes care of the final segment */
  2.1833 +                        data->glDrawArrays(GL_LINE_LOOP, 0, count - 1);
  2.1834 +                    } else {
  2.1835 +                        data->glDrawArrays(GL_LINE_STRIP, 0, count);
  2.1836 +                        /* We need to close the endpoint of the line */
  2.1837 +                        data->glDrawArrays(GL_POINTS, count - 1, 1);
  2.1838 +                    }
  2.1839 +                }
  2.1840 +                break;
  2.1841 +            }
  2.1842 +
  2.1843 +            case SDL_RENDERCMD_FILL_RECTS: {
  2.1844 +                const size_t count = cmd->data.draw.count;
  2.1845 +                size_t offset = 0;
  2.1846 +                if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
  2.1847 +                    for (i = 0; i < count; ++i, offset += 4) {
  2.1848 +                        data->glDrawArrays(GL_TRIANGLE_STRIP, offset, 4);
  2.1849 +                    }
  2.1850 +                }
  2.1851 +                break;
  2.1852 +            }
  2.1853 +
  2.1854 +            case SDL_RENDERCMD_COPY:
  2.1855 +            case SDL_RENDERCMD_COPY_EX: {
  2.1856 +                if (SetCopyState(renderer, cmd) == 0) {
  2.1857 +                    data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  2.1858 +                }
  2.1859 +                break;
  2.1860 +            }
  2.1861 +
  2.1862 +            case SDL_RENDERCMD_NO_OP:
  2.1863 +                break;
  2.1864 +        }
  2.1865 +
  2.1866 +        cmd = cmd->next;
  2.1867 +    }
  2.1868 +
  2.1869 +    return GL_CheckError("", renderer);
  2.1870 +}
  2.1871 +
  2.1872 +static void
  2.1873 +GLES2_DestroyRenderer(SDL_Renderer *renderer)
  2.1874 +{
  2.1875 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  2.1876 +
  2.1877 +    /* Deallocate everything */
  2.1878 +    if (data) {
  2.1879 +        GLES2_ActivateRenderer(renderer);
  2.1880 +
  2.1881 +        {
  2.1882 +            GLES2_ShaderCacheEntry *entry;
  2.1883 +            GLES2_ShaderCacheEntry *next;
  2.1884 +            entry = data->shader_cache.head;
  2.1885 +            while (entry) {
  2.1886 +                data->glDeleteShader(entry->id);
  2.1887 +                next = entry->next;
  2.1888 +                SDL_free(entry);
  2.1889 +                entry = next;
  2.1890 +            }
  2.1891 +        }
  2.1892 +        {
  2.1893 +            GLES2_ProgramCacheEntry *entry;
  2.1894 +            GLES2_ProgramCacheEntry *next;
  2.1895 +            entry = data->program_cache.head;
  2.1896 +            while (entry) {
  2.1897 +                data->glDeleteProgram(entry->id);
  2.1898 +                next = entry->next;
  2.1899 +                SDL_free(entry);
  2.1900 +                entry = next;
  2.1901 +            }
  2.1902 +        }
  2.1903 +
  2.1904 +        if (data->context) {
  2.1905 +            while (data->framebuffers) {
  2.1906 +                GLES2_FBOList *nextnode = data->framebuffers->next;
  2.1907 +                data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
  2.1908 +                GL_CheckError("", renderer);
  2.1909 +                SDL_free(data->framebuffers);
  2.1910 +                data->framebuffers = nextnode;
  2.1911 +            }
  2.1912 +
  2.1913 +            data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
  2.1914 +            GL_CheckError("", renderer);
  2.1915 +
  2.1916 +            SDL_GL_DeleteContext(data->context);
  2.1917 +        }
  2.1918 +
  2.1919 +        SDL_free(data->shader_formats);
  2.1920 +        SDL_free(data);
  2.1921 +    }
  2.1922 +    SDL_free(renderer);
  2.1923 +}
  2.1924 +
  2.1925 +static int
  2.1926 +GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  2.1927 +{
  2.1928 +    GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->driverdata;
  2.1929 +    GLES2_TextureData *data;
  2.1930 +    GLenum format;
  2.1931 +    GLenum type;
  2.1932 +    GLenum scaleMode;
  2.1933 +
  2.1934 +    GLES2_ActivateRenderer(renderer);
  2.1935 +
  2.1936 +    /* Determine the corresponding GLES texture format params */
  2.1937 +    switch (texture->format)
  2.1938 +    {
  2.1939 +    case SDL_PIXELFORMAT_ARGB8888:
  2.1940 +    case SDL_PIXELFORMAT_ABGR8888:
  2.1941 +    case SDL_PIXELFORMAT_RGB888:
  2.1942 +    case SDL_PIXELFORMAT_BGR888:
  2.1943 +        format = GL_RGBA;
  2.1944 +        type = GL_UNSIGNED_BYTE;
  2.1945 +        break;
  2.1946 +    case SDL_PIXELFORMAT_IYUV:
  2.1947 +    case SDL_PIXELFORMAT_YV12:
  2.1948 +    case SDL_PIXELFORMAT_NV12:
  2.1949 +    case SDL_PIXELFORMAT_NV21:
  2.1950 +        format = GL_LUMINANCE;
  2.1951 +        type = GL_UNSIGNED_BYTE;
  2.1952 +        break;
  2.1953 +#ifdef GL_TEXTURE_EXTERNAL_OES
  2.1954 +    case SDL_PIXELFORMAT_EXTERNAL_OES:
  2.1955 +        format = GL_NONE;
  2.1956 +        type = GL_NONE;
  2.1957 +        break;
  2.1958 +#endif
  2.1959 +    default:
  2.1960 +        return SDL_SetError("Texture format not supported");
  2.1961 +    }
  2.1962 +
  2.1963 +    if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES &&
  2.1964 +        texture->access != SDL_TEXTUREACCESS_STATIC) {
  2.1965 +        return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES");
  2.1966 +    }
  2.1967 +
  2.1968 +    /* Allocate a texture struct */
  2.1969 +    data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
  2.1970 +    if (!data) {
  2.1971 +        return SDL_OutOfMemory();
  2.1972 +    }
  2.1973 +    data->texture = 0;
  2.1974 +#ifdef GL_TEXTURE_EXTERNAL_OES
  2.1975 +    data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
  2.1976 +#else
  2.1977 +    data->texture_type = GL_TEXTURE_2D;
  2.1978 +#endif
  2.1979 +    data->pixel_format = format;
  2.1980 +    data->pixel_type = type;
  2.1981 +    data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
  2.1982 +    data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
  2.1983 +    data->texture_u = 0;
  2.1984 +    data->texture_v = 0;
  2.1985 +    scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
  2.1986 +
  2.1987 +    /* Allocate a blob for image renderdata */
  2.1988 +    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
  2.1989 +        size_t size;
  2.1990 +        data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
  2.1991 +        size = texture->h * data->pitch;
  2.1992 +        if (data->yuv) {
  2.1993 +            /* Need to add size for the U and V planes */
  2.1994 +            size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
  2.1995 +        } else if (data->nv12) {
  2.1996 +            /* Need to add size for the U/V plane */
  2.1997 +            size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
  2.1998 +        }
  2.1999 +        data->pixel_data = SDL_calloc(1, size);
  2.2000 +        if (!data->pixel_data) {
  2.2001 +            SDL_free(data);
  2.2002 +            return SDL_OutOfMemory();
  2.2003 +        }
  2.2004 +    }
  2.2005 +
  2.2006 +    /* Allocate the texture */
  2.2007 +    GL_CheckError("", renderer);
  2.2008 +
  2.2009 +    if (data->yuv) {
  2.2010 +        renderdata->glGenTextures(1, &data->texture_v);
  2.2011 +        if (GL_CheckError("glGenTexures()", renderer) < 0) {
  2.2012 +            return -1;
  2.2013 +        }
  2.2014 +        renderdata->glActiveTexture(GL_TEXTURE2);
  2.2015 +        renderdata->glBindTexture(data->texture_type, data->texture_v);
  2.2016 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  2.2017 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  2.2018 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  2.2019 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  2.2020 +        renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
  2.2021 +
  2.2022 +        renderdata->glGenTextures(1, &data->texture_u);
  2.2023 +        if (GL_CheckError("glGenTexures()", renderer) < 0) {
  2.2024 +            return -1;
  2.2025 +        }
  2.2026 +        renderdata->glActiveTexture(GL_TEXTURE1);
  2.2027 +        renderdata->glBindTexture(data->texture_type, data->texture_u);
  2.2028 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  2.2029 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  2.2030 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  2.2031 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  2.2032 +        renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
  2.2033 +        if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  2.2034 +            return -1;
  2.2035 +        }
  2.2036 +    } else if (data->nv12) {
  2.2037 +        renderdata->glGenTextures(1, &data->texture_u);
  2.2038 +        if (GL_CheckError("glGenTexures()", renderer) < 0) {
  2.2039 +            return -1;
  2.2040 +        }
  2.2041 +        renderdata->glActiveTexture(GL_TEXTURE1);
  2.2042 +        renderdata->glBindTexture(data->texture_type, data->texture_u);
  2.2043 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  2.2044 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  2.2045 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  2.2046 +        renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  2.2047 +        renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
  2.2048 +        if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  2.2049 +            return -1;
  2.2050 +        }
  2.2051 +    }
  2.2052 +
  2.2053 +    renderdata->glGenTextures(1, &data->texture);
  2.2054 +    if (GL_CheckError("glGenTexures()", renderer) < 0) {
  2.2055 +        return -1;
  2.2056 +    }
  2.2057 +    texture->driverdata = data;
  2.2058 +    renderdata->glActiveTexture(GL_TEXTURE0);
  2.2059 +    renderdata->glBindTexture(data->texture_type, data->texture);
  2.2060 +    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  2.2061 +    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  2.2062 +    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  2.2063 +    renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  2.2064 +    if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
  2.2065 +        renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
  2.2066 +        if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  2.2067 +            return -1;
  2.2068 +        }
  2.2069 +    }
  2.2070 +
  2.2071 +    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  2.2072 +       data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
  2.2073 +    } else {
  2.2074 +       data->fbo = NULL;
  2.2075 +    }
  2.2076 +
  2.2077 +    return GL_CheckError("", renderer);
  2.2078 +}
  2.2079 +
  2.2080 +static int
  2.2081 +GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
  2.2082 +{
  2.2083 +    Uint8 *blob = NULL;
  2.2084 +    Uint8 *src;
  2.2085 +    int src_pitch;
  2.2086 +    int y;
  2.2087 +
  2.2088 +    if ((width == 0) || (height == 0) || (bpp == 0)) {
  2.2089 +        return 0;  /* nothing to do */
  2.2090 +    }
  2.2091 +
  2.2092 +    /* Reformat the texture data into a tightly packed array */
  2.2093 +    src_pitch = width * bpp;
  2.2094 +    src = (Uint8 *)pixels;
  2.2095 +    if (pitch != src_pitch) {
  2.2096 +        blob = (Uint8 *)SDL_malloc(src_pitch * height);
  2.2097 +        if (!blob) {
  2.2098 +            return SDL_OutOfMemory();
  2.2099 +        }
  2.2100 +        src = blob;
  2.2101 +        for (y = 0; y < height; ++y)
  2.2102 +        {
  2.2103 +            SDL_memcpy(src, pixels, src_pitch);
  2.2104 +            src += src_pitch;
  2.2105 +            pixels = (Uint8 *)pixels + pitch;
  2.2106 +        }
  2.2107 +        src = blob;
  2.2108 +    }
  2.2109 +
  2.2110 +    data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
  2.2111 +    if (blob) {
  2.2112 +        SDL_free(blob);
  2.2113 +    }
  2.2114 +    return 0;
  2.2115 +}
  2.2116 +
  2.2117 +static int
  2.2118 +GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  2.2119 +                    const void *pixels, int pitch)
  2.2120 +{
  2.2121 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  2.2122 +    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.2123 +
  2.2124 +    GLES2_ActivateRenderer(renderer);
  2.2125 +
  2.2126 +    /* Bail out if we're supposed to update an empty rectangle */
  2.2127 +    if (rect->w <= 0 || rect->h <= 0) {
  2.2128 +        return 0;
  2.2129 +    }
  2.2130 +
  2.2131 +    /* Create a texture subimage with the supplied data */
  2.2132 +    data->glBindTexture(tdata->texture_type, tdata->texture);
  2.2133 +    GLES2_TexSubImage2D(data, tdata->texture_type,
  2.2134 +                    rect->x,
  2.2135 +                    rect->y,
  2.2136 +                    rect->w,
  2.2137 +                    rect->h,
  2.2138 +                    tdata->pixel_format,
  2.2139 +                    tdata->pixel_type,
  2.2140 +                    pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
  2.2141 +
  2.2142 +    if (tdata->yuv) {
  2.2143 +        /* Skip to the correct offset into the next texture */
  2.2144 +        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
  2.2145 +        if (texture->format == SDL_PIXELFORMAT_YV12) {
  2.2146 +            data->glBindTexture(tdata->texture_type, tdata->texture_v);
  2.2147 +        } else {
  2.2148 +            data->glBindTexture(tdata->texture_type, tdata->texture_u);
  2.2149 +        }
  2.2150 +        GLES2_TexSubImage2D(data, tdata->texture_type,
  2.2151 +                rect->x / 2,
  2.2152 +                rect->y / 2,
  2.2153 +                (rect->w + 1) / 2,
  2.2154 +                (rect->h + 1) / 2,
  2.2155 +                tdata->pixel_format,
  2.2156 +                tdata->pixel_type,
  2.2157 +                pixels, (pitch + 1) / 2, 1);
  2.2158 +
  2.2159 +
  2.2160 +        /* Skip to the correct offset into the next texture */
  2.2161 +        pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2));
  2.2162 +        if (texture->format == SDL_PIXELFORMAT_YV12) {
  2.2163 +            data->glBindTexture(tdata->texture_type, tdata->texture_u);
  2.2164 +        } else {
  2.2165 +            data->glBindTexture(tdata->texture_type, tdata->texture_v);
  2.2166 +        }
  2.2167 +        GLES2_TexSubImage2D(data, tdata->texture_type,
  2.2168 +                rect->x / 2,
  2.2169 +                rect->y / 2,
  2.2170 +                (rect->w + 1) / 2,
  2.2171 +                (rect->h + 1) / 2,
  2.2172 +                tdata->pixel_format,
  2.2173 +                tdata->pixel_type,
  2.2174 +                pixels, (pitch + 1) / 2, 1);
  2.2175 +    } else if (tdata->nv12) {
  2.2176 +        /* Skip to the correct offset into the next texture */
  2.2177 +        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
  2.2178 +        data->glBindTexture(tdata->texture_type, tdata->texture_u);
  2.2179 +        GLES2_TexSubImage2D(data, tdata->texture_type,
  2.2180 +                rect->x / 2,
  2.2181 +                rect->y / 2,
  2.2182 +                (rect->w + 1) / 2,
  2.2183 +                (rect->h + 1) / 2,
  2.2184 +                GL_LUMINANCE_ALPHA,
  2.2185 +                GL_UNSIGNED_BYTE,
  2.2186 +                pixels, 2 * ((pitch + 1) / 2), 2);
  2.2187 +    }
  2.2188 +
  2.2189 +    return GL_CheckError("glTexSubImage2D()", renderer);
  2.2190 +}
  2.2191 +
  2.2192 +static int
  2.2193 +GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
  2.2194 +                    const SDL_Rect * rect,
  2.2195 +                    const Uint8 *Yplane, int Ypitch,
  2.2196 +                    const Uint8 *Uplane, int Upitch,
  2.2197 +                    const Uint8 *Vplane, int Vpitch)
  2.2198 +{
  2.2199 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  2.2200 +    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.2201 +
  2.2202 +    GLES2_ActivateRenderer(renderer);
  2.2203 +
  2.2204 +    /* Bail out if we're supposed to update an empty rectangle */
  2.2205 +    if (rect->w <= 0 || rect->h <= 0) {
  2.2206 +        return 0;
  2.2207 +    }
  2.2208 +
  2.2209 +    data->glBindTexture(tdata->texture_type, tdata->texture_v);
  2.2210 +    GLES2_TexSubImage2D(data, tdata->texture_type,
  2.2211 +                    rect->x / 2,
  2.2212 +                    rect->y / 2,
  2.2213 +                    (rect->w + 1) / 2,
  2.2214 +                    (rect->h + 1) / 2,
  2.2215 +                    tdata->pixel_format,
  2.2216 +                    tdata->pixel_type,
  2.2217 +                    Vplane, Vpitch, 1);
  2.2218 +
  2.2219 +    data->glBindTexture(tdata->texture_type, tdata->texture_u);
  2.2220 +    GLES2_TexSubImage2D(data, tdata->texture_type,
  2.2221 +                    rect->x / 2,
  2.2222 +                    rect->y / 2,
  2.2223 +                    (rect->w + 1) / 2,
  2.2224 +                    (rect->h + 1) / 2,
  2.2225 +                    tdata->pixel_format,
  2.2226 +                    tdata->pixel_type,
  2.2227 +                    Uplane, Upitch, 1);
  2.2228 +
  2.2229 +    data->glBindTexture(tdata->texture_type, tdata->texture);
  2.2230 +    GLES2_TexSubImage2D(data, tdata->texture_type,
  2.2231 +                    rect->x,
  2.2232 +                    rect->y,
  2.2233 +                    rect->w,
  2.2234 +                    rect->h,
  2.2235 +                    tdata->pixel_format,
  2.2236 +                    tdata->pixel_type,
  2.2237 +                    Yplane, Ypitch, 1);
  2.2238 +
  2.2239 +    return GL_CheckError("glTexSubImage2D()", renderer);
  2.2240 +}
  2.2241 +
  2.2242 +static int
  2.2243 +GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  2.2244 +                  void **pixels, int *pitch)
  2.2245 +{
  2.2246 +    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.2247 +
  2.2248 +    /* Retrieve the buffer/pitch for the specified region */
  2.2249 +    *pixels = (Uint8 *)tdata->pixel_data +
  2.2250 +              (tdata->pitch * rect->y) +
  2.2251 +              (rect->x * SDL_BYTESPERPIXEL(texture->format));
  2.2252 +    *pitch = tdata->pitch;
  2.2253  
  2.2254      return 0;
  2.2255  }
  2.2256  
  2.2257 -static int
  2.2258 -GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  2.2259 -                 const SDL_FRect *dstrect)
  2.2260 +static void
  2.2261 +GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  2.2262  {
  2.2263 -    GLfloat vertices[8];
  2.2264 -    int rc;
  2.2265 +    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.2266 +    SDL_Rect rect;
  2.2267  
  2.2268 -    /* Emit the textured quad */
  2.2269 -    vertices[0] = dstrect->x;
  2.2270 -    vertices[1] = dstrect->y;
  2.2271 -    vertices[2] = (dstrect->x + dstrect->w);
  2.2272 -    vertices[3] = dstrect->y;
  2.2273 -    vertices[4] = dstrect->x;
  2.2274 -    vertices[5] = (dstrect->y + dstrect->h);
  2.2275 -    vertices[6] = (dstrect->x + dstrect->w);
  2.2276 -    vertices[7] = (dstrect->y + dstrect->h);
  2.2277 -    rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
  2.2278 -
  2.2279 -    if (rc == 0) {
  2.2280 -        vertices[0] = srcrect->x / (GLfloat)texture->w;
  2.2281 -        vertices[1] = srcrect->y / (GLfloat)texture->h;
  2.2282 -        vertices[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  2.2283 -        vertices[3] = srcrect->y / (GLfloat)texture->h;
  2.2284 -        vertices[4] = srcrect->x / (GLfloat)texture->w;
  2.2285 -        vertices[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  2.2286 -        vertices[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  2.2287 -        vertices[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  2.2288 -        rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_TEXCOORD, vertices, 8);
  2.2289 -
  2.2290 -        if (rc == 0) {
  2.2291 -            rc = GLES2_AddCopyDrawCommand(renderer, texture, 0);
  2.2292 -        }
  2.2293 -    }
  2.2294 -
  2.2295 -    return rc;
  2.2296 +    /* We do whole texture updates, at least for now */
  2.2297 +    rect.x = 0;
  2.2298 +    rect.y = 0;
  2.2299 +    rect.w = texture->w;
  2.2300 +    rect.h = texture->h;
  2.2301 +    GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
  2.2302  }
  2.2303  
  2.2304  static int
  2.2305 -GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  2.2306 -                 const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
  2.2307 +GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
  2.2308  {
  2.2309 -    const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
  2.2310 -    GLfloat vertices[8];
  2.2311 -    int rc;
  2.2312 +    GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
  2.2313 +    GLES2_TextureData *texturedata = NULL;
  2.2314 +    GLenum status;
  2.2315  
  2.2316 -    vertices[0] = vertices[2] = vertices[4] = vertices[6] = (GLfloat)SDL_sin(radian_angle);
  2.2317 -    /* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
  2.2318 -    vertices[1] = vertices[3] = vertices[5] = vertices[7] = (GLfloat)SDL_cos(radian_angle) - 1.0f;
  2.2319 -    rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_ANGLE, vertices, 8);
  2.2320 -
  2.2321 -    /* Calculate the center of rotation */
  2.2322 -    if (rc == 0) {
  2.2323 -        vertices[0] = vertices[2] = vertices[4] = vertices[6] = (center->x + dstrect->x);
  2.2324 -        vertices[1] = vertices[3] = vertices[5] = vertices[7] = (center->y + dstrect->y);
  2.2325 -        rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_CENTER, vertices, 8);
  2.2326 -    
  2.2327 -        if (rc == 0) {
  2.2328 -            /* Emit the textured quad */
  2.2329 -            vertices[0] = dstrect->x;
  2.2330 -            vertices[1] = dstrect->y;
  2.2331 -            vertices[2] = (dstrect->x + dstrect->w);
  2.2332 -            vertices[3] = dstrect->y;
  2.2333 -            vertices[4] = dstrect->x;
  2.2334 -            vertices[5] = (dstrect->y + dstrect->h);
  2.2335 -            vertices[6] = (dstrect->x + dstrect->w);
  2.2336 -            vertices[7] = (dstrect->y + dstrect->h);
  2.2337 -            if (flip & SDL_FLIP_HORIZONTAL) {
  2.2338 -                const GLfloat tmp = vertices[0];
  2.2339 -                vertices[0] = vertices[4] = vertices[2];
  2.2340 -                vertices[2] = vertices[6] = tmp;
  2.2341 -            }
  2.2342 -            if (flip & SDL_FLIP_VERTICAL) {
  2.2343 -                const GLfloat tmp = vertices[1];
  2.2344 -                vertices[1] = vertices[3] = vertices[5];
  2.2345 -                vertices[5] = vertices[7] = tmp;
  2.2346 -            }
  2.2347 -            rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8);
  2.2348 -
  2.2349 -            if (rc == 0) {
  2.2350 -                vertices[0] = srcrect->x / (GLfloat)texture->w;
  2.2351 -                vertices[1] = srcrect->y / (GLfloat)texture->h;
  2.2352 -                vertices[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  2.2353 -                vertices[3] = srcrect->y / (GLfloat)texture->h;
  2.2354 -                vertices[4] = srcrect->x / (GLfloat)texture->w;
  2.2355 -                vertices[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  2.2356 -                vertices[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  2.2357 -                vertices[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  2.2358 -                rc = GLES2_AddVertices(renderer, GLES2_ATTRIBUTE_TEXCOORD, vertices, 8);
  2.2359 -
  2.2360 -                if (rc == 0) {
  2.2361 -                    GLES2_AddCopyDrawCommand(renderer, texture, (1 << GLES2_ATTRIBUTE_CENTER) | (1 << GLES2_ATTRIBUTE_ANGLE));
  2.2362 -                }
  2.2363 -            }
  2.2364 +    if (texture == NULL) {
  2.2365 +        data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
  2.2366 +    } else {
  2.2367 +        texturedata = (GLES2_TextureData *) texture->driverdata;
  2.2368 +        data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
  2.2369 +        /* TODO: check if texture pixel format allows this operation */
  2.2370 +        data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
  2.2371 +        /* Check FBO status */
  2.2372 +        status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
  2.2373 +        if (status != GL_FRAMEBUFFER_COMPLETE) {
  2.2374 +            return SDL_SetError("glFramebufferTexture2D() failed");
  2.2375          }
  2.2376      }
  2.2377 +    return 0;
  2.2378 +}
  2.2379  
  2.2380 -    return rc;
  2.2381 +static void
  2.2382 +GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  2.2383 +{
  2.2384 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  2.2385 +    GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  2.2386 +
  2.2387 +    GLES2_ActivateRenderer(renderer);
  2.2388 +
  2.2389 +    /* Destroy the texture */
  2.2390 +    if (tdata) {
  2.2391 +        data->glDeleteTextures(1, &tdata->texture);
  2.2392 +        if (tdata->texture_v) {
  2.2393 +            data->glDeleteTextures(1, &tdata->texture_v);
  2.2394 +        }
  2.2395 +        if (tdata->texture_u) {
  2.2396 +            data->glDeleteTextures(1, &tdata->texture_u);
  2.2397 +        }
  2.2398 +        SDL_free(tdata->pixel_data);
  2.2399 +        SDL_free(tdata);
  2.2400 +        texture->driverdata = NULL;
  2.2401 +    }
  2.2402  }
  2.2403  
  2.2404  static int
  2.2405  GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  2.2406                      Uint32 pixel_format, void * pixels, int pitch)
  2.2407  {
  2.2408 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.2409 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  2.2410      Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
  2.2411      size_t buflen;
  2.2412      void *temp_pixels;
  2.2413 @@ -2088,8 +1768,6 @@
  2.2414      int w, h, length, rows;
  2.2415      int status;
  2.2416  
  2.2417 -    GLES2_FlushCommands(renderer);  /* we need to render before we read the results. */
  2.2418 -
  2.2419      temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
  2.2420      buflen = (size_t) (rect->h * temp_pitch);
  2.2421      if (buflen == 0) {
  2.2422 @@ -2137,8 +1815,6 @@
  2.2423  static void
  2.2424  GLES2_RenderPresent(SDL_Renderer *renderer)
  2.2425  {
  2.2426 -    GLES2_FlushCommands(renderer);  /* time to send it to the GPU! */
  2.2427 -
  2.2428      /* Tell the video driver to swap buffers */
  2.2429      SDL_GL_SwapWindow(renderer->window);
  2.2430  }
  2.2431 @@ -2152,7 +1828,7 @@
  2.2432  
  2.2433  static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
  2.2434  {
  2.2435 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.2436 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  2.2437      GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  2.2438      GLES2_ActivateRenderer(renderer);
  2.2439  
  2.2440 @@ -2170,7 +1846,7 @@
  2.2441  
  2.2442  static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
  2.2443  {
  2.2444 -    GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  2.2445 +    GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  2.2446      GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  2.2447      GLES2_ActivateRenderer(renderer);
  2.2448  
  2.2449 @@ -2188,37 +1864,12 @@
  2.2450  #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
  2.2451  #endif
  2.2452  
  2.2453 -static void
  2.2454 -GLES2_ResetState(SDL_Renderer *renderer)
  2.2455 -{
  2.2456 -    GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
  2.2457 -
  2.2458 -    if (SDL_CurrentContext == data->context) {
  2.2459 -        GLES2_UpdateViewport(renderer);
  2.2460 -    } else {
  2.2461 -        GLES2_ActivateRenderer(renderer);
  2.2462 -    }
  2.2463 -
  2.2464 -    data->glActiveTexture(GL_TEXTURE0);
  2.2465 -    data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
  2.2466 -    data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  2.2467 -
  2.2468 -    data->glClearColor((GLfloat) data->clear_r * inv255f,
  2.2469 -                        (GLfloat) data->clear_g * inv255f,
  2.2470 -                        (GLfloat) data->clear_b * inv255f,
  2.2471 -                        (GLfloat) data->clear_a * inv255f);
  2.2472 -
  2.2473 -    data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
  2.2474 -    data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  2.2475 -
  2.2476 -    GL_CheckError("", renderer);
  2.2477 -}
  2.2478  
  2.2479  static SDL_Renderer *
  2.2480  GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
  2.2481  {
  2.2482      SDL_Renderer *renderer;
  2.2483 -    GLES2_DriverContext *data;
  2.2484 +    GLES2_RenderData *data;
  2.2485      GLint nFormats;
  2.2486  #ifndef ZUNE_HD
  2.2487      GLboolean hasCompiler;
  2.2488 @@ -2240,6 +1891,7 @@
  2.2489      }
  2.2490  
  2.2491      window_flags = SDL_GetWindowFlags(window);
  2.2492 +
  2.2493      /* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */
  2.2494      if (!(window_flags & SDL_WINDOW_OPENGL) ||
  2.2495          profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major < RENDERER_CONTEXT_MAJOR) {
  2.2496 @@ -2261,7 +1913,7 @@
  2.2497          goto error;
  2.2498      }
  2.2499  
  2.2500 -    data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext));
  2.2501 +    data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
  2.2502      if (!data) {
  2.2503          GLES2_DestroyRenderer(renderer);
  2.2504          SDL_OutOfMemory();
  2.2505 @@ -2272,15 +1924,6 @@
  2.2506      renderer->driverdata = data;
  2.2507      renderer->window = window;
  2.2508  
  2.2509 -    data->vertex_data_allocation = 512;
  2.2510 -    data->vertex_data = (GLfloat *) SDL_malloc(data->vertex_data_allocation * sizeof (GLfloat));
  2.2511 -    if (data->vertex_data == NULL) {
  2.2512 -        GLES2_DestroyRenderer(renderer);
  2.2513 -        SDL_OutOfMemory();
  2.2514 -        goto error;
  2.2515 -    }
  2.2516 -printf("malloc'd %p\n", data->vertex_data);
  2.2517 -
  2.2518      /* Create an OpenGL ES 2.0 context */
  2.2519      data->context = SDL_GL_CreateContext(window);
  2.2520      if (!data->context) {
  2.2521 @@ -2371,14 +2014,14 @@
  2.2522      renderer->LockTexture         = GLES2_LockTexture;
  2.2523      renderer->UnlockTexture       = GLES2_UnlockTexture;
  2.2524      renderer->SetRenderTarget     = GLES2_SetRenderTarget;
  2.2525 -    renderer->UpdateViewport      = GLES2_UpdateViewport;
  2.2526 -    renderer->UpdateClipRect      = GLES2_UpdateClipRect;
  2.2527 -    renderer->RenderClear         = GLES2_RenderClear;
  2.2528 -    renderer->RenderDrawPoints    = GLES2_RenderDrawPoints;
  2.2529 -    renderer->RenderDrawLines     = GLES2_RenderDrawLines;
  2.2530 -    renderer->RenderFillRects     = GLES2_RenderFillRects;
  2.2531 -    renderer->RenderCopy          = GLES2_RenderCopy;
  2.2532 -    renderer->RenderCopyEx        = GLES2_RenderCopyEx;
  2.2533 +    renderer->QueueSetViewport    = GLES2_QueueSetViewport;
  2.2534 +    renderer->QueueSetDrawColor   = GLES2_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
  2.2535 +    renderer->QueueDrawPoints     = GLES2_QueueDrawPoints;
  2.2536 +    renderer->QueueDrawLines      = GLES2_QueueDrawPoints;  /* lines and points queue vertices the same way. */
  2.2537 +    renderer->QueueFillRects      = GLES2_QueueFillRects;
  2.2538 +    renderer->QueueCopy           = GLES2_QueueCopy;
  2.2539 +    renderer->QueueCopyEx         = GLES2_QueueCopyEx;
  2.2540 +    renderer->RunCommandQueue     = GLES2_RunCommandQueue;
  2.2541      renderer->RenderReadPixels    = GLES2_RenderReadPixels;
  2.2542      renderer->RenderPresent       = GLES2_RenderPresent;
  2.2543      renderer->DestroyTexture      = GLES2_DestroyTexture;
  2.2544 @@ -2394,7 +2037,20 @@
  2.2545      renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_EXTERNAL_OES;
  2.2546  #endif
  2.2547  
  2.2548 -    GLES2_ResetState(renderer);
  2.2549 +    data->glActiveTexture(GL_TEXTURE0);
  2.2550 +    data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
  2.2551 +    data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  2.2552 +
  2.2553 +    data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
  2.2554 +    data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  2.2555 +
  2.2556 +    data->drawstate.blend = SDL_BLENDMODE_INVALID;
  2.2557 +    data->drawstate.color = 0xFFFFFFFF;
  2.2558 +    data->drawstate.clear_color = 0xFFFFFFFF;
  2.2559 +    data->drawstate.projection[3][0] = -1.0f;
  2.2560 +    data->drawstate.projection[3][3] = 1.0f;
  2.2561 +
  2.2562 +    GL_CheckError("", renderer);
  2.2563  
  2.2564      return renderer;
  2.2565  
  2.2566 @@ -2409,6 +2065,23 @@
  2.2567      return NULL;
  2.2568  }
  2.2569  
  2.2570 +SDL_RenderDriver GLES2_RenderDriver = {
  2.2571 +    GLES2_CreateRenderer,
  2.2572 +    {
  2.2573 +        "opengles2",
  2.2574 +        (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
  2.2575 +        4,
  2.2576 +        {
  2.2577 +        SDL_PIXELFORMAT_ARGB8888,
  2.2578 +        SDL_PIXELFORMAT_ABGR8888,
  2.2579 +        SDL_PIXELFORMAT_RGB888,
  2.2580 +        SDL_PIXELFORMAT_BGR888
  2.2581 +        },
  2.2582 +        0,
  2.2583 +        0
  2.2584 +    }
  2.2585 +};
  2.2586 +
  2.2587  #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
  2.2588  
  2.2589  /* vi: set ts=4 sw=4 expandtab: */