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