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