sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_render_gles2.c (76888B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
      4 
      5   This software is provided 'as-is', without any express or implied
      6   warranty.  In no event will the authors be held liable for any damages
      7   arising from the use of this software.
      8 
      9   Permission is granted to anyone to use this software for any purpose,
     10   including commercial applications, and to alter it and redistribute it
     11   freely, subject to the following restrictions:
     12 
     13   1. The origin of this software must not be misrepresented; you must not
     14      claim that you wrote the original software. If you use this software
     15      in a product, an acknowledgment in the product documentation would be
     16      appreciated but is not required.
     17   2. Altered source versions must be plainly marked as such, and must not be
     18      misrepresented as being the original software.
     19   3. This notice may not be removed or altered from any source distribution.
     20 */
     21 #include "../../SDL_internal.h"
     22 
     23 #if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED
     24 
     25 #include "SDL_hints.h"
     26 #include "SDL_opengles2.h"
     27 #include "../SDL_sysrender.h"
     28 #include "../../video/SDL_blit.h"
     29 #include "SDL_shaders_gles2.h"
     30 
     31 /* To prevent unnecessary window recreation,
     32  * these should match the defaults selected in SDL_GL_ResetAttributes
     33  */
     34 #define RENDERER_CONTEXT_MAJOR 2
     35 #define RENDERER_CONTEXT_MINOR 0
     36 
     37 /* Used to re-create the window with OpenGL ES capability */
     38 extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
     39 
     40 /*************************************************************************************************
     41  * Context structures                                                                            *
     42  *************************************************************************************************/
     43 
     44 typedef struct GLES2_FBOList GLES2_FBOList;
     45 
     46 struct GLES2_FBOList
     47 {
     48    Uint32 w, h;
     49    GLuint FBO;
     50    GLES2_FBOList *next;
     51 };
     52 
     53 typedef struct GLES2_TextureData
     54 {
     55     GLenum texture;
     56     GLenum texture_type;
     57     GLenum pixel_format;
     58     GLenum pixel_type;
     59     void *pixel_data;
     60     int pitch;
     61     /* YUV texture support */
     62     SDL_bool yuv;
     63     SDL_bool nv12;
     64     GLenum texture_v;
     65     GLenum texture_u;
     66     GLES2_FBOList *fbo;
     67 } GLES2_TextureData;
     68 
     69 typedef struct GLES2_ShaderCacheEntry
     70 {
     71     GLuint id;
     72     GLES2_ShaderType type;
     73     const GLES2_ShaderInstance *instance;
     74     int references;
     75     struct GLES2_ShaderCacheEntry *prev;
     76     struct GLES2_ShaderCacheEntry *next;
     77 } GLES2_ShaderCacheEntry;
     78 
     79 typedef struct GLES2_ShaderCache
     80 {
     81     int count;
     82     GLES2_ShaderCacheEntry *head;
     83 } GLES2_ShaderCache;
     84 
     85 typedef struct GLES2_ProgramCacheEntry
     86 {
     87     GLuint id;
     88     GLES2_ShaderCacheEntry *vertex_shader;
     89     GLES2_ShaderCacheEntry *fragment_shader;
     90     GLuint uniform_locations[16];
     91     Uint32 color;
     92     GLfloat projection[4][4];
     93     struct GLES2_ProgramCacheEntry *prev;
     94     struct GLES2_ProgramCacheEntry *next;
     95 } GLES2_ProgramCacheEntry;
     96 
     97 typedef struct GLES2_ProgramCache
     98 {
     99     int count;
    100     GLES2_ProgramCacheEntry *head;
    101     GLES2_ProgramCacheEntry *tail;
    102 } GLES2_ProgramCache;
    103 
    104 typedef enum
    105 {
    106     GLES2_ATTRIBUTE_POSITION = 0,
    107     GLES2_ATTRIBUTE_TEXCOORD = 1,
    108     GLES2_ATTRIBUTE_ANGLE = 2,
    109     GLES2_ATTRIBUTE_CENTER = 3,
    110 } GLES2_Attribute;
    111 
    112 typedef enum
    113 {
    114     GLES2_UNIFORM_PROJECTION,
    115     GLES2_UNIFORM_TEXTURE,
    116     GLES2_UNIFORM_COLOR,
    117     GLES2_UNIFORM_TEXTURE_U,
    118     GLES2_UNIFORM_TEXTURE_V
    119 } GLES2_Uniform;
    120 
    121 typedef enum
    122 {
    123     GLES2_IMAGESOURCE_INVALID,
    124     GLES2_IMAGESOURCE_SOLID,
    125     GLES2_IMAGESOURCE_TEXTURE_ABGR,
    126     GLES2_IMAGESOURCE_TEXTURE_ARGB,
    127     GLES2_IMAGESOURCE_TEXTURE_RGB,
    128     GLES2_IMAGESOURCE_TEXTURE_BGR,
    129     GLES2_IMAGESOURCE_TEXTURE_YUV,
    130     GLES2_IMAGESOURCE_TEXTURE_NV12,
    131     GLES2_IMAGESOURCE_TEXTURE_NV21,
    132     GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES
    133 } GLES2_ImageSource;
    134 
    135 typedef struct
    136 {
    137     SDL_Rect viewport;
    138     SDL_bool viewport_dirty;
    139     SDL_Texture *texture;
    140     SDL_Texture *target;
    141     SDL_BlendMode blend;
    142     SDL_bool cliprect_enabled_dirty;
    143     SDL_bool cliprect_enabled;
    144     SDL_bool cliprect_dirty;
    145     SDL_Rect cliprect;
    146     SDL_bool texturing;
    147     SDL_bool is_copy_ex;
    148     Uint32 color;
    149     Uint32 clear_color;
    150     int drawablew;
    151     int drawableh;
    152     GLES2_ProgramCacheEntry *program;
    153     GLfloat projection[4][4];
    154 } GLES2_DrawStateCache;
    155 
    156 typedef struct GLES2_RenderData
    157 {
    158     SDL_GLContext *context;
    159 
    160     SDL_bool debug_enabled;
    161 
    162 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
    163 #include "SDL_gles2funcs.h"
    164 #undef SDL_PROC
    165     GLES2_FBOList *framebuffers;
    166     GLuint window_framebuffer;
    167 
    168     int shader_format_count;
    169     GLenum *shader_formats;
    170     GLES2_ShaderCache shader_cache;
    171     GLES2_ProgramCache program_cache;
    172     Uint8 clear_r, clear_g, clear_b, clear_a;
    173 
    174     GLuint vertex_buffers[8];
    175     size_t vertex_buffer_size[8];
    176     int current_vertex_buffer;
    177     GLES2_DrawStateCache drawstate;
    178 } GLES2_RenderData;
    179 
    180 #define GLES2_MAX_CACHED_PROGRAMS 8
    181 
    182 static const float inv255f = 1.0f / 255.0f;
    183 
    184 
    185 SDL_FORCE_INLINE const char*
    186 GL_TranslateError (GLenum error)
    187 {
    188 #define GL_ERROR_TRANSLATE(e) case e: return #e;
    189     switch (error) {
    190     GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
    191     GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
    192     GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
    193     GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
    194     GL_ERROR_TRANSLATE(GL_NO_ERROR)
    195     default:
    196         return "UNKNOWN";
    197 }
    198 #undef GL_ERROR_TRANSLATE
    199 }
    200 
    201 SDL_FORCE_INLINE void
    202 GL_ClearErrors(SDL_Renderer *renderer)
    203 {
    204     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
    205 
    206     if (!data->debug_enabled) {
    207         return;
    208     }
    209     while (data->glGetError() != GL_NO_ERROR) {
    210         /* continue; */
    211     }
    212 }
    213 
    214 SDL_FORCE_INLINE int
    215 GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
    216 {
    217     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
    218     int ret = 0;
    219 
    220     if (!data->debug_enabled) {
    221         return 0;
    222     }
    223     /* check gl errors (can return multiple errors) */
    224     for (;;) {
    225         GLenum error = data->glGetError();
    226         if (error != GL_NO_ERROR) {
    227             if (prefix == NULL || prefix[0] == '\0') {
    228                 prefix = "generic";
    229             }
    230             SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
    231             ret = -1;
    232         } else {
    233             break;
    234         }
    235     }
    236     return ret;
    237 }
    238 
    239 #if 0
    240 #define GL_CheckError(prefix, renderer)
    241 #else
    242 #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION)
    243 #endif
    244 
    245 
    246 /*************************************************************************************************
    247  * Renderer state APIs                                                                           *
    248  *************************************************************************************************/
    249 
    250 static int GLES2_LoadFunctions(GLES2_RenderData * data)
    251 {
    252 #if SDL_VIDEO_DRIVER_UIKIT
    253 #define __SDL_NOGETPROCADDR__
    254 #elif SDL_VIDEO_DRIVER_ANDROID
    255 #define __SDL_NOGETPROCADDR__
    256 #elif SDL_VIDEO_DRIVER_PANDORA
    257 #define __SDL_NOGETPROCADDR__
    258 #endif
    259 
    260 #if defined __SDL_NOGETPROCADDR__
    261 #define SDL_PROC(ret,func,params) data->func=func;
    262 #else
    263 #define SDL_PROC(ret,func,params) \
    264     do { \
    265         data->func = SDL_GL_GetProcAddress(#func); \
    266         if ( ! data->func ) { \
    267             return SDL_SetError("Couldn't load GLES2 function %s: %s", #func, SDL_GetError()); \
    268         } \
    269     } while ( 0 );
    270 #endif /* __SDL_NOGETPROCADDR__ */
    271 
    272 #include "SDL_gles2funcs.h"
    273 #undef SDL_PROC
    274     return 0;
    275 }
    276 
    277 static GLES2_FBOList *
    278 GLES2_GetFBO(GLES2_RenderData *data, Uint32 w, Uint32 h)
    279 {
    280    GLES2_FBOList *result = data->framebuffers;
    281    while ((result) && ((result->w != w) || (result->h != h)) ) {
    282        result = result->next;
    283    }
    284    if (result == NULL) {
    285        result = SDL_malloc(sizeof(GLES2_FBOList));
    286        result->w = w;
    287        result->h = h;
    288        data->glGenFramebuffers(1, &result->FBO);
    289        result->next = data->framebuffers;
    290        data->framebuffers = result;
    291    }
    292    return result;
    293 }
    294 
    295 static int
    296 GLES2_ActivateRenderer(SDL_Renderer * renderer)
    297 {
    298     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
    299 
    300     if (SDL_GL_GetCurrentContext() != data->context) {
    301         /* Null out the current program to ensure we set it again */
    302         data->drawstate.program = NULL;
    303 
    304         if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
    305             return -1;
    306         }
    307     }
    308 
    309     GL_ClearErrors(renderer);
    310 
    311     return 0;
    312 }
    313 
    314 static void
    315 GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
    316 {
    317     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
    318 
    319     if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
    320         /* According to Apple documentation, we need to finish drawing NOW! */
    321         data->glFinish();
    322     }
    323 }
    324 
    325 static int
    326 GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
    327 {
    328     SDL_GL_GetDrawableSize(renderer->window, w, h);
    329     return 0;
    330 }
    331 
    332 static GLenum GetBlendFunc(SDL_BlendFactor factor)
    333 {
    334     switch (factor) {
    335     case SDL_BLENDFACTOR_ZERO:
    336         return GL_ZERO;
    337     case SDL_BLENDFACTOR_ONE:
    338         return GL_ONE;
    339     case SDL_BLENDFACTOR_SRC_COLOR:
    340         return GL_SRC_COLOR;
    341     case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
    342         return GL_ONE_MINUS_SRC_COLOR;
    343     case SDL_BLENDFACTOR_SRC_ALPHA:
    344         return GL_SRC_ALPHA;
    345     case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
    346         return GL_ONE_MINUS_SRC_ALPHA;
    347     case SDL_BLENDFACTOR_DST_COLOR:
    348         return GL_DST_COLOR;
    349     case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
    350         return GL_ONE_MINUS_DST_COLOR;
    351     case SDL_BLENDFACTOR_DST_ALPHA:
    352         return GL_DST_ALPHA;
    353     case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
    354         return GL_ONE_MINUS_DST_ALPHA;
    355     default:
    356         return GL_INVALID_ENUM;
    357     }
    358 }
    359 
    360 static GLenum GetBlendEquation(SDL_BlendOperation operation)
    361 {
    362     switch (operation) {
    363     case SDL_BLENDOPERATION_ADD:
    364         return GL_FUNC_ADD;
    365     case SDL_BLENDOPERATION_SUBTRACT:
    366         return GL_FUNC_SUBTRACT;
    367     case SDL_BLENDOPERATION_REV_SUBTRACT:
    368         return GL_FUNC_REVERSE_SUBTRACT;
    369     default:
    370         return GL_INVALID_ENUM;
    371     }
    372 }
    373 
    374 static SDL_bool
    375 GLES2_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
    376 {
    377     SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
    378     SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
    379     SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
    380     SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
    381     SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
    382     SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
    383 
    384     if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
    385         GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
    386         GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
    387         GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
    388         GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
    389         GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
    390         return SDL_FALSE;
    391     }
    392     return SDL_TRUE;
    393 }
    394 
    395 
    396 static void
    397 GLES2_EvictShader(GLES2_RenderData *data, GLES2_ShaderCacheEntry *entry)
    398 {
    399     /* Unlink the shader from the cache */
    400     if (entry->next) {
    401         entry->next->prev = entry->prev;
    402     }
    403     if (entry->prev) {
    404         entry->prev->next = entry->next;
    405     }
    406     if (data->shader_cache.head == entry) {
    407         data->shader_cache.head = entry->next;
    408     }
    409     --data->shader_cache.count;
    410 
    411     /* Deallocate the shader */
    412     data->glDeleteShader(entry->id);
    413     SDL_free(entry);
    414 }
    415 
    416 static GLES2_ProgramCacheEntry *
    417 GLES2_CacheProgram(GLES2_RenderData *data, GLES2_ShaderCacheEntry *vertex,
    418                    GLES2_ShaderCacheEntry *fragment)
    419 {
    420     GLES2_ProgramCacheEntry *entry;
    421     GLES2_ShaderCacheEntry *shaderEntry;
    422     GLint linkSuccessful;
    423 
    424     /* Check if we've already cached this program */
    425     entry = data->program_cache.head;
    426     while (entry) {
    427         if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) {
    428             break;
    429         }
    430         entry = entry->next;
    431     }
    432     if (entry) {
    433         if (data->program_cache.head != entry) {
    434             if (entry->next) {
    435                 entry->next->prev = entry->prev;
    436             }
    437             if (entry->prev) {
    438                 entry->prev->next = entry->next;
    439             }
    440             entry->prev = NULL;
    441             entry->next = data->program_cache.head;
    442             data->program_cache.head->prev = entry;
    443             data->program_cache.head = entry;
    444         }
    445         return entry;
    446     }
    447 
    448     /* Create a program cache entry */
    449     entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
    450     if (!entry) {
    451         SDL_OutOfMemory();
    452         return NULL;
    453     }
    454     entry->vertex_shader = vertex;
    455     entry->fragment_shader = fragment;
    456 
    457     /* Create the program and link it */
    458     entry->id = data->glCreateProgram();
    459     data->glAttachShader(entry->id, vertex->id);
    460     data->glAttachShader(entry->id, fragment->id);
    461     data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
    462     data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
    463     data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
    464     data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
    465     data->glLinkProgram(entry->id);
    466     data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
    467     if (!linkSuccessful) {
    468         data->glDeleteProgram(entry->id);
    469         SDL_free(entry);
    470         SDL_SetError("Failed to link shader program");
    471         return NULL;
    472     }
    473 
    474     /* Predetermine locations of uniform variables */
    475     entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
    476         data->glGetUniformLocation(entry->id, "u_projection");
    477     entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] =
    478         data->glGetUniformLocation(entry->id, "u_texture_v");
    479     entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] =
    480         data->glGetUniformLocation(entry->id, "u_texture_u");
    481     entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
    482         data->glGetUniformLocation(entry->id, "u_texture");
    483     entry->uniform_locations[GLES2_UNIFORM_COLOR] =
    484         data->glGetUniformLocation(entry->id, "u_color");
    485 
    486     entry->color = 0;
    487 
    488     data->glUseProgram(entry->id);
    489     if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] != -1) {
    490         data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2);  /* always texture unit 2. */
    491     }
    492     if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] != -1) {
    493         data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1);  /* always texture unit 1. */
    494     }
    495     if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE] != -1) {
    496         data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0);  /* always texture unit 0. */
    497     }
    498     if (entry->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
    499         data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
    500     }
    501     if (entry->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
    502         data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 0.0f, 0.0f, 0.0f, 0.0f);
    503     }
    504 
    505     /* Cache the linked program */
    506     if (data->program_cache.head) {
    507         entry->next = data->program_cache.head;
    508         data->program_cache.head->prev = entry;
    509     } else {
    510         data->program_cache.tail = entry;
    511     }
    512     data->program_cache.head = entry;
    513     ++data->program_cache.count;
    514 
    515     /* Increment the refcount of the shaders we're using */
    516     ++vertex->references;
    517     ++fragment->references;
    518 
    519     /* Evict the last entry from the cache if we exceed the limit */
    520     if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
    521         shaderEntry = data->program_cache.tail->vertex_shader;
    522         if (--shaderEntry->references <= 0) {
    523             GLES2_EvictShader(data, shaderEntry);
    524         }
    525         shaderEntry = data->program_cache.tail->fragment_shader;
    526         if (--shaderEntry->references <= 0) {
    527             GLES2_EvictShader(data, shaderEntry);
    528         }
    529         data->glDeleteProgram(data->program_cache.tail->id);
    530         data->program_cache.tail = data->program_cache.tail->prev;
    531         if (data->program_cache.tail != NULL) {
    532             SDL_free(data->program_cache.tail->next);
    533             data->program_cache.tail->next = NULL;
    534         }
    535         --data->program_cache.count;
    536     }
    537     return entry;
    538 }
    539 
    540 static GLES2_ShaderCacheEntry *
    541 GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type)
    542 {
    543     const GLES2_Shader *shader;
    544     const GLES2_ShaderInstance *instance = NULL;
    545     GLES2_ShaderCacheEntry *entry = NULL;
    546     GLint compileSuccessful = GL_FALSE;
    547     int i, j;
    548 
    549     /* Find the corresponding shader */
    550     shader = GLES2_GetShader(type);
    551     if (!shader) {
    552         SDL_SetError("No shader matching the requested characteristics was found");
    553         return NULL;
    554     }
    555 
    556     /* Find a matching shader instance that's supported on this hardware */
    557     for (i = 0; i < shader->instance_count && !instance; ++i) {
    558         for (j = 0; j < data->shader_format_count && !instance; ++j) {
    559             if (!shader->instances[i]) {
    560                 continue;
    561             }
    562             if (shader->instances[i]->format != data->shader_formats[j]) {
    563                 continue;
    564             }
    565             instance = shader->instances[i];
    566         }
    567     }
    568     if (!instance) {
    569         SDL_SetError("The specified shader cannot be loaded on the current platform");
    570         return NULL;
    571     }
    572 
    573     /* Check if we've already cached this shader */
    574     entry = data->shader_cache.head;
    575     while (entry) {
    576         if (entry->instance == instance) {
    577             break;
    578         }
    579         entry = entry->next;
    580     }
    581     if (entry) {
    582         return entry;
    583     }
    584 
    585     /* Create a shader cache entry */
    586     entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry));
    587     if (!entry) {
    588         SDL_OutOfMemory();
    589         return NULL;
    590     }
    591     entry->type = type;
    592     entry->instance = instance;
    593 
    594     /* Compile or load the selected shader instance */
    595     entry->id = data->glCreateShader(instance->type);
    596     if (instance->format == (GLenum)-1) {
    597         data->glShaderSource(entry->id, 1, (const char **)(char *)&instance->data, NULL);
    598         data->glCompileShader(entry->id);
    599         data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
    600     } else {
    601         data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
    602         compileSuccessful = GL_TRUE;
    603     }
    604     if (!compileSuccessful) {
    605         SDL_bool isstack = SDL_FALSE;
    606         char *info = NULL;
    607         int length = 0;
    608 
    609         data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
    610         if (length > 0) {
    611             info = SDL_small_alloc(char, length, &isstack);
    612             if (info) {
    613                 data->glGetShaderInfoLog(entry->id, length, &length, info);
    614             }
    615         }
    616         if (info) {
    617             SDL_SetError("Failed to load the shader: %s", info);
    618             SDL_small_free(info, isstack);
    619         } else {
    620             SDL_SetError("Failed to load the shader");
    621         }
    622         data->glDeleteShader(entry->id);
    623         SDL_free(entry);
    624         return NULL;
    625     }
    626 
    627     /* Link the shader entry in at the front of the cache */
    628     if (data->shader_cache.head) {
    629         entry->next = data->shader_cache.head;
    630         data->shader_cache.head->prev = entry;
    631     }
    632     data->shader_cache.head = entry;
    633     ++data->shader_cache.count;
    634     return entry;
    635 }
    636 
    637 static int
    638 GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int h)
    639 {
    640     GLES2_ShaderCacheEntry *vertex = NULL;
    641     GLES2_ShaderCacheEntry *fragment = NULL;
    642     GLES2_ShaderType vtype, ftype;
    643     GLES2_ProgramCacheEntry *program;
    644 
    645     /* Select an appropriate shader pair for the specified modes */
    646     vtype = GLES2_SHADER_VERTEX_DEFAULT;
    647     switch (source) {
    648     case GLES2_IMAGESOURCE_SOLID:
    649         ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
    650         break;
    651     case GLES2_IMAGESOURCE_TEXTURE_ABGR:
    652         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
    653         break;
    654     case GLES2_IMAGESOURCE_TEXTURE_ARGB:
    655         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
    656         break;
    657     case GLES2_IMAGESOURCE_TEXTURE_RGB:
    658         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
    659         break;
    660     case GLES2_IMAGESOURCE_TEXTURE_BGR:
    661         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
    662         break;
    663     case GLES2_IMAGESOURCE_TEXTURE_YUV:
    664         switch (SDL_GetYUVConversionModeForResolution(w, h)) {
    665         case SDL_YUV_CONVERSION_JPEG:
    666             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG_SRC;
    667             break;
    668         case SDL_YUV_CONVERSION_BT601:
    669             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601_SRC;
    670             break;
    671         case SDL_YUV_CONVERSION_BT709:
    672             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709_SRC;
    673             break;
    674         default:
    675             SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
    676             goto fault;
    677         }
    678         break;
    679     case GLES2_IMAGESOURCE_TEXTURE_NV12:
    680         switch (SDL_GetYUVConversionModeForResolution(w, h)) {
    681         case SDL_YUV_CONVERSION_JPEG:
    682             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG_SRC;
    683             break;
    684         case SDL_YUV_CONVERSION_BT601:
    685             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601_SRC;
    686             break;
    687         case SDL_YUV_CONVERSION_BT709:
    688             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709_SRC;
    689             break;
    690         default:
    691             SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
    692             goto fault;
    693         }
    694         break;
    695     case GLES2_IMAGESOURCE_TEXTURE_NV21:
    696         switch (SDL_GetYUVConversionModeForResolution(w, h)) {
    697         case SDL_YUV_CONVERSION_JPEG:
    698             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG_SRC;
    699             break;
    700         case SDL_YUV_CONVERSION_BT601:
    701             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601_SRC;
    702             break;
    703         case SDL_YUV_CONVERSION_BT709:
    704             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC;
    705             break;
    706         default:
    707             SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
    708             goto fault;
    709         }
    710         break;
    711     case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
    712         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC;
    713         break;
    714     default:
    715         goto fault;
    716     }
    717 
    718     /* Load the requested shaders */
    719     vertex = GLES2_CacheShader(data, vtype);
    720     if (!vertex) {
    721         goto fault;
    722     }
    723     fragment = GLES2_CacheShader(data, ftype);
    724     if (!fragment) {
    725         goto fault;
    726     }
    727 
    728     /* Check if we need to change programs at all */
    729     if (data->drawstate.program &&
    730         data->drawstate.program->vertex_shader == vertex &&
    731         data->drawstate.program->fragment_shader == fragment) {
    732         return 0;
    733     }
    734 
    735     /* Generate a matching program */
    736     program = GLES2_CacheProgram(data, vertex, fragment);
    737     if (!program) {
    738         goto fault;
    739     }
    740 
    741     /* Select that program in OpenGL */
    742     data->glUseProgram(program->id);
    743 
    744     /* Set the current program */
    745     data->drawstate.program = program;
    746 
    747     /* Clean up and return */
    748     return 0;
    749 fault:
    750     if (vertex && vertex->references <= 0) {
    751         GLES2_EvictShader(data, vertex);
    752     }
    753     if (fragment && fragment->references <= 0) {
    754         GLES2_EvictShader(data, fragment);
    755     }
    756     data->drawstate.program = NULL;
    757     return -1;
    758 }
    759 
    760 static int
    761 GLES2_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
    762 {
    763     return 0;  /* nothing to do in this backend. */
    764 }
    765 
    766 static int
    767 GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
    768 {
    769     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    770     int i;
    771 
    772     if (!verts) {
    773         return -1;
    774     }
    775 
    776     cmd->data.draw.count = count;
    777     for (i = 0; i < count; i++) {
    778         *(verts++) = 0.5f + points[i].x;
    779         *(verts++) = 0.5f + points[i].y;
    780     }
    781 
    782     return 0;
    783 }
    784 
    785 static int
    786 GLES2_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
    787 {
    788     int i;
    789     const size_t vertlen = (sizeof (GLfloat) * 2) * count;
    790     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, vertlen, 0, &cmd->data.draw.first);
    791     if (!verts) {
    792         return -1;
    793     }
    794     cmd->data.draw.count = count;
    795 
    796     /* Offset to hit the center of the pixel. */
    797     for (i = 0; i < count; i++) {
    798         *(verts++) = 0.5f + points[i].x;
    799         *(verts++) = 0.5f + points[i].y;
    800     }
    801 
    802     /* Make the last line segment one pixel longer, to satisfy the
    803        diamond-exit rule. */
    804     verts -= 4;
    805     {
    806         const GLfloat xstart = verts[0];
    807         const GLfloat ystart = verts[1];
    808         const GLfloat xend = verts[2];
    809         const GLfloat yend = verts[3];
    810 
    811         if (ystart == yend) {  /* horizontal line */
    812             verts[2] += (xend > xstart) ? 1.0f : -1.0f;
    813         } else if (xstart == xend) {  /* vertical line */
    814             verts[3] += (yend > ystart) ? 1.0f : -1.0f;
    815         } else {  /* bump a pixel in the direction we are moving in. */
    816             const GLfloat deltax = xend - xstart;
    817             const GLfloat deltay = yend - ystart;
    818             const GLfloat angle = SDL_atan2f(deltay, deltax);
    819             verts[2] += SDL_cosf(angle);
    820             verts[3] += SDL_sinf(angle);
    821         }
    822     }
    823 
    824     return 0;
    825 }
    826 
    827 static int
    828 GLES2_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
    829 {
    830     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    831     int i;
    832 
    833     if (!verts) {
    834         return -1;
    835     }
    836 
    837     cmd->data.draw.count = count;
    838 
    839     for (i = 0; i < count; i++) {
    840         const SDL_FRect *rect = &rects[i];
    841         const GLfloat minx = rect->x;
    842         const GLfloat maxx = rect->x + rect->w;
    843         const GLfloat miny = rect->y;
    844         const GLfloat maxy = rect->y + rect->h;
    845         *(verts++) = minx;
    846         *(verts++) = miny;
    847         *(verts++) = maxx;
    848         *(verts++) = miny;
    849         *(verts++) = minx;
    850         *(verts++) = maxy;
    851         *(verts++) = maxx;
    852         *(verts++) = maxy;
    853     }
    854 
    855     return 0;
    856 }
    857 
    858 static int
    859 GLES2_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
    860                           const SDL_Rect * srcrect, const SDL_FRect * dstrect)
    861 {
    862     GLfloat minx, miny, maxx, maxy;
    863     GLfloat minu, maxu, minv, maxv;
    864     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    865 
    866     if (!verts) {
    867         return -1;
    868     }
    869 
    870     cmd->data.draw.count = 1;
    871 
    872     minx = dstrect->x;
    873     miny = dstrect->y;
    874     maxx = dstrect->x + dstrect->w;
    875     maxy = dstrect->y + dstrect->h;
    876 
    877     minu = (GLfloat) srcrect->x / texture->w;
    878     maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
    879     minv = (GLfloat) srcrect->y / texture->h;
    880     maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
    881 
    882     *(verts++) = minx;
    883     *(verts++) = miny;
    884     *(verts++) = maxx;
    885     *(verts++) = miny;
    886     *(verts++) = minx;
    887     *(verts++) = maxy;
    888     *(verts++) = maxx;
    889     *(verts++) = maxy;
    890 
    891     *(verts++) = minu;
    892     *(verts++) = minv;
    893     *(verts++) = maxu;
    894     *(verts++) = minv;
    895     *(verts++) = minu;
    896     *(verts++) = maxv;
    897     *(verts++) = maxu;
    898     *(verts++) = maxv;
    899 
    900     return 0;
    901 }
    902 
    903 static int
    904 GLES2_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
    905                         const SDL_Rect * srcquad, const SDL_FRect * dstrect,
    906                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
    907 {
    908     /* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
    909     const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
    910     const GLfloat s = (GLfloat) SDL_sin(radian_angle);
    911     const GLfloat c = (GLfloat) SDL_cos(radian_angle) - 1.0f;
    912     const GLfloat centerx = center->x + dstrect->x;
    913     const GLfloat centery = center->y + dstrect->y;
    914     GLfloat minx, miny, maxx, maxy;
    915     GLfloat minu, maxu, minv, maxv;
    916     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 32 * sizeof (GLfloat), 0, &cmd->data.draw.first);
    917 
    918     if (!verts) {
    919         return -1;
    920     }
    921 
    922     if (flip & SDL_FLIP_HORIZONTAL) {
    923         minx = dstrect->x + dstrect->w;
    924         maxx = dstrect->x;
    925     } else {
    926         minx = dstrect->x;
    927         maxx = dstrect->x + dstrect->w;
    928     }
    929 
    930     if (flip & SDL_FLIP_VERTICAL) {
    931         miny = dstrect->y + dstrect->h;
    932         maxy = dstrect->y;
    933     } else {
    934         miny = dstrect->y;
    935         maxy = dstrect->y + dstrect->h;
    936     }
    937 
    938     minu = ((GLfloat) srcquad->x) / ((GLfloat) texture->w);
    939     maxu = ((GLfloat) (srcquad->x + srcquad->w)) / ((GLfloat) texture->w);
    940     minv = ((GLfloat) srcquad->y) / ((GLfloat) texture->h);
    941     maxv = ((GLfloat) (srcquad->y + srcquad->h)) / ((GLfloat) texture->h);
    942 
    943 
    944     cmd->data.draw.count = 1;
    945 
    946     *(verts++) = minx;
    947     *(verts++) = miny;
    948     *(verts++) = maxx;
    949     *(verts++) = miny;
    950     *(verts++) = minx;
    951     *(verts++) = maxy;
    952     *(verts++) = maxx;
    953     *(verts++) = maxy;
    954 
    955     *(verts++) = minu;
    956     *(verts++) = minv;
    957     *(verts++) = maxu;
    958     *(verts++) = minv;
    959     *(verts++) = minu;
    960     *(verts++) = maxv;
    961     *(verts++) = maxu;
    962     *(verts++) = maxv;
    963 
    964     *(verts++) = s;
    965     *(verts++) = c;
    966     *(verts++) = s;
    967     *(verts++) = c;
    968     *(verts++) = s;
    969     *(verts++) = c;
    970     *(verts++) = s;
    971     *(verts++) = c;
    972 
    973     *(verts++) = centerx;
    974     *(verts++) = centery;
    975     *(verts++) = centerx;
    976     *(verts++) = centery;
    977     *(verts++) = centerx;
    978     *(verts++) = centery;
    979     *(verts++) = centerx;
    980     *(verts++) = centery;
    981 
    982     return 0;
    983 }
    984 
    985 static int
    986 SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc)
    987 {
    988     const SDL_bool was_copy_ex = data->drawstate.is_copy_ex;
    989     const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX);
    990     SDL_Texture *texture = cmd->data.draw.texture;
    991     const SDL_BlendMode blend = cmd->data.draw.blend;
    992     GLES2_ProgramCacheEntry *program;
    993 
    994     SDL_assert((texture != NULL) == (imgsrc != GLES2_IMAGESOURCE_SOLID));
    995 
    996     if (data->drawstate.viewport_dirty) {
    997         const SDL_Rect *viewport = &data->drawstate.viewport;
    998         data->glViewport(viewport->x,
    999                          data->drawstate.target ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
   1000                          viewport->w, viewport->h);
   1001         if (viewport->w && viewport->h) {
   1002             data->drawstate.projection[0][0] = 2.0f / viewport->w;
   1003             data->drawstate.projection[1][1] = (data->drawstate.target ? 2.0f : -2.0f) / viewport->h;
   1004             data->drawstate.projection[3][1] = data->drawstate.target ? -1.0f : 1.0f;
   1005         }
   1006         data->drawstate.viewport_dirty = SDL_FALSE;
   1007     }
   1008 
   1009     if (data->drawstate.cliprect_enabled_dirty) {
   1010         if (!data->drawstate.cliprect_enabled) {
   1011             data->glDisable(GL_SCISSOR_TEST);
   1012         } else {
   1013             data->glEnable(GL_SCISSOR_TEST);
   1014         }
   1015         data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
   1016     }
   1017 
   1018     if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
   1019         const SDL_Rect *viewport = &data->drawstate.viewport;
   1020         const SDL_Rect *rect = &data->drawstate.cliprect;
   1021         data->glScissor(viewport->x + rect->x,
   1022                         data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
   1023                         rect->w, rect->h);
   1024         data->drawstate.cliprect_dirty = SDL_FALSE;
   1025     }
   1026 
   1027     if (texture != data->drawstate.texture) {
   1028         if ((texture != NULL) != data->drawstate.texturing) {
   1029             if (texture == NULL) {
   1030                 data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
   1031                 data->drawstate.texturing = SDL_FALSE;
   1032             } else {
   1033                 data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
   1034                 data->drawstate.texturing = SDL_TRUE;
   1035             }
   1036         }
   1037 
   1038         if (texture) {
   1039             GLES2_TextureData *tdata = (GLES2_TextureData *) texture->driverdata;
   1040             if (tdata->yuv) {
   1041                 data->glActiveTexture(GL_TEXTURE2);
   1042                 data->glBindTexture(tdata->texture_type, tdata->texture_v);
   1043 
   1044                 data->glActiveTexture(GL_TEXTURE1);
   1045                 data->glBindTexture(tdata->texture_type, tdata->texture_u);
   1046 
   1047                 data->glActiveTexture(GL_TEXTURE0);
   1048             } else if (tdata->nv12) {
   1049                 data->glActiveTexture(GL_TEXTURE1);
   1050                 data->glBindTexture(tdata->texture_type, tdata->texture_u);
   1051 
   1052                 data->glActiveTexture(GL_TEXTURE0);
   1053             }
   1054             data->glBindTexture(tdata->texture_type, tdata->texture);
   1055         }
   1056 
   1057         data->drawstate.texture = texture;
   1058     }
   1059 
   1060     if (texture) {
   1061         data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 8)));
   1062     }
   1063 
   1064     if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
   1065         return -1;
   1066     }
   1067 
   1068     program = data->drawstate.program;
   1069 
   1070     if (program->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
   1071         if (SDL_memcmp(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)) != 0) {
   1072             data->glUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection);
   1073             SDL_memcpy(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection));
   1074         }
   1075     }
   1076 
   1077     if (program->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
   1078         if (data->drawstate.color != program->color) {
   1079             const Uint8 r = (data->drawstate.color >> 16) & 0xFF;
   1080             const Uint8 g = (data->drawstate.color >> 8) & 0xFF;
   1081             const Uint8 b = (data->drawstate.color >> 0) & 0xFF;
   1082             const Uint8 a = (data->drawstate.color >> 24) & 0xFF;
   1083             data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
   1084             program->color = data->drawstate.color;
   1085         }
   1086     }
   1087 
   1088     if (blend != data->drawstate.blend) {
   1089         if (blend == SDL_BLENDMODE_NONE) {
   1090             data->glDisable(GL_BLEND);
   1091         } else {
   1092             data->glEnable(GL_BLEND);
   1093             data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
   1094                                       GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
   1095                                       GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
   1096                                       GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
   1097             data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
   1098                                           GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
   1099         }
   1100         data->drawstate.blend = blend;
   1101     }
   1102 
   1103     /* all drawing commands use this */
   1104     data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first);
   1105 
   1106     if (is_copy_ex != was_copy_ex) {
   1107         if (is_copy_ex) {
   1108             data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
   1109             data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
   1110         } else {
   1111             data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
   1112             data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
   1113         }
   1114         data->drawstate.is_copy_ex = is_copy_ex;
   1115     }
   1116 
   1117     if (is_copy_ex) {
   1118         data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 16)));
   1119         data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 24)));
   1120     }
   1121 
   1122     return 0;
   1123 }
   1124 
   1125 static int
   1126 SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
   1127 {
   1128     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
   1129     GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
   1130     SDL_Texture *texture = cmd->data.draw.texture;
   1131 
   1132     /* Pick an appropriate shader */
   1133     if (renderer->target) {
   1134         /* Check if we need to do color mapping between the source and render target textures */
   1135         if (renderer->target->format != texture->format) {
   1136             switch (texture->format) {
   1137             case SDL_PIXELFORMAT_ARGB8888:
   1138                 switch (renderer->target->format) {
   1139                 case SDL_PIXELFORMAT_ABGR8888:
   1140                 case SDL_PIXELFORMAT_BGR888:
   1141                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   1142                     break;
   1143                 case SDL_PIXELFORMAT_RGB888:
   1144                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
   1145                     break;
   1146                 }
   1147                 break;
   1148             case SDL_PIXELFORMAT_ABGR8888:
   1149                 switch (renderer->target->format) {
   1150                 case SDL_PIXELFORMAT_ARGB8888:
   1151                 case SDL_PIXELFORMAT_RGB888:
   1152                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   1153                     break;
   1154                 case SDL_PIXELFORMAT_BGR888:
   1155                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
   1156                     break;
   1157                 }
   1158                 break;
   1159             case SDL_PIXELFORMAT_RGB888:
   1160                 switch (renderer->target->format) {
   1161                 case SDL_PIXELFORMAT_ABGR8888:
   1162                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   1163                     break;
   1164                 case SDL_PIXELFORMAT_ARGB8888:
   1165                     sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
   1166                     break;
   1167                 case SDL_PIXELFORMAT_BGR888:
   1168                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   1169                     break;
   1170                 }
   1171                 break;
   1172             case SDL_PIXELFORMAT_BGR888:
   1173                 switch (renderer->target->format) {
   1174                 case SDL_PIXELFORMAT_ABGR8888:
   1175                     sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
   1176                     break;
   1177                 case SDL_PIXELFORMAT_ARGB8888:
   1178                     sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
   1179                     break;
   1180                 case SDL_PIXELFORMAT_RGB888:
   1181                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   1182                     break;
   1183                 }
   1184                 break;
   1185             case SDL_PIXELFORMAT_IYUV:
   1186             case SDL_PIXELFORMAT_YV12:
   1187                 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
   1188                 break;
   1189             case SDL_PIXELFORMAT_NV12:
   1190                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
   1191                 break;
   1192             case SDL_PIXELFORMAT_NV21:
   1193                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
   1194                 break;
   1195             case SDL_PIXELFORMAT_EXTERNAL_OES:
   1196                 sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
   1197                 break;
   1198             default:
   1199                 return SDL_SetError("Unsupported texture format");
   1200             }
   1201         } else {
   1202             sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;   /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
   1203         }
   1204     } else {
   1205         switch (texture->format) {
   1206             case SDL_PIXELFORMAT_ARGB8888:
   1207                 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
   1208                 break;
   1209             case SDL_PIXELFORMAT_ABGR8888:
   1210                 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
   1211                 break;
   1212             case SDL_PIXELFORMAT_RGB888:
   1213                 sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
   1214                 break;
   1215             case SDL_PIXELFORMAT_BGR888:
   1216                 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
   1217                 break;
   1218             case SDL_PIXELFORMAT_IYUV:
   1219             case SDL_PIXELFORMAT_YV12:
   1220                 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
   1221                 break;
   1222             case SDL_PIXELFORMAT_NV12:
   1223                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
   1224                 break;
   1225             case SDL_PIXELFORMAT_NV21:
   1226                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
   1227                 break;
   1228             case SDL_PIXELFORMAT_EXTERNAL_OES:
   1229                 sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
   1230                 break;
   1231             default:
   1232                 return SDL_SetError("Unsupported texture format");
   1233         }
   1234     }
   1235 
   1236     return SetDrawState(data, cmd, sourceType);
   1237 }
   1238 
   1239 static int
   1240 GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
   1241 {
   1242     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
   1243     const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
   1244     const int vboidx = data->current_vertex_buffer;
   1245     const GLuint vbo = data->vertex_buffers[vboidx];
   1246     size_t i;
   1247 
   1248     if (GLES2_ActivateRenderer(renderer) < 0) {
   1249         return -1;
   1250     }
   1251 
   1252     data->drawstate.target = renderer->target;
   1253     if (!data->drawstate.target) {
   1254         SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
   1255     }
   1256 
   1257     /* upload the new VBO data for this set of commands. */
   1258     data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
   1259     if (data->vertex_buffer_size[vboidx] < vertsize) {
   1260         data->glBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_STREAM_DRAW);
   1261         data->vertex_buffer_size[vboidx] = vertsize;
   1262     } else {
   1263         data->glBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices);
   1264     }
   1265 
   1266     /* cycle through a few VBOs so the GL has some time with the data before we replace it. */
   1267     data->current_vertex_buffer++;
   1268     if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
   1269         data->current_vertex_buffer = 0;
   1270     }
   1271 
   1272     while (cmd) {
   1273         switch (cmd->command) {
   1274             case SDL_RENDERCMD_SETDRAWCOLOR: {
   1275                 const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
   1276                 const Uint8 g = cmd->data.color.g;
   1277                 const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
   1278                 const Uint8 a = cmd->data.color.a;
   1279                 data->drawstate.color = ((a << 24) | (r << 16) | (g << 8) | b);
   1280                 break;
   1281             }
   1282 
   1283             case SDL_RENDERCMD_SETVIEWPORT: {
   1284                 SDL_Rect *viewport = &data->drawstate.viewport;
   1285                 if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
   1286                     SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
   1287                     data->drawstate.viewport_dirty = SDL_TRUE;
   1288                 }
   1289                 break;
   1290             }
   1291 
   1292             case SDL_RENDERCMD_SETCLIPRECT: {
   1293                 const SDL_Rect *rect = &cmd->data.cliprect.rect;
   1294                 if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
   1295                     data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
   1296                     data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
   1297                 }
   1298 
   1299                 if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
   1300                     SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
   1301                     data->drawstate.cliprect_dirty = SDL_TRUE;
   1302                 }
   1303                 break;
   1304             }
   1305 
   1306             case SDL_RENDERCMD_CLEAR: {
   1307                 const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
   1308                 const Uint8 g = cmd->data.color.g;
   1309                 const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
   1310                 const Uint8 a = cmd->data.color.a;
   1311                 const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
   1312                 if (color != data->drawstate.clear_color) {
   1313                     const GLfloat fr = ((GLfloat) r) * inv255f;
   1314                     const GLfloat fg = ((GLfloat) g) * inv255f;
   1315                     const GLfloat fb = ((GLfloat) b) * inv255f;
   1316                     const GLfloat fa = ((GLfloat) a) * inv255f;
   1317                     data->glClearColor(fr, fg, fb, fa);
   1318                     data->drawstate.clear_color = color;
   1319                 }
   1320 
   1321                 if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
   1322                     data->glDisable(GL_SCISSOR_TEST);
   1323                     data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
   1324                 }
   1325 
   1326                 data->glClear(GL_COLOR_BUFFER_BIT);
   1327                 break;
   1328             }
   1329 
   1330             case SDL_RENDERCMD_DRAW_POINTS: {
   1331                 if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
   1332                     data->glDrawArrays(GL_POINTS, 0, (GLsizei) cmd->data.draw.count);
   1333                 }
   1334                 break;
   1335             }
   1336 
   1337             case SDL_RENDERCMD_DRAW_LINES: {
   1338                 const size_t count = cmd->data.draw.count;
   1339                 SDL_assert(count >= 2);
   1340                 if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
   1341                     data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
   1342                 }
   1343                 break;
   1344             }
   1345 
   1346             case SDL_RENDERCMD_FILL_RECTS: {
   1347                 const size_t count = cmd->data.draw.count;
   1348                 size_t offset = 0;
   1349                 if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
   1350                     for (i = 0; i < count; ++i, offset += 4) {
   1351                         data->glDrawArrays(GL_TRIANGLE_STRIP, (GLsizei) offset, 4);
   1352                     }
   1353                 }
   1354                 break;
   1355             }
   1356 
   1357             case SDL_RENDERCMD_COPY:
   1358             case SDL_RENDERCMD_COPY_EX: {
   1359                 if (SetCopyState(renderer, cmd) == 0) {
   1360                     data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   1361                 }
   1362                 break;
   1363             }
   1364 
   1365             case SDL_RENDERCMD_NO_OP:
   1366                 break;
   1367         }
   1368 
   1369         cmd = cmd->next;
   1370     }
   1371 
   1372     return GL_CheckError("", renderer);
   1373 }
   1374 
   1375 static void
   1376 GLES2_DestroyRenderer(SDL_Renderer *renderer)
   1377 {
   1378     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   1379 
   1380     /* Deallocate everything */
   1381     if (data) {
   1382         GLES2_ActivateRenderer(renderer);
   1383 
   1384         {
   1385             GLES2_ShaderCacheEntry *entry;
   1386             GLES2_ShaderCacheEntry *next;
   1387             entry = data->shader_cache.head;
   1388             while (entry) {
   1389                 data->glDeleteShader(entry->id);
   1390                 next = entry->next;
   1391                 SDL_free(entry);
   1392                 entry = next;
   1393             }
   1394         }
   1395         {
   1396             GLES2_ProgramCacheEntry *entry;
   1397             GLES2_ProgramCacheEntry *next;
   1398             entry = data->program_cache.head;
   1399             while (entry) {
   1400                 data->glDeleteProgram(entry->id);
   1401                 next = entry->next;
   1402                 SDL_free(entry);
   1403                 entry = next;
   1404             }
   1405         }
   1406 
   1407         if (data->context) {
   1408             while (data->framebuffers) {
   1409                 GLES2_FBOList *nextnode = data->framebuffers->next;
   1410                 data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
   1411                 GL_CheckError("", renderer);
   1412                 SDL_free(data->framebuffers);
   1413                 data->framebuffers = nextnode;
   1414             }
   1415 
   1416             data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
   1417             GL_CheckError("", renderer);
   1418 
   1419             SDL_GL_DeleteContext(data->context);
   1420         }
   1421 
   1422         SDL_free(data->shader_formats);
   1423         SDL_free(data);
   1424     }
   1425     SDL_free(renderer);
   1426 }
   1427 
   1428 static int
   1429 GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
   1430 {
   1431     GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->driverdata;
   1432     GLES2_TextureData *data;
   1433     GLenum format;
   1434     GLenum type;
   1435     GLenum scaleMode;
   1436 
   1437     GLES2_ActivateRenderer(renderer);
   1438 
   1439     renderdata->drawstate.texture = NULL;  /* we trash this state. */
   1440 
   1441     /* Determine the corresponding GLES texture format params */
   1442     switch (texture->format)
   1443     {
   1444     case SDL_PIXELFORMAT_ARGB8888:
   1445     case SDL_PIXELFORMAT_ABGR8888:
   1446     case SDL_PIXELFORMAT_RGB888:
   1447     case SDL_PIXELFORMAT_BGR888:
   1448         format = GL_RGBA;
   1449         type = GL_UNSIGNED_BYTE;
   1450         break;
   1451     case SDL_PIXELFORMAT_IYUV:
   1452     case SDL_PIXELFORMAT_YV12:
   1453     case SDL_PIXELFORMAT_NV12:
   1454     case SDL_PIXELFORMAT_NV21:
   1455         format = GL_LUMINANCE;
   1456         type = GL_UNSIGNED_BYTE;
   1457         break;
   1458 #ifdef GL_TEXTURE_EXTERNAL_OES
   1459     case SDL_PIXELFORMAT_EXTERNAL_OES:
   1460         format = GL_NONE;
   1461         type = GL_NONE;
   1462         break;
   1463 #endif
   1464     default:
   1465         return SDL_SetError("Texture format not supported");
   1466     }
   1467 
   1468     if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES &&
   1469         texture->access != SDL_TEXTUREACCESS_STATIC) {
   1470         return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES");
   1471     }
   1472 
   1473     /* Allocate a texture struct */
   1474     data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
   1475     if (!data) {
   1476         return SDL_OutOfMemory();
   1477     }
   1478     data->texture = 0;
   1479 #ifdef GL_TEXTURE_EXTERNAL_OES
   1480     data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
   1481 #else
   1482     data->texture_type = GL_TEXTURE_2D;
   1483 #endif
   1484     data->pixel_format = format;
   1485     data->pixel_type = type;
   1486     data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
   1487     data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
   1488     data->texture_u = 0;
   1489     data->texture_v = 0;
   1490     scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
   1491 
   1492     /* Allocate a blob for image renderdata */
   1493     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   1494         size_t size;
   1495         data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
   1496         size = texture->h * data->pitch;
   1497         if (data->yuv) {
   1498             /* Need to add size for the U and V planes */
   1499             size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
   1500         } else if (data->nv12) {
   1501             /* Need to add size for the U/V plane */
   1502             size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
   1503         }
   1504         data->pixel_data = SDL_calloc(1, size);
   1505         if (!data->pixel_data) {
   1506             SDL_free(data);
   1507             return SDL_OutOfMemory();
   1508         }
   1509     }
   1510 
   1511     /* Allocate the texture */
   1512     GL_CheckError("", renderer);
   1513 
   1514     if (data->yuv) {
   1515         renderdata->glGenTextures(1, &data->texture_v);
   1516         if (GL_CheckError("glGenTexures()", renderer) < 0) {
   1517             return -1;
   1518         }
   1519         renderdata->glActiveTexture(GL_TEXTURE2);
   1520         renderdata->glBindTexture(data->texture_type, data->texture_v);
   1521         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   1522         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   1523         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   1524         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   1525         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
   1526 
   1527         renderdata->glGenTextures(1, &data->texture_u);
   1528         if (GL_CheckError("glGenTexures()", renderer) < 0) {
   1529             return -1;
   1530         }
   1531         renderdata->glActiveTexture(GL_TEXTURE1);
   1532         renderdata->glBindTexture(data->texture_type, data->texture_u);
   1533         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   1534         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   1535         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   1536         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   1537         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
   1538         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   1539             return -1;
   1540         }
   1541     } else if (data->nv12) {
   1542         renderdata->glGenTextures(1, &data->texture_u);
   1543         if (GL_CheckError("glGenTexures()", renderer) < 0) {
   1544             return -1;
   1545         }
   1546         renderdata->glActiveTexture(GL_TEXTURE1);
   1547         renderdata->glBindTexture(data->texture_type, data->texture_u);
   1548         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   1549         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   1550         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   1551         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   1552         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);
   1553         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   1554             return -1;
   1555         }
   1556     }
   1557 
   1558     renderdata->glGenTextures(1, &data->texture);
   1559     if (GL_CheckError("glGenTexures()", renderer) < 0) {
   1560         return -1;
   1561     }
   1562     texture->driverdata = data;
   1563     renderdata->glActiveTexture(GL_TEXTURE0);
   1564     renderdata->glBindTexture(data->texture_type, data->texture);
   1565     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
   1566     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
   1567     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   1568     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   1569     if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
   1570         renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
   1571         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
   1572             return -1;
   1573         }
   1574     }
   1575 
   1576     if (texture->access == SDL_TEXTUREACCESS_TARGET) {
   1577        data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
   1578     } else {
   1579        data->fbo = NULL;
   1580     }
   1581 
   1582     return GL_CheckError("", renderer);
   1583 }
   1584 
   1585 static int
   1586 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)
   1587 {
   1588     Uint8 *blob = NULL;
   1589     Uint8 *src;
   1590     int src_pitch;
   1591     int y;
   1592 
   1593     if ((width == 0) || (height == 0) || (bpp == 0)) {
   1594         return 0;  /* nothing to do */
   1595     }
   1596 
   1597     /* Reformat the texture data into a tightly packed array */
   1598     src_pitch = width * bpp;
   1599     src = (Uint8 *)pixels;
   1600     if (pitch != src_pitch) {
   1601         blob = (Uint8 *)SDL_malloc(src_pitch * height);
   1602         if (!blob) {
   1603             return SDL_OutOfMemory();
   1604         }
   1605         src = blob;
   1606         for (y = 0; y < height; ++y)
   1607         {
   1608             SDL_memcpy(src, pixels, src_pitch);
   1609             src += src_pitch;
   1610             pixels = (Uint8 *)pixels + pitch;
   1611         }
   1612         src = blob;
   1613     }
   1614 
   1615     data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
   1616     if (blob) {
   1617         SDL_free(blob);
   1618     }
   1619     return 0;
   1620 }
   1621 
   1622 static int
   1623 GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
   1624                     const void *pixels, int pitch)
   1625 {
   1626     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   1627     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   1628 
   1629     GLES2_ActivateRenderer(renderer);
   1630 
   1631     /* Bail out if we're supposed to update an empty rectangle */
   1632     if (rect->w <= 0 || rect->h <= 0) {
   1633         return 0;
   1634     }
   1635 
   1636     data->drawstate.texture = NULL;  /* we trash this state. */
   1637 
   1638     /* Create a texture subimage with the supplied data */
   1639     data->glBindTexture(tdata->texture_type, tdata->texture);
   1640     GLES2_TexSubImage2D(data, tdata->texture_type,
   1641                     rect->x,
   1642                     rect->y,
   1643                     rect->w,
   1644                     rect->h,
   1645                     tdata->pixel_format,
   1646                     tdata->pixel_type,
   1647                     pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
   1648 
   1649     if (tdata->yuv) {
   1650         /* Skip to the correct offset into the next texture */
   1651         pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
   1652         if (texture->format == SDL_PIXELFORMAT_YV12) {
   1653             data->glBindTexture(tdata->texture_type, tdata->texture_v);
   1654         } else {
   1655             data->glBindTexture(tdata->texture_type, tdata->texture_u);
   1656         }
   1657         GLES2_TexSubImage2D(data, tdata->texture_type,
   1658                 rect->x / 2,
   1659                 rect->y / 2,
   1660                 (rect->w + 1) / 2,
   1661                 (rect->h + 1) / 2,
   1662                 tdata->pixel_format,
   1663                 tdata->pixel_type,
   1664                 pixels, (pitch + 1) / 2, 1);
   1665 
   1666 
   1667         /* Skip to the correct offset into the next texture */
   1668         pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2));
   1669         if (texture->format == SDL_PIXELFORMAT_YV12) {
   1670             data->glBindTexture(tdata->texture_type, tdata->texture_u);
   1671         } else {
   1672             data->glBindTexture(tdata->texture_type, tdata->texture_v);
   1673         }
   1674         GLES2_TexSubImage2D(data, tdata->texture_type,
   1675                 rect->x / 2,
   1676                 rect->y / 2,
   1677                 (rect->w + 1) / 2,
   1678                 (rect->h + 1) / 2,
   1679                 tdata->pixel_format,
   1680                 tdata->pixel_type,
   1681                 pixels, (pitch + 1) / 2, 1);
   1682     } else if (tdata->nv12) {
   1683         /* Skip to the correct offset into the next texture */
   1684         pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
   1685         data->glBindTexture(tdata->texture_type, tdata->texture_u);
   1686         GLES2_TexSubImage2D(data, tdata->texture_type,
   1687                 rect->x / 2,
   1688                 rect->y / 2,
   1689                 (rect->w + 1) / 2,
   1690                 (rect->h + 1) / 2,
   1691                 GL_LUMINANCE_ALPHA,
   1692                 GL_UNSIGNED_BYTE,
   1693                 pixels, 2 * ((pitch + 1) / 2), 2);
   1694     }
   1695 
   1696     return GL_CheckError("glTexSubImage2D()", renderer);
   1697 }
   1698 
   1699 static int
   1700 GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
   1701                     const SDL_Rect * rect,
   1702                     const Uint8 *Yplane, int Ypitch,
   1703                     const Uint8 *Uplane, int Upitch,
   1704                     const Uint8 *Vplane, int Vpitch)
   1705 {
   1706     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   1707     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   1708 
   1709     GLES2_ActivateRenderer(renderer);
   1710 
   1711     /* Bail out if we're supposed to update an empty rectangle */
   1712     if (rect->w <= 0 || rect->h <= 0) {
   1713         return 0;
   1714     }
   1715 
   1716     data->drawstate.texture = NULL;  /* we trash this state. */
   1717 
   1718     data->glBindTexture(tdata->texture_type, tdata->texture_v);
   1719     GLES2_TexSubImage2D(data, tdata->texture_type,
   1720                     rect->x / 2,
   1721                     rect->y / 2,
   1722                     (rect->w + 1) / 2,
   1723                     (rect->h + 1) / 2,
   1724                     tdata->pixel_format,
   1725                     tdata->pixel_type,
   1726                     Vplane, Vpitch, 1);
   1727 
   1728     data->glBindTexture(tdata->texture_type, tdata->texture_u);
   1729     GLES2_TexSubImage2D(data, tdata->texture_type,
   1730                     rect->x / 2,
   1731                     rect->y / 2,
   1732                     (rect->w + 1) / 2,
   1733                     (rect->h + 1) / 2,
   1734                     tdata->pixel_format,
   1735                     tdata->pixel_type,
   1736                     Uplane, Upitch, 1);
   1737 
   1738     data->glBindTexture(tdata->texture_type, tdata->texture);
   1739     GLES2_TexSubImage2D(data, tdata->texture_type,
   1740                     rect->x,
   1741                     rect->y,
   1742                     rect->w,
   1743                     rect->h,
   1744                     tdata->pixel_format,
   1745                     tdata->pixel_type,
   1746                     Yplane, Ypitch, 1);
   1747 
   1748     return GL_CheckError("glTexSubImage2D()", renderer);
   1749 }
   1750 
   1751 static int
   1752 GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
   1753                   void **pixels, int *pitch)
   1754 {
   1755     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   1756 
   1757     /* Retrieve the buffer/pitch for the specified region */
   1758     *pixels = (Uint8 *)tdata->pixel_data +
   1759               (tdata->pitch * rect->y) +
   1760               (rect->x * SDL_BYTESPERPIXEL(texture->format));
   1761     *pitch = tdata->pitch;
   1762 
   1763     return 0;
   1764 }
   1765 
   1766 static void
   1767 GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
   1768 {
   1769     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   1770     SDL_Rect rect;
   1771 
   1772     /* We do whole texture updates, at least for now */
   1773     rect.x = 0;
   1774     rect.y = 0;
   1775     rect.w = texture->w;
   1776     rect.h = texture->h;
   1777     GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
   1778 }
   1779 
   1780 static void
   1781 GLES2_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
   1782 {
   1783     GLES2_RenderData *renderdata = (GLES2_RenderData *) renderer->driverdata;
   1784     GLES2_TextureData *data = (GLES2_TextureData *) texture->driverdata;
   1785     GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
   1786 
   1787     if (data->yuv) {
   1788         renderdata->glActiveTexture(GL_TEXTURE2);
   1789         renderdata->glBindTexture(data->texture_type, data->texture_v);
   1790         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
   1791         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
   1792 
   1793         renderdata->glActiveTexture(GL_TEXTURE1);
   1794         renderdata->glBindTexture(data->texture_type, data->texture_u);
   1795         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
   1796         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
   1797     } else if (data->nv12) {
   1798         renderdata->glActiveTexture(GL_TEXTURE1);
   1799         renderdata->glBindTexture(data->texture_type, data->texture_u);
   1800         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
   1801         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
   1802     }
   1803 
   1804     renderdata->glActiveTexture(GL_TEXTURE0);
   1805     renderdata->glBindTexture(data->texture_type, data->texture);
   1806     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
   1807     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
   1808 }
   1809 
   1810 static int
   1811 GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
   1812 {
   1813     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
   1814     GLES2_TextureData *texturedata = NULL;
   1815     GLenum status;
   1816 
   1817     data->drawstate.viewport_dirty = SDL_TRUE;
   1818 
   1819     if (texture == NULL) {
   1820         data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
   1821     } else {
   1822         texturedata = (GLES2_TextureData *) texture->driverdata;
   1823         data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
   1824         /* TODO: check if texture pixel format allows this operation */
   1825         data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
   1826         /* Check FBO status */
   1827         status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
   1828         if (status != GL_FRAMEBUFFER_COMPLETE) {
   1829             return SDL_SetError("glFramebufferTexture2D() failed");
   1830         }
   1831     }
   1832     return 0;
   1833 }
   1834 
   1835 static void
   1836 GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
   1837 {
   1838     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   1839     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   1840 
   1841     GLES2_ActivateRenderer(renderer);
   1842 
   1843     if (data->drawstate.texture == texture) {
   1844         data->drawstate.texture = NULL;
   1845     }
   1846     if (data->drawstate.target == texture) {
   1847         data->drawstate.target = NULL;
   1848     }
   1849 
   1850     /* Destroy the texture */
   1851     if (tdata) {
   1852         data->glDeleteTextures(1, &tdata->texture);
   1853         if (tdata->texture_v) {
   1854             data->glDeleteTextures(1, &tdata->texture_v);
   1855         }
   1856         if (tdata->texture_u) {
   1857             data->glDeleteTextures(1, &tdata->texture_u);
   1858         }
   1859         SDL_free(tdata->pixel_data);
   1860         SDL_free(tdata);
   1861         texture->driverdata = NULL;
   1862     }
   1863 }
   1864 
   1865 static int
   1866 GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1867                     Uint32 pixel_format, void * pixels, int pitch)
   1868 {
   1869     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   1870     Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
   1871     size_t buflen;
   1872     void *temp_pixels;
   1873     int temp_pitch;
   1874     Uint8 *src, *dst, *tmp;
   1875     int w, h, length, rows;
   1876     int status;
   1877 
   1878     temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
   1879     buflen = rect->h * temp_pitch;
   1880     if (buflen == 0) {
   1881         return 0;  /* nothing to do. */
   1882     }
   1883 
   1884     temp_pixels = SDL_malloc(buflen);
   1885     if (!temp_pixels) {
   1886         return SDL_OutOfMemory();
   1887     }
   1888 
   1889     SDL_GetRendererOutputSize(renderer, &w, &h);
   1890 
   1891     data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
   1892                        rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
   1893     if (GL_CheckError("glReadPixels()", renderer) < 0) {
   1894         return -1;
   1895     }
   1896 
   1897     /* Flip the rows to be top-down if necessary */
   1898     if (!renderer->target) {
   1899         SDL_bool isstack;
   1900         length = rect->w * SDL_BYTESPERPIXEL(temp_format);
   1901         src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
   1902         dst = (Uint8*)temp_pixels;
   1903         tmp = SDL_small_alloc(Uint8, length, &isstack);
   1904         rows = rect->h / 2;
   1905         while (rows--) {
   1906             SDL_memcpy(tmp, dst, length);
   1907             SDL_memcpy(dst, src, length);
   1908             SDL_memcpy(src, tmp, length);
   1909             dst += temp_pitch;
   1910             src -= temp_pitch;
   1911         }
   1912         SDL_small_free(tmp, isstack);
   1913     }
   1914 
   1915     status = SDL_ConvertPixels(rect->w, rect->h,
   1916                                temp_format, temp_pixels, temp_pitch,
   1917                                pixel_format, pixels, pitch);
   1918     SDL_free(temp_pixels);
   1919 
   1920     return status;
   1921 }
   1922 
   1923 static void
   1924 GLES2_RenderPresent(SDL_Renderer *renderer)
   1925 {
   1926     /* Tell the video driver to swap buffers */
   1927     SDL_GL_SwapWindow(renderer->window);
   1928 }
   1929 
   1930 
   1931 /*************************************************************************************************
   1932  * Bind/unbinding of textures
   1933  *************************************************************************************************/
   1934 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
   1935 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
   1936 
   1937 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
   1938 {
   1939     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   1940     GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
   1941     GLES2_ActivateRenderer(renderer);
   1942 
   1943     data->glBindTexture(texturedata->texture_type, texturedata->texture);
   1944     data->drawstate.texture = texture;
   1945 
   1946     if (texw) {
   1947         *texw = 1.0;
   1948     }
   1949     if (texh) {
   1950         *texh = 1.0;
   1951     }
   1952 
   1953     return 0;
   1954 }
   1955 
   1956 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
   1957 {
   1958     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
   1959     GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
   1960     GLES2_ActivateRenderer(renderer);
   1961 
   1962     data->glBindTexture(texturedata->texture_type, 0);
   1963     data->drawstate.texture = NULL;
   1964 
   1965     return 0;
   1966 }
   1967 
   1968 
   1969 /*************************************************************************************************
   1970  * Renderer instantiation                                                                        *
   1971  *************************************************************************************************/
   1972 
   1973 #ifdef ZUNE_HD
   1974 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
   1975 #endif
   1976 
   1977 
   1978 static SDL_Renderer *
   1979 GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
   1980 {
   1981     SDL_Renderer *renderer;
   1982     GLES2_RenderData *data;
   1983     GLint nFormats;
   1984 #ifndef ZUNE_HD
   1985     GLboolean hasCompiler;
   1986 #endif
   1987     Uint32 window_flags = 0; /* -Wconditional-uninitialized */
   1988     GLint window_framebuffer;
   1989     GLint value;
   1990     int profile_mask = 0, major = 0, minor = 0;
   1991     SDL_bool changed_window = SDL_FALSE;
   1992 
   1993     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask) < 0) {
   1994         goto error;
   1995     }
   1996     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major) < 0) {
   1997         goto error;
   1998     }
   1999     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor) < 0) {
   2000         goto error;
   2001     }
   2002 
   2003     window_flags = SDL_GetWindowFlags(window);
   2004 
   2005     /* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */
   2006     if (!(window_flags & SDL_WINDOW_OPENGL) ||
   2007         profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major < RENDERER_CONTEXT_MAJOR) {
   2008 
   2009         changed_window = SDL_TRUE;
   2010         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
   2011         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
   2012         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
   2013 
   2014         if (SDL_RecreateWindow(window, (window_flags & ~(SDL_WINDOW_VULKAN | SDL_WINDOW_METAL)) | SDL_WINDOW_OPENGL) < 0) {
   2015             goto error;
   2016         }
   2017     }
   2018 
   2019     /* Create the renderer struct */
   2020     renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
   2021     if (!renderer) {
   2022         SDL_OutOfMemory();
   2023         goto error;
   2024     }
   2025 
   2026     data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
   2027     if (!data) {
   2028         SDL_free(renderer);
   2029         SDL_OutOfMemory();
   2030         goto error;
   2031     }
   2032     renderer->info = GLES2_RenderDriver.info;
   2033     renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
   2034     renderer->driverdata = data;
   2035     renderer->window = window;
   2036 
   2037     /* Create an OpenGL ES 2.0 context */
   2038     data->context = SDL_GL_CreateContext(window);
   2039     if (!data->context) {
   2040         SDL_free(renderer);
   2041         SDL_free(data);
   2042         goto error;
   2043     }
   2044     if (SDL_GL_MakeCurrent(window, data->context) < 0) {
   2045         SDL_GL_DeleteContext(data->context);
   2046         SDL_free(renderer);
   2047         SDL_free(data);
   2048         goto error;
   2049     }
   2050 
   2051     if (GLES2_LoadFunctions(data) < 0) {
   2052         SDL_GL_DeleteContext(data->context);
   2053         SDL_free(renderer);
   2054         SDL_free(data);
   2055         goto error;
   2056     }
   2057 
   2058 #if __WINRT__
   2059     /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync
   2060      * is turned on.  Not doing so will freeze the screen's contents to that
   2061      * of the first drawn frame.
   2062      */
   2063     flags |= SDL_RENDERER_PRESENTVSYNC;
   2064 #endif
   2065 
   2066     if (flags & SDL_RENDERER_PRESENTVSYNC) {
   2067         SDL_GL_SetSwapInterval(1);
   2068     } else {
   2069         SDL_GL_SetSwapInterval(0);
   2070     }
   2071     if (SDL_GL_GetSwapInterval() > 0) {
   2072         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
   2073     }
   2074 
   2075     /* Check for debug output support */
   2076     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
   2077         (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
   2078         data->debug_enabled = SDL_TRUE;
   2079     }
   2080 
   2081     value = 0;
   2082     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   2083     renderer->info.max_texture_width = value;
   2084     value = 0;
   2085     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
   2086     renderer->info.max_texture_height = value;
   2087 
   2088     /* Determine supported shader formats */
   2089     /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
   2090 #ifdef ZUNE_HD
   2091     nFormats = 1;
   2092 #else /* !ZUNE_HD */
   2093     data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
   2094     data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
   2095     if (hasCompiler) {
   2096         ++nFormats;
   2097     }
   2098 #endif /* ZUNE_HD */
   2099     data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
   2100     if (!data->shader_formats) {
   2101         GLES2_DestroyRenderer(renderer);
   2102         SDL_OutOfMemory();
   2103         goto error;
   2104     }
   2105     data->shader_format_count = nFormats;
   2106 #ifdef ZUNE_HD
   2107     data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
   2108 #else /* !ZUNE_HD */
   2109     data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats);
   2110     if (hasCompiler) {
   2111         data->shader_formats[nFormats - 1] = (GLenum)-1;
   2112     }
   2113 #endif /* ZUNE_HD */
   2114 
   2115     /* we keep a few of these and cycle through them, so data can live for a few frames. */
   2116     data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
   2117 
   2118     data->framebuffers = NULL;
   2119     data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
   2120     data->window_framebuffer = (GLuint)window_framebuffer;
   2121 
   2122     /* Populate the function pointers for the module */
   2123     renderer->WindowEvent         = GLES2_WindowEvent;
   2124     renderer->GetOutputSize       = GLES2_GetOutputSize;
   2125     renderer->SupportsBlendMode   = GLES2_SupportsBlendMode;
   2126     renderer->CreateTexture       = GLES2_CreateTexture;
   2127     renderer->UpdateTexture       = GLES2_UpdateTexture;
   2128     renderer->UpdateTextureYUV    = GLES2_UpdateTextureYUV;
   2129     renderer->LockTexture         = GLES2_LockTexture;
   2130     renderer->UnlockTexture       = GLES2_UnlockTexture;
   2131     renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode;
   2132     renderer->SetRenderTarget     = GLES2_SetRenderTarget;
   2133     renderer->QueueSetViewport    = GLES2_QueueSetViewport;
   2134     renderer->QueueSetDrawColor   = GLES2_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
   2135     renderer->QueueDrawPoints     = GLES2_QueueDrawPoints;
   2136     renderer->QueueDrawLines      = GLES2_QueueDrawLines;
   2137     renderer->QueueFillRects      = GLES2_QueueFillRects;
   2138     renderer->QueueCopy           = GLES2_QueueCopy;
   2139     renderer->QueueCopyEx         = GLES2_QueueCopyEx;
   2140     renderer->RunCommandQueue     = GLES2_RunCommandQueue;
   2141     renderer->RenderReadPixels    = GLES2_RenderReadPixels;
   2142     renderer->RenderPresent       = GLES2_RenderPresent;
   2143     renderer->DestroyTexture      = GLES2_DestroyTexture;
   2144     renderer->DestroyRenderer     = GLES2_DestroyRenderer;
   2145     renderer->GL_BindTexture      = GLES2_BindTexture;
   2146     renderer->GL_UnbindTexture    = GLES2_UnbindTexture;
   2147 
   2148     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
   2149     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
   2150     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
   2151     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
   2152 #ifdef GL_TEXTURE_EXTERNAL_OES
   2153     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_EXTERNAL_OES;
   2154 #endif
   2155 
   2156     /* Set up parameters for rendering */
   2157     data->glActiveTexture(GL_TEXTURE0);
   2158     data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
   2159     data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   2160 
   2161     data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   2162     data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
   2163 
   2164     data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
   2165 
   2166     data->drawstate.blend = SDL_BLENDMODE_INVALID;
   2167     data->drawstate.color = 0xFFFFFFFF;
   2168     data->drawstate.clear_color = 0xFFFFFFFF;
   2169     data->drawstate.projection[3][0] = -1.0f;
   2170     data->drawstate.projection[3][3] = 1.0f;
   2171 
   2172     GL_CheckError("", renderer);
   2173 
   2174     return renderer;
   2175 
   2176 error:
   2177     if (changed_window) {
   2178         /* Uh oh, better try to put it back... */
   2179         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
   2180         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
   2181         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
   2182         SDL_RecreateWindow(window, window_flags);
   2183     }
   2184     return NULL;
   2185 }
   2186 
   2187 SDL_RenderDriver GLES2_RenderDriver = {
   2188     GLES2_CreateRenderer,
   2189     {
   2190         "opengles2",
   2191         (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
   2192         4,
   2193         {
   2194         SDL_PIXELFORMAT_ARGB8888,
   2195         SDL_PIXELFORMAT_ABGR8888,
   2196         SDL_PIXELFORMAT_RGB888,
   2197         SDL_PIXELFORMAT_BGR888
   2198         },
   2199         0,
   2200         0
   2201     }
   2202 };
   2203 
   2204 #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
   2205 
   2206 /* vi: set ts=4 sw=4 expandtab: */