src/render/opengles2/SDL_render_gles2.c
author Ryan C. Gordon
Sat, 31 Oct 2020 11:32:40 -0400
changeset 14210 2b1cce20e59b
parent 14197 0a38c9fd363d
permissions -rw-r--r--
coreaudio: Remove unnecessary include of CoreServices.h
     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_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         if (data->program_cache.tail != NULL) {
   533             SDL_free(data->program_cache.tail->next);
   534             data->program_cache.tail->next = NULL;
   535         }
   536         --data->program_cache.count;
   537     }
   538     return entry;
   539 }
   540 
   541 static GLES2_ShaderCacheEntry *
   542 GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type)
   543 {
   544     const GLES2_Shader *shader;
   545     const GLES2_ShaderInstance *instance = NULL;
   546     GLES2_ShaderCacheEntry *entry = NULL;
   547     GLint compileSuccessful = GL_FALSE;
   548     int i, j;
   549 
   550     /* Find the corresponding shader */
   551     shader = GLES2_GetShader(type);
   552     if (!shader) {
   553         SDL_SetError("No shader matching the requested characteristics was found");
   554         return NULL;
   555     }
   556 
   557     /* Find a matching shader instance that's supported on this hardware */
   558     for (i = 0; i < shader->instance_count && !instance; ++i) {
   559         for (j = 0; j < data->shader_format_count && !instance; ++j) {
   560             if (!shader->instances[i]) {
   561                 continue;
   562             }
   563             if (shader->instances[i]->format != data->shader_formats[j]) {
   564                 continue;
   565             }
   566             instance = shader->instances[i];
   567         }
   568     }
   569     if (!instance) {
   570         SDL_SetError("The specified shader cannot be loaded on the current platform");
   571         return NULL;
   572     }
   573 
   574     /* Check if we've already cached this shader */
   575     entry = data->shader_cache.head;
   576     while (entry) {
   577         if (entry->instance == instance) {
   578             break;
   579         }
   580         entry = entry->next;
   581     }
   582     if (entry) {
   583         return entry;
   584     }
   585 
   586     /* Create a shader cache entry */
   587     entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry));
   588     if (!entry) {
   589         SDL_OutOfMemory();
   590         return NULL;
   591     }
   592     entry->type = type;
   593     entry->instance = instance;
   594 
   595     /* Compile or load the selected shader instance */
   596     entry->id = data->glCreateShader(instance->type);
   597     if (instance->format == (GLenum)-1) {
   598         data->glShaderSource(entry->id, 1, (const char **)(char *)&instance->data, NULL);
   599         data->glCompileShader(entry->id);
   600         data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
   601     } else {
   602         data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
   603         compileSuccessful = GL_TRUE;
   604     }
   605     if (!compileSuccessful) {
   606         SDL_bool isstack = SDL_FALSE;
   607         char *info = NULL;
   608         int length = 0;
   609 
   610         data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
   611         if (length > 0) {
   612             info = SDL_small_alloc(char, length, &isstack);
   613             if (info) {
   614                 data->glGetShaderInfoLog(entry->id, length, &length, info);
   615             }
   616         }
   617         if (info) {
   618             SDL_SetError("Failed to load the shader: %s", info);
   619             SDL_small_free(info, isstack);
   620         } else {
   621             SDL_SetError("Failed to load the shader");
   622         }
   623         data->glDeleteShader(entry->id);
   624         SDL_free(entry);
   625         return NULL;
   626     }
   627 
   628     /* Link the shader entry in at the front of the cache */
   629     if (data->shader_cache.head) {
   630         entry->next = data->shader_cache.head;
   631         data->shader_cache.head->prev = entry;
   632     }
   633     data->shader_cache.head = entry;
   634     ++data->shader_cache.count;
   635     return entry;
   636 }
   637 
   638 static int
   639 GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int h)
   640 {
   641     GLES2_ShaderCacheEntry *vertex = NULL;
   642     GLES2_ShaderCacheEntry *fragment = NULL;
   643     GLES2_ShaderType vtype, ftype;
   644     GLES2_ProgramCacheEntry *program;
   645 
   646     /* Select an appropriate shader pair for the specified modes */
   647     vtype = GLES2_SHADER_VERTEX_DEFAULT;
   648     switch (source) {
   649     case GLES2_IMAGESOURCE_SOLID:
   650         ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
   651         break;
   652     case GLES2_IMAGESOURCE_TEXTURE_ABGR:
   653         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
   654         break;
   655     case GLES2_IMAGESOURCE_TEXTURE_ARGB:
   656         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
   657         break;
   658     case GLES2_IMAGESOURCE_TEXTURE_RGB:
   659         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
   660         break;
   661     case GLES2_IMAGESOURCE_TEXTURE_BGR:
   662         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
   663         break;
   664     case GLES2_IMAGESOURCE_TEXTURE_YUV:
   665         switch (SDL_GetYUVConversionModeForResolution(w, h)) {
   666         case SDL_YUV_CONVERSION_JPEG:
   667             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG_SRC;
   668             break;
   669         case SDL_YUV_CONVERSION_BT601:
   670             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601_SRC;
   671             break;
   672         case SDL_YUV_CONVERSION_BT709:
   673             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709_SRC;
   674             break;
   675         default:
   676             SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
   677             goto fault;
   678         }
   679         break;
   680     case GLES2_IMAGESOURCE_TEXTURE_NV12:
   681         switch (SDL_GetYUVConversionModeForResolution(w, h)) {
   682         case SDL_YUV_CONVERSION_JPEG:
   683             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG_SRC;
   684             break;
   685         case SDL_YUV_CONVERSION_BT601:
   686             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601_SRC;
   687             break;
   688         case SDL_YUV_CONVERSION_BT709:
   689             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709_SRC;
   690             break;
   691         default:
   692             SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
   693             goto fault;
   694         }
   695         break;
   696     case GLES2_IMAGESOURCE_TEXTURE_NV21:
   697         switch (SDL_GetYUVConversionModeForResolution(w, h)) {
   698         case SDL_YUV_CONVERSION_JPEG:
   699             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG_SRC;
   700             break;
   701         case SDL_YUV_CONVERSION_BT601:
   702             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601_SRC;
   703             break;
   704         case SDL_YUV_CONVERSION_BT709:
   705             ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC;
   706             break;
   707         default:
   708             SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
   709             goto fault;
   710         }
   711         break;
   712     case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
   713         ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC;
   714         break;
   715     default:
   716         goto fault;
   717     }
   718 
   719     /* Load the requested shaders */
   720     vertex = GLES2_CacheShader(data, vtype);
   721     if (!vertex) {
   722         goto fault;
   723     }
   724     fragment = GLES2_CacheShader(data, ftype);
   725     if (!fragment) {
   726         goto fault;
   727     }
   728 
   729     /* Check if we need to change programs at all */
   730     if (data->drawstate.program &&
   731         data->drawstate.program->vertex_shader == vertex &&
   732         data->drawstate.program->fragment_shader == fragment) {
   733         return 0;
   734     }
   735 
   736     /* Generate a matching program */
   737     program = GLES2_CacheProgram(data, vertex, fragment);
   738     if (!program) {
   739         goto fault;
   740     }
   741 
   742     /* Select that program in OpenGL */
   743     data->glUseProgram(program->id);
   744 
   745     /* Set the current program */
   746     data->drawstate.program = program;
   747 
   748     /* Clean up and return */
   749     return 0;
   750 fault:
   751     if (vertex && vertex->references <= 0) {
   752         GLES2_EvictShader(data, vertex);
   753     }
   754     if (fragment && fragment->references <= 0) {
   755         GLES2_EvictShader(data, fragment);
   756     }
   757     data->drawstate.program = NULL;
   758     return -1;
   759 }
   760 
   761 static int
   762 GLES2_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
   763 {
   764     return 0;  /* nothing to do in this backend. */
   765 }
   766 
   767 static int
   768 GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
   769 {
   770     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
   771     int i;
   772 
   773     if (!verts) {
   774         return -1;
   775     }
   776 
   777     cmd->data.draw.count = count;
   778     for (i = 0; i < count; i++) {
   779         *(verts++) = 0.5f + points[i].x;
   780         *(verts++) = 0.5f + points[i].y;
   781     }
   782 
   783     return 0;
   784 }
   785 
   786 static int
   787 GLES2_QueueDrawLines(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
   788 {
   789     GLfloat *verts;
   790     int i;
   791 
   792     SDL_assert(count >= 2);  /* should have been checked at the higher level. */
   793 
   794     verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, (count-1) * 4 * sizeof (GLfloat), 0, &cmd->data.draw.first);
   795     if (!verts) {
   796         return -1;
   797     }
   798 
   799     cmd->data.draw.count = count;
   800 
   801     /* GL_LINE_STRIP seems to be unreliable on various drivers, so try
   802        to build out our own GL_LINES.  :(
   803        If the line segment is completely horizontal or vertical,
   804        make it one pixel longer, to satisfy the diamond-exit rule.
   805        We should probably do this for diagonal lines too, but we'd have to
   806        do some trigonometry to figure out the correct pixel and generally
   807        when we have problems with pixel perfection, it's for straight lines
   808        that are missing a pixel that frames something and not arbitrary
   809        angles. Maybe !!! FIXME for later, though. */
   810 
   811     for (i = 0; i < count-1; i++, points++) {
   812         GLfloat xstart = 0.5f + points[0].x;   /* 0.5f to get to the center of the pixel. */
   813         GLfloat ystart = 0.5f + points[0].y;
   814         GLfloat xend = 0.5f + points[1].x;
   815         GLfloat yend = 0.5f + points[1].y;
   816 
   817         if (xstart == xend) {  /* vertical line */
   818             if (yend > ystart) {
   819                 yend += 1.0f;
   820             } else {
   821                 ystart += 1.0f;
   822             }
   823         } else if (ystart == yend) {  /* horizontal line */
   824             if (xend > xstart) {
   825                 xend += 1.0f;
   826             } else {
   827                 xstart += 1.0f;
   828             }
   829         }
   830 
   831         *(verts++) = xstart;
   832         *(verts++) = ystart;
   833         *(verts++) = xend;
   834         *(verts++) = yend;
   835     }
   836 
   837     return 0;
   838 }
   839 
   840 static int
   841 GLES2_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
   842 {
   843     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
   844     int i;
   845 
   846     if (!verts) {
   847         return -1;
   848     }
   849 
   850     cmd->data.draw.count = count;
   851 
   852     for (i = 0; i < count; i++) {
   853         const SDL_FRect *rect = &rects[i];
   854         const GLfloat minx = rect->x;
   855         const GLfloat maxx = rect->x + rect->w;
   856         const GLfloat miny = rect->y;
   857         const GLfloat maxy = rect->y + rect->h;
   858         *(verts++) = minx;
   859         *(verts++) = miny;
   860         *(verts++) = maxx;
   861         *(verts++) = miny;
   862         *(verts++) = minx;
   863         *(verts++) = maxy;
   864         *(verts++) = maxx;
   865         *(verts++) = maxy;
   866     }
   867 
   868     return 0;
   869 }
   870 
   871 static int
   872 GLES2_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   873                           const SDL_Rect * srcrect, const SDL_FRect * dstrect)
   874 {
   875     GLfloat minx, miny, maxx, maxy;
   876     GLfloat minu, maxu, minv, maxv;
   877     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
   878 
   879     if (!verts) {
   880         return -1;
   881     }
   882 
   883     cmd->data.draw.count = 1;
   884 
   885     minx = dstrect->x;
   886     miny = dstrect->y;
   887     maxx = dstrect->x + dstrect->w;
   888     maxy = dstrect->y + dstrect->h;
   889 
   890     minu = (GLfloat) srcrect->x / texture->w;
   891     maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
   892     minv = (GLfloat) srcrect->y / texture->h;
   893     maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   894 
   895     *(verts++) = minx;
   896     *(verts++) = miny;
   897     *(verts++) = maxx;
   898     *(verts++) = miny;
   899     *(verts++) = minx;
   900     *(verts++) = maxy;
   901     *(verts++) = maxx;
   902     *(verts++) = maxy;
   903 
   904     *(verts++) = minu;
   905     *(verts++) = minv;
   906     *(verts++) = maxu;
   907     *(verts++) = minv;
   908     *(verts++) = minu;
   909     *(verts++) = maxv;
   910     *(verts++) = maxu;
   911     *(verts++) = maxv;
   912 
   913     return 0;
   914 }
   915 
   916 static int
   917 GLES2_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
   918                         const SDL_Rect * srcquad, const SDL_FRect * dstrect,
   919                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
   920 {
   921     /* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
   922     const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
   923     const GLfloat s = (GLfloat) SDL_sin(radian_angle);
   924     const GLfloat c = (GLfloat) SDL_cos(radian_angle) - 1.0f;
   925     const GLfloat centerx = center->x + dstrect->x;
   926     const GLfloat centery = center->y + dstrect->y;
   927     GLfloat minx, miny, maxx, maxy;
   928     GLfloat minu, maxu, minv, maxv;
   929     GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 32 * sizeof (GLfloat), 0, &cmd->data.draw.first);
   930 
   931     if (!verts) {
   932         return -1;
   933     }
   934 
   935     if (flip & SDL_FLIP_HORIZONTAL) {
   936         minx = dstrect->x + dstrect->w;
   937         maxx = dstrect->x;
   938     } else {
   939         minx = dstrect->x;
   940         maxx = dstrect->x + dstrect->w;
   941     }
   942 
   943     if (flip & SDL_FLIP_VERTICAL) {
   944         miny = dstrect->y + dstrect->h;
   945         maxy = dstrect->y;
   946     } else {
   947         miny = dstrect->y;
   948         maxy = dstrect->y + dstrect->h;
   949     }
   950 
   951     minu = ((GLfloat) srcquad->x) / ((GLfloat) texture->w);
   952     maxu = ((GLfloat) (srcquad->x + srcquad->w)) / ((GLfloat) texture->w);
   953     minv = ((GLfloat) srcquad->y) / ((GLfloat) texture->h);
   954     maxv = ((GLfloat) (srcquad->y + srcquad->h)) / ((GLfloat) texture->h);
   955 
   956 
   957     cmd->data.draw.count = 1;
   958 
   959     *(verts++) = minx;
   960     *(verts++) = miny;
   961     *(verts++) = maxx;
   962     *(verts++) = miny;
   963     *(verts++) = minx;
   964     *(verts++) = maxy;
   965     *(verts++) = maxx;
   966     *(verts++) = maxy;
   967 
   968     *(verts++) = minu;
   969     *(verts++) = minv;
   970     *(verts++) = maxu;
   971     *(verts++) = minv;
   972     *(verts++) = minu;
   973     *(verts++) = maxv;
   974     *(verts++) = maxu;
   975     *(verts++) = maxv;
   976 
   977     *(verts++) = s;
   978     *(verts++) = c;
   979     *(verts++) = s;
   980     *(verts++) = c;
   981     *(verts++) = s;
   982     *(verts++) = c;
   983     *(verts++) = s;
   984     *(verts++) = c;
   985 
   986     *(verts++) = centerx;
   987     *(verts++) = centery;
   988     *(verts++) = centerx;
   989     *(verts++) = centery;
   990     *(verts++) = centerx;
   991     *(verts++) = centery;
   992     *(verts++) = centerx;
   993     *(verts++) = centery;
   994 
   995     return 0;
   996 }
   997 
   998 static int
   999 SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc)
  1000 {
  1001     const SDL_bool was_copy_ex = data->drawstate.is_copy_ex;
  1002     const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX);
  1003     SDL_Texture *texture = cmd->data.draw.texture;
  1004     const SDL_BlendMode blend = cmd->data.draw.blend;
  1005     GLES2_ProgramCacheEntry *program;
  1006 
  1007     SDL_assert((texture != NULL) == (imgsrc != GLES2_IMAGESOURCE_SOLID));
  1008 
  1009     if (data->drawstate.viewport_dirty) {
  1010         const SDL_Rect *viewport = &data->drawstate.viewport;
  1011         data->glViewport(viewport->x,
  1012                          data->drawstate.target ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
  1013                          viewport->w, viewport->h);
  1014         if (viewport->w && viewport->h) {
  1015             data->drawstate.projection[0][0] = 2.0f / viewport->w;
  1016             data->drawstate.projection[1][1] = (data->drawstate.target ? 2.0f : -2.0f) / viewport->h;
  1017             data->drawstate.projection[3][1] = data->drawstate.target ? -1.0f : 1.0f;
  1018         }
  1019         data->drawstate.viewport_dirty = SDL_FALSE;
  1020     }
  1021 
  1022     if (data->drawstate.cliprect_enabled_dirty) {
  1023         if (!data->drawstate.cliprect_enabled) {
  1024             data->glDisable(GL_SCISSOR_TEST);
  1025         } else {
  1026             data->glEnable(GL_SCISSOR_TEST);
  1027         }
  1028         data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
  1029     }
  1030 
  1031     if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
  1032         const SDL_Rect *viewport = &data->drawstate.viewport;
  1033         const SDL_Rect *rect = &data->drawstate.cliprect;
  1034         data->glScissor(viewport->x + rect->x,
  1035                         data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
  1036                         rect->w, rect->h);
  1037         data->drawstate.cliprect_dirty = SDL_FALSE;
  1038     }
  1039 
  1040     if (texture != data->drawstate.texture) {
  1041         if ((texture != NULL) != data->drawstate.texturing) {
  1042             if (texture == NULL) {
  1043                 data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
  1044                 data->drawstate.texturing = SDL_FALSE;
  1045             } else {
  1046                 data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
  1047                 data->drawstate.texturing = SDL_TRUE;
  1048             }
  1049         }
  1050 
  1051         if (texture) {
  1052             GLES2_TextureData *tdata = (GLES2_TextureData *) texture->driverdata;
  1053             if (tdata->yuv) {
  1054                 data->glActiveTexture(GL_TEXTURE2);
  1055                 data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1056 
  1057                 data->glActiveTexture(GL_TEXTURE1);
  1058                 data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1059 
  1060                 data->glActiveTexture(GL_TEXTURE0);
  1061             } else if (tdata->nv12) {
  1062                 data->glActiveTexture(GL_TEXTURE1);
  1063                 data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1064 
  1065                 data->glActiveTexture(GL_TEXTURE0);
  1066             }
  1067             data->glBindTexture(tdata->texture_type, tdata->texture);
  1068         }
  1069 
  1070         data->drawstate.texture = texture;
  1071     }
  1072 
  1073     if (texture) {
  1074         data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 8)));
  1075     }
  1076 
  1077     if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
  1078         return -1;
  1079     }
  1080 
  1081     program = data->drawstate.program;
  1082 
  1083     if (program->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
  1084         if (SDL_memcmp(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)) != 0) {
  1085             data->glUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection);
  1086             SDL_memcpy(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection));
  1087         }
  1088     }
  1089 
  1090     if (program->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
  1091         if (data->drawstate.color != program->color) {
  1092             const Uint8 r = (data->drawstate.color >> 16) & 0xFF;
  1093             const Uint8 g = (data->drawstate.color >> 8) & 0xFF;
  1094             const Uint8 b = (data->drawstate.color >> 0) & 0xFF;
  1095             const Uint8 a = (data->drawstate.color >> 24) & 0xFF;
  1096             data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
  1097             program->color = data->drawstate.color;
  1098         }
  1099     }
  1100 
  1101     if (blend != data->drawstate.blend) {
  1102         if (blend == SDL_BLENDMODE_NONE) {
  1103             data->glDisable(GL_BLEND);
  1104         } else {
  1105             data->glEnable(GL_BLEND);
  1106             data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
  1107                                       GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
  1108                                       GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
  1109                                       GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
  1110             data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
  1111                                           GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
  1112         }
  1113         data->drawstate.blend = blend;
  1114     }
  1115 
  1116     /* all drawing commands use this */
  1117     data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first);
  1118 
  1119     if (is_copy_ex != was_copy_ex) {
  1120         if (is_copy_ex) {
  1121             data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
  1122             data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
  1123         } else {
  1124             data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
  1125             data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
  1126         }
  1127         data->drawstate.is_copy_ex = is_copy_ex;
  1128     }
  1129 
  1130     if (is_copy_ex) {
  1131         data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 16)));
  1132         data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 24)));
  1133     }
  1134 
  1135     return 0;
  1136 }
  1137 
  1138 static int
  1139 SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
  1140 {
  1141     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
  1142     GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1143     SDL_Texture *texture = cmd->data.draw.texture;
  1144 
  1145     /* Pick an appropriate shader */
  1146     if (renderer->target) {
  1147         /* Check if we need to do color mapping between the source and render target textures */
  1148         if (renderer->target->format != texture->format) {
  1149             switch (texture->format) {
  1150             case SDL_PIXELFORMAT_ARGB8888:
  1151                 switch (renderer->target->format) {
  1152                 case SDL_PIXELFORMAT_ABGR8888:
  1153                 case SDL_PIXELFORMAT_BGR888:
  1154                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1155                     break;
  1156                 case SDL_PIXELFORMAT_RGB888:
  1157                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1158                     break;
  1159                 }
  1160                 break;
  1161             case SDL_PIXELFORMAT_ABGR8888:
  1162                 switch (renderer->target->format) {
  1163                 case SDL_PIXELFORMAT_ARGB8888:
  1164                 case SDL_PIXELFORMAT_RGB888:
  1165                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1166                     break;
  1167                 case SDL_PIXELFORMAT_BGR888:
  1168                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1169                     break;
  1170                 }
  1171                 break;
  1172             case SDL_PIXELFORMAT_RGB888:
  1173                 switch (renderer->target->format) {
  1174                 case SDL_PIXELFORMAT_ABGR8888:
  1175                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1176                     break;
  1177                 case SDL_PIXELFORMAT_ARGB8888:
  1178                     sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1179                     break;
  1180                 case SDL_PIXELFORMAT_BGR888:
  1181                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1182                     break;
  1183                 }
  1184                 break;
  1185             case SDL_PIXELFORMAT_BGR888:
  1186                 switch (renderer->target->format) {
  1187                 case SDL_PIXELFORMAT_ABGR8888:
  1188                     sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1189                     break;
  1190                 case SDL_PIXELFORMAT_ARGB8888:
  1191                     sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1192                     break;
  1193                 case SDL_PIXELFORMAT_RGB888:
  1194                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1195                     break;
  1196                 }
  1197                 break;
  1198             case SDL_PIXELFORMAT_IYUV:
  1199             case SDL_PIXELFORMAT_YV12:
  1200                 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
  1201                 break;
  1202             case SDL_PIXELFORMAT_NV12:
  1203                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
  1204                 break;
  1205             case SDL_PIXELFORMAT_NV21:
  1206                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
  1207                 break;
  1208             case SDL_PIXELFORMAT_EXTERNAL_OES:
  1209                 sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
  1210                 break;
  1211             default:
  1212                 return SDL_SetError("Unsupported texture format");
  1213             }
  1214         } else {
  1215             sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;   /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
  1216         }
  1217     } else {
  1218         switch (texture->format) {
  1219             case SDL_PIXELFORMAT_ARGB8888:
  1220                 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1221                 break;
  1222             case SDL_PIXELFORMAT_ABGR8888:
  1223                 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1224                 break;
  1225             case SDL_PIXELFORMAT_RGB888:
  1226                 sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1227                 break;
  1228             case SDL_PIXELFORMAT_BGR888:
  1229                 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1230                 break;
  1231             case SDL_PIXELFORMAT_IYUV:
  1232             case SDL_PIXELFORMAT_YV12:
  1233                 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
  1234                 break;
  1235             case SDL_PIXELFORMAT_NV12:
  1236                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
  1237                 break;
  1238             case SDL_PIXELFORMAT_NV21:
  1239                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
  1240                 break;
  1241             case SDL_PIXELFORMAT_EXTERNAL_OES:
  1242                 sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
  1243                 break;
  1244             default:
  1245                 return SDL_SetError("Unsupported texture format");
  1246         }
  1247     }
  1248 
  1249     return SetDrawState(data, cmd, sourceType);
  1250 }
  1251 
  1252 static int
  1253 GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
  1254 {
  1255     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
  1256     const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
  1257     const int vboidx = data->current_vertex_buffer;
  1258     const GLuint vbo = data->vertex_buffers[vboidx];
  1259     size_t i;
  1260 
  1261     if (GLES2_ActivateRenderer(renderer) < 0) {
  1262         return -1;
  1263     }
  1264 
  1265     data->drawstate.target = renderer->target;
  1266     if (!data->drawstate.target) {
  1267         SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
  1268     }
  1269 
  1270     /* upload the new VBO data for this set of commands. */
  1271     data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
  1272     if (data->vertex_buffer_size[vboidx] < vertsize) {
  1273         data->glBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_STREAM_DRAW);
  1274         data->vertex_buffer_size[vboidx] = vertsize;
  1275     } else {
  1276         data->glBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices);
  1277     }
  1278 
  1279     /* cycle through a few VBOs so the GL has some time with the data before we replace it. */
  1280     data->current_vertex_buffer++;
  1281     if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
  1282         data->current_vertex_buffer = 0;
  1283     }
  1284 
  1285     while (cmd) {
  1286         switch (cmd->command) {
  1287             case SDL_RENDERCMD_SETDRAWCOLOR: {
  1288                 const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
  1289                 const Uint8 g = cmd->data.color.g;
  1290                 const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
  1291                 const Uint8 a = cmd->data.color.a;
  1292                 data->drawstate.color = ((a << 24) | (r << 16) | (g << 8) | b);
  1293                 break;
  1294             }
  1295 
  1296             case SDL_RENDERCMD_SETVIEWPORT: {
  1297                 SDL_Rect *viewport = &data->drawstate.viewport;
  1298                 if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
  1299                     SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
  1300                     data->drawstate.viewport_dirty = SDL_TRUE;
  1301                 }
  1302                 break;
  1303             }
  1304 
  1305             case SDL_RENDERCMD_SETCLIPRECT: {
  1306                 const SDL_Rect *rect = &cmd->data.cliprect.rect;
  1307                 if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
  1308                     data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
  1309                     data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
  1310                 }
  1311 
  1312                 if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
  1313                     SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
  1314                     data->drawstate.cliprect_dirty = SDL_TRUE;
  1315                 }
  1316                 break;
  1317             }
  1318 
  1319             case SDL_RENDERCMD_CLEAR: {
  1320                 const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
  1321                 const Uint8 g = cmd->data.color.g;
  1322                 const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
  1323                 const Uint8 a = cmd->data.color.a;
  1324                 const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
  1325                 if (color != data->drawstate.clear_color) {
  1326                     const GLfloat fr = ((GLfloat) r) * inv255f;
  1327                     const GLfloat fg = ((GLfloat) g) * inv255f;
  1328                     const GLfloat fb = ((GLfloat) b) * inv255f;
  1329                     const GLfloat fa = ((GLfloat) a) * inv255f;
  1330                     data->glClearColor(fr, fg, fb, fa);
  1331                     data->drawstate.clear_color = color;
  1332                 }
  1333 
  1334                 if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
  1335                     data->glDisable(GL_SCISSOR_TEST);
  1336                     data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
  1337                 }
  1338 
  1339                 data->glClear(GL_COLOR_BUFFER_BIT);
  1340                 break;
  1341             }
  1342 
  1343             case SDL_RENDERCMD_DRAW_POINTS: {
  1344                 if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
  1345                     data->glDrawArrays(GL_POINTS, 0, (GLsizei) cmd->data.draw.count);
  1346                 }
  1347                 break;
  1348             }
  1349 
  1350             case SDL_RENDERCMD_DRAW_LINES: {
  1351                 const size_t count = cmd->data.draw.count;
  1352                 SDL_assert(count >= 2);
  1353                 if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
  1354                     data->glDrawArrays(GL_LINES, 0, (GLsizei) ((count-1) * 2));
  1355                 }
  1356                 break;
  1357             }
  1358 
  1359             case SDL_RENDERCMD_FILL_RECTS: {
  1360                 const size_t count = cmd->data.draw.count;
  1361                 size_t offset = 0;
  1362                 if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
  1363                     for (i = 0; i < count; ++i, offset += 4) {
  1364                         data->glDrawArrays(GL_TRIANGLE_STRIP, (GLsizei) offset, 4);
  1365                     }
  1366                 }
  1367                 break;
  1368             }
  1369 
  1370             case SDL_RENDERCMD_COPY:
  1371             case SDL_RENDERCMD_COPY_EX: {
  1372                 if (SetCopyState(renderer, cmd) == 0) {
  1373                     data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1374                 }
  1375                 break;
  1376             }
  1377 
  1378             case SDL_RENDERCMD_NO_OP:
  1379                 break;
  1380         }
  1381 
  1382         cmd = cmd->next;
  1383     }
  1384 
  1385     return GL_CheckError("", renderer);
  1386 }
  1387 
  1388 static void
  1389 GLES2_DestroyRenderer(SDL_Renderer *renderer)
  1390 {
  1391     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  1392 
  1393     /* Deallocate everything */
  1394     if (data) {
  1395         GLES2_ActivateRenderer(renderer);
  1396 
  1397         {
  1398             GLES2_ShaderCacheEntry *entry;
  1399             GLES2_ShaderCacheEntry *next;
  1400             entry = data->shader_cache.head;
  1401             while (entry) {
  1402                 data->glDeleteShader(entry->id);
  1403                 next = entry->next;
  1404                 SDL_free(entry);
  1405                 entry = next;
  1406             }
  1407         }
  1408         {
  1409             GLES2_ProgramCacheEntry *entry;
  1410             GLES2_ProgramCacheEntry *next;
  1411             entry = data->program_cache.head;
  1412             while (entry) {
  1413                 data->glDeleteProgram(entry->id);
  1414                 next = entry->next;
  1415                 SDL_free(entry);
  1416                 entry = next;
  1417             }
  1418         }
  1419 
  1420         if (data->context) {
  1421             while (data->framebuffers) {
  1422                 GLES2_FBOList *nextnode = data->framebuffers->next;
  1423                 data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
  1424                 GL_CheckError("", renderer);
  1425                 SDL_free(data->framebuffers);
  1426                 data->framebuffers = nextnode;
  1427             }
  1428 
  1429             data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
  1430             GL_CheckError("", renderer);
  1431 
  1432             SDL_GL_DeleteContext(data->context);
  1433         }
  1434 
  1435         SDL_free(data->shader_formats);
  1436         SDL_free(data);
  1437     }
  1438     SDL_free(renderer);
  1439 }
  1440 
  1441 static int
  1442 GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  1443 {
  1444     GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->driverdata;
  1445     GLES2_TextureData *data;
  1446     GLenum format;
  1447     GLenum type;
  1448     GLenum scaleMode;
  1449 
  1450     GLES2_ActivateRenderer(renderer);
  1451 
  1452     renderdata->drawstate.texture = NULL;  /* we trash this state. */
  1453 
  1454     /* Determine the corresponding GLES texture format params */
  1455     switch (texture->format)
  1456     {
  1457     case SDL_PIXELFORMAT_ARGB8888:
  1458     case SDL_PIXELFORMAT_ABGR8888:
  1459     case SDL_PIXELFORMAT_RGB888:
  1460     case SDL_PIXELFORMAT_BGR888:
  1461         format = GL_RGBA;
  1462         type = GL_UNSIGNED_BYTE;
  1463         break;
  1464     case SDL_PIXELFORMAT_IYUV:
  1465     case SDL_PIXELFORMAT_YV12:
  1466     case SDL_PIXELFORMAT_NV12:
  1467     case SDL_PIXELFORMAT_NV21:
  1468         format = GL_LUMINANCE;
  1469         type = GL_UNSIGNED_BYTE;
  1470         break;
  1471 #ifdef GL_TEXTURE_EXTERNAL_OES
  1472     case SDL_PIXELFORMAT_EXTERNAL_OES:
  1473         format = GL_NONE;
  1474         type = GL_NONE;
  1475         break;
  1476 #endif
  1477     default:
  1478         return SDL_SetError("Texture format not supported");
  1479     }
  1480 
  1481     if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES &&
  1482         texture->access != SDL_TEXTUREACCESS_STATIC) {
  1483         return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES");
  1484     }
  1485 
  1486     /* Allocate a texture struct */
  1487     data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
  1488     if (!data) {
  1489         return SDL_OutOfMemory();
  1490     }
  1491     data->texture = 0;
  1492 #ifdef GL_TEXTURE_EXTERNAL_OES
  1493     data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
  1494 #else
  1495     data->texture_type = GL_TEXTURE_2D;
  1496 #endif
  1497     data->pixel_format = format;
  1498     data->pixel_type = type;
  1499     data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
  1500     data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
  1501     data->texture_u = 0;
  1502     data->texture_v = 0;
  1503     scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
  1504 
  1505     /* Allocate a blob for image renderdata */
  1506     if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
  1507         size_t size;
  1508         data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
  1509         size = texture->h * data->pitch;
  1510         if (data->yuv) {
  1511             /* Need to add size for the U and V planes */
  1512             size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
  1513         } else if (data->nv12) {
  1514             /* Need to add size for the U/V plane */
  1515             size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
  1516         }
  1517         data->pixel_data = SDL_calloc(1, size);
  1518         if (!data->pixel_data) {
  1519             SDL_free(data);
  1520             return SDL_OutOfMemory();
  1521         }
  1522     }
  1523 
  1524     /* Allocate the texture */
  1525     GL_CheckError("", renderer);
  1526 
  1527     if (data->yuv) {
  1528         renderdata->glGenTextures(1, &data->texture_v);
  1529         if (GL_CheckError("glGenTexures()", renderer) < 0) {
  1530             return -1;
  1531         }
  1532         renderdata->glActiveTexture(GL_TEXTURE2);
  1533         renderdata->glBindTexture(data->texture_type, data->texture_v);
  1534         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1535         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1536         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  1537         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  1538         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
  1539 
  1540         renderdata->glGenTextures(1, &data->texture_u);
  1541         if (GL_CheckError("glGenTexures()", renderer) < 0) {
  1542             return -1;
  1543         }
  1544         renderdata->glActiveTexture(GL_TEXTURE1);
  1545         renderdata->glBindTexture(data->texture_type, data->texture_u);
  1546         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1547         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1548         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  1549         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  1550         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
  1551         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  1552             return -1;
  1553         }
  1554     } else if (data->nv12) {
  1555         renderdata->glGenTextures(1, &data->texture_u);
  1556         if (GL_CheckError("glGenTexures()", renderer) < 0) {
  1557             return -1;
  1558         }
  1559         renderdata->glActiveTexture(GL_TEXTURE1);
  1560         renderdata->glBindTexture(data->texture_type, data->texture_u);
  1561         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1562         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1563         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  1564         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  1565         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);
  1566         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  1567             return -1;
  1568         }
  1569     }
  1570 
  1571     renderdata->glGenTextures(1, &data->texture);
  1572     if (GL_CheckError("glGenTexures()", renderer) < 0) {
  1573         return -1;
  1574     }
  1575     texture->driverdata = data;
  1576     renderdata->glActiveTexture(GL_TEXTURE0);
  1577     renderdata->glBindTexture(data->texture_type, data->texture);
  1578     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1579     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1580     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  1581     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  1582     if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
  1583         renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
  1584         if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  1585             return -1;
  1586         }
  1587     }
  1588 
  1589     if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  1590        data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
  1591     } else {
  1592        data->fbo = NULL;
  1593     }
  1594 
  1595     return GL_CheckError("", renderer);
  1596 }
  1597 
  1598 static int
  1599 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)
  1600 {
  1601     Uint8 *blob = NULL;
  1602     Uint8 *src;
  1603     int src_pitch;
  1604     int y;
  1605 
  1606     if ((width == 0) || (height == 0) || (bpp == 0)) {
  1607         return 0;  /* nothing to do */
  1608     }
  1609 
  1610     /* Reformat the texture data into a tightly packed array */
  1611     src_pitch = width * bpp;
  1612     src = (Uint8 *)pixels;
  1613     if (pitch != src_pitch) {
  1614         blob = (Uint8 *)SDL_malloc(src_pitch * height);
  1615         if (!blob) {
  1616             return SDL_OutOfMemory();
  1617         }
  1618         src = blob;
  1619         for (y = 0; y < height; ++y)
  1620         {
  1621             SDL_memcpy(src, pixels, src_pitch);
  1622             src += src_pitch;
  1623             pixels = (Uint8 *)pixels + pitch;
  1624         }
  1625         src = blob;
  1626     }
  1627 
  1628     data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
  1629     if (blob) {
  1630         SDL_free(blob);
  1631     }
  1632     return 0;
  1633 }
  1634 
  1635 static int
  1636 GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  1637                     const void *pixels, int pitch)
  1638 {
  1639     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  1640     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1641 
  1642     GLES2_ActivateRenderer(renderer);
  1643 
  1644     /* Bail out if we're supposed to update an empty rectangle */
  1645     if (rect->w <= 0 || rect->h <= 0) {
  1646         return 0;
  1647     }
  1648 
  1649     data->drawstate.texture = NULL;  /* we trash this state. */
  1650 
  1651     /* Create a texture subimage with the supplied data */
  1652     data->glBindTexture(tdata->texture_type, tdata->texture);
  1653     GLES2_TexSubImage2D(data, tdata->texture_type,
  1654                     rect->x,
  1655                     rect->y,
  1656                     rect->w,
  1657                     rect->h,
  1658                     tdata->pixel_format,
  1659                     tdata->pixel_type,
  1660                     pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
  1661 
  1662     if (tdata->yuv) {
  1663         /* Skip to the correct offset into the next texture */
  1664         pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
  1665         if (texture->format == SDL_PIXELFORMAT_YV12) {
  1666             data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1667         } else {
  1668             data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1669         }
  1670         GLES2_TexSubImage2D(data, tdata->texture_type,
  1671                 rect->x / 2,
  1672                 rect->y / 2,
  1673                 (rect->w + 1) / 2,
  1674                 (rect->h + 1) / 2,
  1675                 tdata->pixel_format,
  1676                 tdata->pixel_type,
  1677                 pixels, (pitch + 1) / 2, 1);
  1678 
  1679 
  1680         /* Skip to the correct offset into the next texture */
  1681         pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2));
  1682         if (texture->format == SDL_PIXELFORMAT_YV12) {
  1683             data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1684         } else {
  1685             data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1686         }
  1687         GLES2_TexSubImage2D(data, tdata->texture_type,
  1688                 rect->x / 2,
  1689                 rect->y / 2,
  1690                 (rect->w + 1) / 2,
  1691                 (rect->h + 1) / 2,
  1692                 tdata->pixel_format,
  1693                 tdata->pixel_type,
  1694                 pixels, (pitch + 1) / 2, 1);
  1695     } else if (tdata->nv12) {
  1696         /* Skip to the correct offset into the next texture */
  1697         pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
  1698         data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1699         GLES2_TexSubImage2D(data, tdata->texture_type,
  1700                 rect->x / 2,
  1701                 rect->y / 2,
  1702                 (rect->w + 1) / 2,
  1703                 (rect->h + 1) / 2,
  1704                 GL_LUMINANCE_ALPHA,
  1705                 GL_UNSIGNED_BYTE,
  1706                 pixels, 2 * ((pitch + 1) / 2), 2);
  1707     }
  1708 
  1709     return GL_CheckError("glTexSubImage2D()", renderer);
  1710 }
  1711 
  1712 static int
  1713 GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
  1714                     const SDL_Rect * rect,
  1715                     const Uint8 *Yplane, int Ypitch,
  1716                     const Uint8 *Uplane, int Upitch,
  1717                     const Uint8 *Vplane, int Vpitch)
  1718 {
  1719     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  1720     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1721 
  1722     GLES2_ActivateRenderer(renderer);
  1723 
  1724     /* Bail out if we're supposed to update an empty rectangle */
  1725     if (rect->w <= 0 || rect->h <= 0) {
  1726         return 0;
  1727     }
  1728 
  1729     data->drawstate.texture = NULL;  /* we trash this state. */
  1730 
  1731     data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1732     GLES2_TexSubImage2D(data, tdata->texture_type,
  1733                     rect->x / 2,
  1734                     rect->y / 2,
  1735                     (rect->w + 1) / 2,
  1736                     (rect->h + 1) / 2,
  1737                     tdata->pixel_format,
  1738                     tdata->pixel_type,
  1739                     Vplane, Vpitch, 1);
  1740 
  1741     data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1742     GLES2_TexSubImage2D(data, tdata->texture_type,
  1743                     rect->x / 2,
  1744                     rect->y / 2,
  1745                     (rect->w + 1) / 2,
  1746                     (rect->h + 1) / 2,
  1747                     tdata->pixel_format,
  1748                     tdata->pixel_type,
  1749                     Uplane, Upitch, 1);
  1750 
  1751     data->glBindTexture(tdata->texture_type, tdata->texture);
  1752     GLES2_TexSubImage2D(data, tdata->texture_type,
  1753                     rect->x,
  1754                     rect->y,
  1755                     rect->w,
  1756                     rect->h,
  1757                     tdata->pixel_format,
  1758                     tdata->pixel_type,
  1759                     Yplane, Ypitch, 1);
  1760 
  1761     return GL_CheckError("glTexSubImage2D()", renderer);
  1762 }
  1763 
  1764 static int
  1765 GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  1766                   void **pixels, int *pitch)
  1767 {
  1768     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1769 
  1770     /* Retrieve the buffer/pitch for the specified region */
  1771     *pixels = (Uint8 *)tdata->pixel_data +
  1772               (tdata->pitch * rect->y) +
  1773               (rect->x * SDL_BYTESPERPIXEL(texture->format));
  1774     *pitch = tdata->pitch;
  1775 
  1776     return 0;
  1777 }
  1778 
  1779 static void
  1780 GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  1781 {
  1782     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1783     SDL_Rect rect;
  1784 
  1785     /* We do whole texture updates, at least for now */
  1786     rect.x = 0;
  1787     rect.y = 0;
  1788     rect.w = texture->w;
  1789     rect.h = texture->h;
  1790     GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
  1791 }
  1792 
  1793 static void
  1794 GLES2_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode)
  1795 {
  1796     GLES2_RenderData *renderdata = (GLES2_RenderData *) renderer->driverdata;
  1797     GLES2_TextureData *data = (GLES2_TextureData *) texture->driverdata;
  1798     GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
  1799 
  1800     if (data->yuv) {
  1801         renderdata->glActiveTexture(GL_TEXTURE2);
  1802         renderdata->glBindTexture(data->texture_type, data->texture_v);
  1803         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1804         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1805 
  1806         renderdata->glActiveTexture(GL_TEXTURE1);
  1807         renderdata->glBindTexture(data->texture_type, data->texture_u);
  1808         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1809         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1810     } else if (data->nv12) {
  1811         renderdata->glActiveTexture(GL_TEXTURE1);
  1812         renderdata->glBindTexture(data->texture_type, data->texture_u);
  1813         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1814         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1815     }
  1816 
  1817     renderdata->glActiveTexture(GL_TEXTURE0);
  1818     renderdata->glBindTexture(data->texture_type, data->texture);
  1819     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1820     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1821 }
  1822 
  1823 static int
  1824 GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
  1825 {
  1826     GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
  1827     GLES2_TextureData *texturedata = NULL;
  1828     GLenum status;
  1829 
  1830     data->drawstate.viewport_dirty = SDL_TRUE;
  1831 
  1832     if (texture == NULL) {
  1833         data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
  1834     } else {
  1835         texturedata = (GLES2_TextureData *) texture->driverdata;
  1836         data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
  1837         /* TODO: check if texture pixel format allows this operation */
  1838         data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
  1839         /* Check FBO status */
  1840         status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
  1841         if (status != GL_FRAMEBUFFER_COMPLETE) {
  1842             return SDL_SetError("glFramebufferTexture2D() failed");
  1843         }
  1844     }
  1845     return 0;
  1846 }
  1847 
  1848 static void
  1849 GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  1850 {
  1851     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  1852     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1853 
  1854     GLES2_ActivateRenderer(renderer);
  1855 
  1856     if (data->drawstate.texture == texture) {
  1857         data->drawstate.texture = NULL;
  1858     }
  1859     if (data->drawstate.target == texture) {
  1860         data->drawstate.target = NULL;
  1861     }
  1862 
  1863     /* Destroy the texture */
  1864     if (tdata) {
  1865         data->glDeleteTextures(1, &tdata->texture);
  1866         if (tdata->texture_v) {
  1867             data->glDeleteTextures(1, &tdata->texture_v);
  1868         }
  1869         if (tdata->texture_u) {
  1870             data->glDeleteTextures(1, &tdata->texture_u);
  1871         }
  1872         SDL_free(tdata->pixel_data);
  1873         SDL_free(tdata);
  1874         texture->driverdata = NULL;
  1875     }
  1876 }
  1877 
  1878 static int
  1879 GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1880                     Uint32 pixel_format, void * pixels, int pitch)
  1881 {
  1882     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  1883     Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
  1884     size_t buflen;
  1885     void *temp_pixels;
  1886     int temp_pitch;
  1887     Uint8 *src, *dst, *tmp;
  1888     int w, h, length, rows;
  1889     int status;
  1890 
  1891     temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
  1892     buflen = rect->h * temp_pitch;
  1893     if (buflen == 0) {
  1894         return 0;  /* nothing to do. */
  1895     }
  1896 
  1897     temp_pixels = SDL_malloc(buflen);
  1898     if (!temp_pixels) {
  1899         return SDL_OutOfMemory();
  1900     }
  1901 
  1902     SDL_GetRendererOutputSize(renderer, &w, &h);
  1903 
  1904     data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
  1905                        rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
  1906     if (GL_CheckError("glReadPixels()", renderer) < 0) {
  1907         return -1;
  1908     }
  1909 
  1910     /* Flip the rows to be top-down if necessary */
  1911     if (!renderer->target) {
  1912         SDL_bool isstack;
  1913         length = rect->w * SDL_BYTESPERPIXEL(temp_format);
  1914         src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
  1915         dst = (Uint8*)temp_pixels;
  1916         tmp = SDL_small_alloc(Uint8, length, &isstack);
  1917         rows = rect->h / 2;
  1918         while (rows--) {
  1919             SDL_memcpy(tmp, dst, length);
  1920             SDL_memcpy(dst, src, length);
  1921             SDL_memcpy(src, tmp, length);
  1922             dst += temp_pitch;
  1923             src -= temp_pitch;
  1924         }
  1925         SDL_small_free(tmp, isstack);
  1926     }
  1927 
  1928     status = SDL_ConvertPixels(rect->w, rect->h,
  1929                                temp_format, temp_pixels, temp_pitch,
  1930                                pixel_format, pixels, pitch);
  1931     SDL_free(temp_pixels);
  1932 
  1933     return status;
  1934 }
  1935 
  1936 static void
  1937 GLES2_RenderPresent(SDL_Renderer *renderer)
  1938 {
  1939     /* Tell the video driver to swap buffers */
  1940     SDL_GL_SwapWindow(renderer->window);
  1941 }
  1942 
  1943 
  1944 /*************************************************************************************************
  1945  * Bind/unbinding of textures
  1946  *************************************************************************************************/
  1947 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
  1948 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
  1949 
  1950 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
  1951 {
  1952     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  1953     GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  1954     GLES2_ActivateRenderer(renderer);
  1955 
  1956     data->glBindTexture(texturedata->texture_type, texturedata->texture);
  1957     data->drawstate.texture = texture;
  1958 
  1959     if (texw) {
  1960         *texw = 1.0;
  1961     }
  1962     if (texh) {
  1963         *texh = 1.0;
  1964     }
  1965 
  1966     return 0;
  1967 }
  1968 
  1969 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
  1970 {
  1971     GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
  1972     GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  1973     GLES2_ActivateRenderer(renderer);
  1974 
  1975     data->glBindTexture(texturedata->texture_type, 0);
  1976     data->drawstate.texture = NULL;
  1977 
  1978     return 0;
  1979 }
  1980 
  1981 
  1982 /*************************************************************************************************
  1983  * Renderer instantiation                                                                        *
  1984  *************************************************************************************************/
  1985 
  1986 #ifdef ZUNE_HD
  1987 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
  1988 #endif
  1989 
  1990 
  1991 static SDL_Renderer *
  1992 GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
  1993 {
  1994     SDL_Renderer *renderer;
  1995     GLES2_RenderData *data;
  1996     GLint nFormats;
  1997 #ifndef ZUNE_HD
  1998     GLboolean hasCompiler;
  1999 #endif
  2000     Uint32 window_flags = 0; /* -Wconditional-uninitialized */
  2001     GLint window_framebuffer;
  2002     GLint value;
  2003     int profile_mask = 0, major = 0, minor = 0;
  2004     SDL_bool changed_window = SDL_FALSE;
  2005 
  2006     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask) < 0) {
  2007         goto error;
  2008     }
  2009     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major) < 0) {
  2010         goto error;
  2011     }
  2012     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor) < 0) {
  2013         goto error;
  2014     }
  2015 
  2016     window_flags = SDL_GetWindowFlags(window);
  2017 
  2018     /* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */
  2019     if (!(window_flags & SDL_WINDOW_OPENGL) ||
  2020         profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major < RENDERER_CONTEXT_MAJOR) {
  2021 
  2022         changed_window = SDL_TRUE;
  2023         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
  2024         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
  2025         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
  2026 
  2027         if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
  2028             goto error;
  2029         }
  2030     }
  2031 
  2032     /* Create the renderer struct */
  2033     renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
  2034     if (!renderer) {
  2035         SDL_OutOfMemory();
  2036         goto error;
  2037     }
  2038 
  2039     data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
  2040     if (!data) {
  2041         SDL_free(renderer);
  2042         SDL_OutOfMemory();
  2043         goto error;
  2044     }
  2045     renderer->info = GLES2_RenderDriver.info;
  2046     renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
  2047     renderer->driverdata = data;
  2048     renderer->window = window;
  2049 
  2050     /* Create an OpenGL ES 2.0 context */
  2051     data->context = SDL_GL_CreateContext(window);
  2052     if (!data->context) {
  2053         SDL_free(renderer);
  2054         SDL_free(data);
  2055         goto error;
  2056     }
  2057     if (SDL_GL_MakeCurrent(window, data->context) < 0) {
  2058         SDL_GL_DeleteContext(data->context);
  2059         SDL_free(renderer);
  2060         SDL_free(data);
  2061         goto error;
  2062     }
  2063 
  2064     if (GLES2_LoadFunctions(data) < 0) {
  2065         SDL_GL_DeleteContext(data->context);
  2066         SDL_free(renderer);
  2067         SDL_free(data);
  2068         goto error;
  2069     }
  2070 
  2071 #if __WINRT__
  2072     /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync
  2073      * is turned on.  Not doing so will freeze the screen's contents to that
  2074      * of the first drawn frame.
  2075      */
  2076     flags |= SDL_RENDERER_PRESENTVSYNC;
  2077 #endif
  2078 
  2079     if (flags & SDL_RENDERER_PRESENTVSYNC) {
  2080         SDL_GL_SetSwapInterval(1);
  2081     } else {
  2082         SDL_GL_SetSwapInterval(0);
  2083     }
  2084     if (SDL_GL_GetSwapInterval() > 0) {
  2085         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
  2086     }
  2087 
  2088     /* Check for debug output support */
  2089     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
  2090         (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
  2091         data->debug_enabled = SDL_TRUE;
  2092     }
  2093 
  2094     value = 0;
  2095     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
  2096     renderer->info.max_texture_width = value;
  2097     value = 0;
  2098     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
  2099     renderer->info.max_texture_height = value;
  2100 
  2101     /* Determine supported shader formats */
  2102     /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
  2103 #ifdef ZUNE_HD
  2104     nFormats = 1;
  2105 #else /* !ZUNE_HD */
  2106     data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
  2107     data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
  2108     if (hasCompiler) {
  2109         ++nFormats;
  2110     }
  2111 #endif /* ZUNE_HD */
  2112     data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
  2113     if (!data->shader_formats) {
  2114         GLES2_DestroyRenderer(renderer);
  2115         SDL_OutOfMemory();
  2116         goto error;
  2117     }
  2118     data->shader_format_count = nFormats;
  2119 #ifdef ZUNE_HD
  2120     data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
  2121 #else /* !ZUNE_HD */
  2122     data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats);
  2123     if (hasCompiler) {
  2124         data->shader_formats[nFormats - 1] = (GLenum)-1;
  2125     }
  2126 #endif /* ZUNE_HD */
  2127 
  2128     /* we keep a few of these and cycle through them, so data can live for a few frames. */
  2129     data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
  2130 
  2131     data->framebuffers = NULL;
  2132     data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
  2133     data->window_framebuffer = (GLuint)window_framebuffer;
  2134 
  2135     /* Populate the function pointers for the module */
  2136     renderer->WindowEvent         = GLES2_WindowEvent;
  2137     renderer->GetOutputSize       = GLES2_GetOutputSize;
  2138     renderer->SupportsBlendMode   = GLES2_SupportsBlendMode;
  2139     renderer->CreateTexture       = GLES2_CreateTexture;
  2140     renderer->UpdateTexture       = GLES2_UpdateTexture;
  2141     renderer->UpdateTextureYUV    = GLES2_UpdateTextureYUV;
  2142     renderer->LockTexture         = GLES2_LockTexture;
  2143     renderer->UnlockTexture       = GLES2_UnlockTexture;
  2144     renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode;
  2145     renderer->SetRenderTarget     = GLES2_SetRenderTarget;
  2146     renderer->QueueSetViewport    = GLES2_QueueSetViewport;
  2147     renderer->QueueSetDrawColor   = GLES2_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
  2148     renderer->QueueDrawPoints     = GLES2_QueueDrawPoints;
  2149     renderer->QueueDrawLines      = GLES2_QueueDrawLines;
  2150     renderer->QueueFillRects      = GLES2_QueueFillRects;
  2151     renderer->QueueCopy           = GLES2_QueueCopy;
  2152     renderer->QueueCopyEx         = GLES2_QueueCopyEx;
  2153     renderer->RunCommandQueue     = GLES2_RunCommandQueue;
  2154     renderer->RenderReadPixels    = GLES2_RenderReadPixels;
  2155     renderer->RenderPresent       = GLES2_RenderPresent;
  2156     renderer->DestroyTexture      = GLES2_DestroyTexture;
  2157     renderer->DestroyRenderer     = GLES2_DestroyRenderer;
  2158     renderer->GL_BindTexture      = GLES2_BindTexture;
  2159     renderer->GL_UnbindTexture    = GLES2_UnbindTexture;
  2160 
  2161     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
  2162     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
  2163     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
  2164     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
  2165 #ifdef GL_TEXTURE_EXTERNAL_OES
  2166     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_EXTERNAL_OES;
  2167 #endif
  2168 
  2169     /* Set up parameters for rendering */
  2170     data->glActiveTexture(GL_TEXTURE0);
  2171     data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
  2172     data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  2173 
  2174     data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
  2175     data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  2176 
  2177     data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  2178 
  2179     data->drawstate.blend = SDL_BLENDMODE_INVALID;
  2180     data->drawstate.color = 0xFFFFFFFF;
  2181     data->drawstate.clear_color = 0xFFFFFFFF;
  2182     data->drawstate.projection[3][0] = -1.0f;
  2183     data->drawstate.projection[3][3] = 1.0f;
  2184 
  2185     GL_CheckError("", renderer);
  2186 
  2187     return renderer;
  2188 
  2189 error:
  2190     if (changed_window) {
  2191         /* Uh oh, better try to put it back... */
  2192         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
  2193         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
  2194         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
  2195         SDL_RecreateWindow(window, window_flags);
  2196     }
  2197     return NULL;
  2198 }
  2199 
  2200 SDL_RenderDriver GLES2_RenderDriver = {
  2201     GLES2_CreateRenderer,
  2202     {
  2203         "opengles2",
  2204         (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
  2205         4,
  2206         {
  2207         SDL_PIXELFORMAT_ARGB8888,
  2208         SDL_PIXELFORMAT_ABGR8888,
  2209         SDL_PIXELFORMAT_RGB888,
  2210         SDL_PIXELFORMAT_BGR888
  2211         },
  2212         0,
  2213         0
  2214     }
  2215 };
  2216 
  2217 #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
  2218 
  2219 /* vi: set ts=4 sw=4 expandtab: */