src/render/opengles2/SDL_render_gles2.c
author Alex Szpakowski <slime73@gmail.com>
Thu, 10 Dec 2015 20:25:34 -0400
changeset 9958 687e118144c7
parent 9739 306e09b65660
child 9977 f9cd179cf50e
permissions -rw-r--r--
SDL_GL_GetAttribute: If a GL context isn't active, only return failure when the specified attribute needs an active GL context to be queried.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2015 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 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_GetRendererOutputSize(renderer, &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_GetRendererOutputSize(renderer, &w, &h);
   421             data->glScissor(renderer->viewport.x + rect->x, (h - renderer->viewport.y - renderer->viewport.h) + rect->y, 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 **)&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     data->glClear(GL_COLOR_BUFFER_BIT);
  1331 
  1332     return 0;
  1333 }
  1334 
  1335 static void
  1336 GLES2_SetBlendMode(GLES2_DriverContext *data, int blendMode)
  1337 {
  1338     if (blendMode != data->current.blendMode) {
  1339         switch (blendMode) {
  1340         default:
  1341         case SDL_BLENDMODE_NONE:
  1342             data->glDisable(GL_BLEND);
  1343             break;
  1344         case SDL_BLENDMODE_BLEND:
  1345             data->glEnable(GL_BLEND);
  1346             data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  1347             break;
  1348         case SDL_BLENDMODE_ADD:
  1349             data->glEnable(GL_BLEND);
  1350             data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
  1351             break;
  1352         case SDL_BLENDMODE_MOD:
  1353             data->glEnable(GL_BLEND);
  1354             data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
  1355             break;
  1356         }
  1357         data->current.blendMode = blendMode;
  1358     }
  1359 }
  1360 
  1361 static void
  1362 GLES2_SetTexCoords(GLES2_DriverContext * data, SDL_bool enabled)
  1363 {
  1364     if (enabled != data->current.tex_coords) {
  1365         if (enabled) {
  1366             data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  1367         } else {
  1368             data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  1369         }
  1370         data->current.tex_coords = enabled;
  1371     }
  1372 }
  1373 
  1374 static int
  1375 GLES2_SetDrawingState(SDL_Renderer * renderer)
  1376 {
  1377     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1378     const int blendMode = renderer->blendMode;
  1379     GLES2_ProgramCacheEntry *program;
  1380     Uint8 r, g, b, a;
  1381 
  1382     GLES2_ActivateRenderer(renderer);
  1383 
  1384     GLES2_SetBlendMode(data, blendMode);
  1385 
  1386     GLES2_SetTexCoords(data, SDL_FALSE);
  1387 
  1388     /* Activate an appropriate shader and set the projection matrix */
  1389     if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0) {
  1390         return -1;
  1391     }
  1392 
  1393     /* Select the color to draw with */
  1394     g = renderer->g;
  1395     a = renderer->a;
  1396 
  1397     if (renderer->target &&
  1398          (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
  1399          renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
  1400         r = renderer->b;
  1401         b = renderer->r;
  1402      } else {
  1403         r = renderer->r;
  1404         b = renderer->b;
  1405      }
  1406 
  1407     program = data->current_program;
  1408     if (!CompareColors(program->color_r, program->color_g, program->color_b, program->color_a, r, g, b, a)) {
  1409         /* Select the color to draw with */
  1410         data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
  1411         program->color_r = r;
  1412         program->color_g = g;
  1413         program->color_b = b;
  1414         program->color_a = a;
  1415     }
  1416 
  1417     return 0;
  1418 }
  1419 
  1420 static int
  1421 GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
  1422                          const void *vertexData, size_t dataSizeInBytes)
  1423 {
  1424     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1425 
  1426 #if !SDL_GLES2_USE_VBOS
  1427     data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
  1428 #else
  1429     if (!data->vertex_buffers[attr]) {
  1430         data->glGenBuffers(1, &data->vertex_buffers[attr]);
  1431     }
  1432 
  1433     data->glBindBuffer(GL_ARRAY_BUFFER, data->vertex_buffers[attr]);
  1434 
  1435     if (data->vertex_buffer_size[attr] < dataSizeInBytes) {
  1436         data->glBufferData(GL_ARRAY_BUFFER, dataSizeInBytes, vertexData, GL_STREAM_DRAW);
  1437         data->vertex_buffer_size[attr] = dataSizeInBytes;
  1438     } else {
  1439         data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
  1440     }
  1441 
  1442     data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
  1443 #endif
  1444 
  1445     return 0;
  1446 }
  1447 
  1448 static int
  1449 GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
  1450 {
  1451     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1452     GLfloat *vertices;
  1453     int idx;
  1454 
  1455     if (GLES2_SetDrawingState(renderer) < 0) {
  1456         return -1;
  1457     }
  1458 
  1459     /* Emit the specified vertices as points */
  1460     vertices = SDL_stack_alloc(GLfloat, count * 2);
  1461     for (idx = 0; idx < count; ++idx) {
  1462         GLfloat x = points[idx].x + 0.5f;
  1463         GLfloat y = points[idx].y + 0.5f;
  1464 
  1465         vertices[idx * 2] = x;
  1466         vertices[(idx * 2) + 1] = y;
  1467     }
  1468     /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
  1469     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
  1470     data->glDrawArrays(GL_POINTS, 0, count);
  1471     SDL_stack_free(vertices);
  1472     return 0;
  1473 }
  1474 
  1475 static int
  1476 GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
  1477 {
  1478     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1479     GLfloat *vertices;
  1480     int idx;
  1481 
  1482     if (GLES2_SetDrawingState(renderer) < 0) {
  1483         return -1;
  1484     }
  1485 
  1486     /* Emit a line strip including the specified vertices */
  1487     vertices = SDL_stack_alloc(GLfloat, count * 2);
  1488     for (idx = 0; idx < count; ++idx) {
  1489         GLfloat x = points[idx].x + 0.5f;
  1490         GLfloat y = points[idx].y + 0.5f;
  1491 
  1492         vertices[idx * 2] = x;
  1493         vertices[(idx * 2) + 1] = y;
  1494     }
  1495     /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
  1496     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat));
  1497     data->glDrawArrays(GL_LINE_STRIP, 0, count);
  1498 
  1499     /* We need to close the endpoint of the line */
  1500     if (count == 2 ||
  1501         points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
  1502         data->glDrawArrays(GL_POINTS, count-1, 1);
  1503     }
  1504     SDL_stack_free(vertices);
  1505 
  1506     return GL_CheckError("", renderer);
  1507 }
  1508 
  1509 static int
  1510 GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
  1511 {
  1512     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1513     GLfloat vertices[8];
  1514     int idx;
  1515 
  1516     if (GLES2_SetDrawingState(renderer) < 0) {
  1517         return -1;
  1518     }
  1519 
  1520     /* Emit a line loop for each rectangle */
  1521     for (idx = 0; idx < count; ++idx) {
  1522         const SDL_FRect *rect = &rects[idx];
  1523 
  1524         GLfloat xMin = rect->x;
  1525         GLfloat xMax = (rect->x + rect->w);
  1526         GLfloat yMin = rect->y;
  1527         GLfloat yMax = (rect->y + rect->h);
  1528 
  1529         vertices[0] = xMin;
  1530         vertices[1] = yMin;
  1531         vertices[2] = xMax;
  1532         vertices[3] = yMin;
  1533         vertices[4] = xMin;
  1534         vertices[5] = yMax;
  1535         vertices[6] = xMax;
  1536         vertices[7] = yMax;
  1537         /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
  1538         GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
  1539         data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1540     }
  1541     return GL_CheckError("", renderer);
  1542 }
  1543 
  1544 static int
  1545 GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
  1546 {
  1547     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1548     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1549     GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1550     SDL_BlendMode blendMode;
  1551     GLES2_ProgramCacheEntry *program;
  1552     Uint8 r, g, b, a;
  1553 
  1554     /* Activate an appropriate shader and set the projection matrix */
  1555     blendMode = texture->blendMode;
  1556     if (renderer->target) {
  1557         /* Check if we need to do color mapping between the source and render target textures */
  1558         if (renderer->target->format != texture->format) {
  1559             switch (texture->format) {
  1560             case SDL_PIXELFORMAT_ARGB8888:
  1561                 switch (renderer->target->format) {
  1562                 case SDL_PIXELFORMAT_ABGR8888:
  1563                 case SDL_PIXELFORMAT_BGR888:
  1564                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1565                     break;
  1566                 case SDL_PIXELFORMAT_RGB888:
  1567                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1568                     break;
  1569                 }
  1570                 break;
  1571             case SDL_PIXELFORMAT_ABGR8888:
  1572                 switch (renderer->target->format) {
  1573                 case SDL_PIXELFORMAT_ARGB8888:
  1574                 case SDL_PIXELFORMAT_RGB888:
  1575                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1576                     break;
  1577                 case SDL_PIXELFORMAT_BGR888:
  1578                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1579                     break;
  1580                 }
  1581                 break;
  1582             case SDL_PIXELFORMAT_RGB888:
  1583                 switch (renderer->target->format) {
  1584                 case SDL_PIXELFORMAT_ABGR8888:
  1585                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1586                     break;
  1587                 case SDL_PIXELFORMAT_ARGB8888:
  1588                     sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1589                     break;
  1590                 case SDL_PIXELFORMAT_BGR888:
  1591                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1592                     break;
  1593                 }
  1594                 break;
  1595             case SDL_PIXELFORMAT_BGR888:
  1596                 switch (renderer->target->format) {
  1597                 case SDL_PIXELFORMAT_ABGR8888:
  1598                     sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1599                     break;
  1600                 case SDL_PIXELFORMAT_ARGB8888:
  1601                     sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1602                     break;
  1603                 case SDL_PIXELFORMAT_RGB888:
  1604                     sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1605                     break;
  1606                 }
  1607                 break;
  1608             case SDL_PIXELFORMAT_IYUV:
  1609             case SDL_PIXELFORMAT_YV12:
  1610                 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
  1611                 break;
  1612             case SDL_PIXELFORMAT_NV12:
  1613                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
  1614                 break;
  1615             case SDL_PIXELFORMAT_NV21:
  1616                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
  1617                 break;
  1618             default:
  1619                 return SDL_SetError("Unsupported texture format");
  1620             }
  1621         } else {
  1622             sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;   /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
  1623         }
  1624     } else {
  1625         switch (texture->format) {
  1626             case SDL_PIXELFORMAT_ARGB8888:
  1627                 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1628                 break;
  1629             case SDL_PIXELFORMAT_ABGR8888:
  1630                 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1631                 break;
  1632             case SDL_PIXELFORMAT_RGB888:
  1633                 sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1634                 break;
  1635             case SDL_PIXELFORMAT_BGR888:
  1636                 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1637                 break;
  1638             case SDL_PIXELFORMAT_IYUV:
  1639             case SDL_PIXELFORMAT_YV12:
  1640                 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
  1641                 break;
  1642             case SDL_PIXELFORMAT_NV12:
  1643                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
  1644                 break;
  1645             case SDL_PIXELFORMAT_NV21:
  1646                 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
  1647                 break;
  1648             default:
  1649                 return SDL_SetError("Unsupported texture format");
  1650         }
  1651     }
  1652 
  1653     if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0) {
  1654         return -1;
  1655     }
  1656 
  1657     /* Select the target texture */
  1658     if (tdata->yuv) {
  1659         data->glActiveTexture(GL_TEXTURE2);
  1660         data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1661 
  1662         data->glActiveTexture(GL_TEXTURE1);
  1663         data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1664 
  1665         data->glActiveTexture(GL_TEXTURE0);
  1666     }
  1667     if (tdata->nv12) {
  1668         data->glActiveTexture(GL_TEXTURE1);
  1669         data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1670 
  1671         data->glActiveTexture(GL_TEXTURE0);
  1672     }
  1673     data->glBindTexture(tdata->texture_type, tdata->texture);
  1674 
  1675     /* Configure color modulation */
  1676     g = texture->g;
  1677     a = texture->a;
  1678 
  1679     if (renderer->target &&
  1680         (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
  1681          renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
  1682         r = texture->b;
  1683         b = texture->r;
  1684     } else {
  1685         r = texture->r;
  1686         b = texture->b;
  1687     }
  1688 
  1689     program = data->current_program;
  1690 
  1691     if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
  1692         data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
  1693         program->modulation_r = r;
  1694         program->modulation_g = g;
  1695         program->modulation_b = b;
  1696         program->modulation_a = a;
  1697     }
  1698 
  1699     /* Configure texture blending */
  1700     GLES2_SetBlendMode(data, blendMode);
  1701 
  1702     GLES2_SetTexCoords(data, SDL_TRUE);
  1703     return 0;
  1704 }
  1705 
  1706 static int
  1707 GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  1708                  const SDL_FRect *dstrect)
  1709 {
  1710     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1711     GLfloat vertices[8];
  1712     GLfloat texCoords[8];
  1713 
  1714     GLES2_ActivateRenderer(renderer);
  1715 
  1716     if (GLES2_SetupCopy(renderer, texture) < 0) {
  1717         return -1;
  1718     }
  1719 
  1720     /* Emit the textured quad */
  1721     vertices[0] = dstrect->x;
  1722     vertices[1] = dstrect->y;
  1723     vertices[2] = (dstrect->x + dstrect->w);
  1724     vertices[3] = dstrect->y;
  1725     vertices[4] = dstrect->x;
  1726     vertices[5] = (dstrect->y + dstrect->h);
  1727     vertices[6] = (dstrect->x + dstrect->w);
  1728     vertices[7] = (dstrect->y + dstrect->h);
  1729     /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
  1730     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
  1731     texCoords[0] = srcrect->x / (GLfloat)texture->w;
  1732     texCoords[1] = srcrect->y / (GLfloat)texture->h;
  1733     texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1734     texCoords[3] = srcrect->y / (GLfloat)texture->h;
  1735     texCoords[4] = srcrect->x / (GLfloat)texture->w;
  1736     texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1737     texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1738     texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1739     /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
  1740     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
  1741     data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1742 
  1743     return GL_CheckError("", renderer);
  1744 }
  1745 
  1746 static int
  1747 GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  1748                  const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
  1749 {
  1750     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1751     GLfloat vertices[8];
  1752     GLfloat texCoords[8];
  1753     GLfloat translate[8];
  1754     GLfloat fAngle[4];
  1755     GLfloat tmp;
  1756 
  1757     GLES2_ActivateRenderer(renderer);
  1758 
  1759     if (GLES2_SetupCopy(renderer, texture) < 0) {
  1760         return -1;
  1761     }
  1762 
  1763     data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
  1764     data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
  1765     fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
  1766     /* Calculate the center of rotation */
  1767     translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
  1768     translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
  1769 
  1770     /* Emit the textured quad */
  1771     vertices[0] = dstrect->x;
  1772     vertices[1] = dstrect->y;
  1773     vertices[2] = (dstrect->x + dstrect->w);
  1774     vertices[3] = dstrect->y;
  1775     vertices[4] = dstrect->x;
  1776     vertices[5] = (dstrect->y + dstrect->h);
  1777     vertices[6] = (dstrect->x + dstrect->w);
  1778     vertices[7] = (dstrect->y + dstrect->h);
  1779     if (flip & SDL_FLIP_HORIZONTAL) {
  1780         tmp = vertices[0];
  1781         vertices[0] = vertices[4] = vertices[2];
  1782         vertices[2] = vertices[6] = tmp;
  1783     }
  1784     if (flip & SDL_FLIP_VERTICAL) {
  1785         tmp = vertices[1];
  1786         vertices[1] = vertices[3] = vertices[5];
  1787         vertices[5] = vertices[7] = tmp;
  1788     }
  1789 
  1790     /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
  1791     data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
  1792     data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
  1793 
  1794     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
  1795     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
  1796     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
  1797 
  1798     texCoords[0] = srcrect->x / (GLfloat)texture->w;
  1799     texCoords[1] = srcrect->y / (GLfloat)texture->h;
  1800     texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1801     texCoords[3] = srcrect->y / (GLfloat)texture->h;
  1802     texCoords[4] = srcrect->x / (GLfloat)texture->w;
  1803     texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1804     texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1805     texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1806     /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/
  1807     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat));
  1808     data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1809     data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
  1810     data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
  1811 
  1812     return GL_CheckError("", renderer);
  1813 }
  1814 
  1815 static int
  1816 GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1817                     Uint32 pixel_format, void * pixels, int pitch)
  1818 {
  1819     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1820     Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
  1821     void *temp_pixels;
  1822     int temp_pitch;
  1823     Uint8 *src, *dst, *tmp;
  1824     int w, h, length, rows;
  1825     int status;
  1826 
  1827     GLES2_ActivateRenderer(renderer);
  1828 
  1829     temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
  1830     temp_pixels = SDL_malloc(rect->h * temp_pitch);
  1831     if (!temp_pixels) {
  1832         return SDL_OutOfMemory();
  1833     }
  1834 
  1835     SDL_GetRendererOutputSize(renderer, &w, &h);
  1836 
  1837     data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
  1838                        GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
  1839     if (GL_CheckError("glReadPixels()", renderer) < 0) {
  1840         return -1;
  1841     }
  1842 
  1843     /* Flip the rows to be top-down */
  1844     length = rect->w * SDL_BYTESPERPIXEL(temp_format);
  1845     src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
  1846     dst = (Uint8*)temp_pixels;
  1847     tmp = SDL_stack_alloc(Uint8, length);
  1848     rows = rect->h / 2;
  1849     while (rows--) {
  1850         SDL_memcpy(tmp, dst, length);
  1851         SDL_memcpy(dst, src, length);
  1852         SDL_memcpy(src, tmp, length);
  1853         dst += temp_pitch;
  1854         src -= temp_pitch;
  1855     }
  1856     SDL_stack_free(tmp);
  1857 
  1858     status = SDL_ConvertPixels(rect->w, rect->h,
  1859                                temp_format, temp_pixels, temp_pitch,
  1860                                pixel_format, pixels, pitch);
  1861     SDL_free(temp_pixels);
  1862 
  1863     return status;
  1864 }
  1865 
  1866 static void
  1867 GLES2_RenderPresent(SDL_Renderer *renderer)
  1868 {
  1869     GLES2_ActivateRenderer(renderer);
  1870 
  1871     /* Tell the video driver to swap buffers */
  1872     SDL_GL_SwapWindow(renderer->window);
  1873 }
  1874 
  1875 
  1876 /*************************************************************************************************
  1877  * Bind/unbinding of textures
  1878  *************************************************************************************************/
  1879 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
  1880 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
  1881 
  1882 static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
  1883 {
  1884     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1885     GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  1886     GLES2_ActivateRenderer(renderer);
  1887 
  1888     data->glBindTexture(texturedata->texture_type, texturedata->texture);
  1889 
  1890     if (texw) {
  1891         *texw = 1.0;
  1892     }
  1893     if (texh) {
  1894         *texh = 1.0;
  1895     }
  1896 
  1897     return 0;
  1898 }
  1899 
  1900 static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
  1901 {
  1902     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1903     GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  1904     GLES2_ActivateRenderer(renderer);
  1905 
  1906     data->glBindTexture(texturedata->texture_type, 0);
  1907 
  1908     return 0;
  1909 }
  1910 
  1911 
  1912 /*************************************************************************************************
  1913  * Renderer instantiation                                                                        *
  1914  *************************************************************************************************/
  1915 
  1916 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
  1917 
  1918 static void
  1919 GLES2_ResetState(SDL_Renderer *renderer)
  1920 {
  1921     GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
  1922 
  1923     if (SDL_CurrentContext == data->context) {
  1924         GLES2_UpdateViewport(renderer);
  1925     } else {
  1926         GLES2_ActivateRenderer(renderer);
  1927     }
  1928 
  1929     data->current.blendMode = -1;
  1930     data->current.tex_coords = SDL_FALSE;
  1931 
  1932     data->glActiveTexture(GL_TEXTURE0);
  1933     data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
  1934     data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  1935 
  1936     data->glClearColor((GLfloat) data->clear_r * inv255f,
  1937                         (GLfloat) data->clear_g * inv255f,
  1938                         (GLfloat) data->clear_b * inv255f,
  1939                         (GLfloat) data->clear_a * inv255f);
  1940 
  1941     data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
  1942     data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  1943 
  1944     GL_CheckError("", renderer);
  1945 }
  1946 
  1947 static SDL_Renderer *
  1948 GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
  1949 {
  1950     SDL_Renderer *renderer;
  1951     GLES2_DriverContext *data;
  1952     GLint nFormats;
  1953 #ifndef ZUNE_HD
  1954     GLboolean hasCompiler;
  1955 #endif
  1956     Uint32 window_flags;
  1957     GLint window_framebuffer;
  1958     GLint value;
  1959     int profile_mask = 0, major = 0, minor = 0;
  1960     SDL_bool changed_window = SDL_FALSE;
  1961 
  1962     SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
  1963     SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
  1964     SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
  1965 
  1966     window_flags = SDL_GetWindowFlags(window);
  1967     if (!(window_flags & SDL_WINDOW_OPENGL) ||
  1968         profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
  1969 
  1970         changed_window = SDL_TRUE;
  1971         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
  1972         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
  1973         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
  1974 
  1975         if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
  1976             goto error;
  1977         }
  1978     }
  1979 
  1980     /* Create the renderer struct */
  1981     renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
  1982     if (!renderer) {
  1983         SDL_OutOfMemory();
  1984         goto error;
  1985     }
  1986 
  1987     data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext));
  1988     if (!data) {
  1989         GLES2_DestroyRenderer(renderer);
  1990         SDL_OutOfMemory();
  1991         goto error;
  1992     }
  1993     renderer->info = GLES2_RenderDriver.info;
  1994     renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
  1995     renderer->driverdata = data;
  1996     renderer->window = window;
  1997 
  1998     /* Create an OpenGL ES 2.0 context */
  1999     data->context = SDL_GL_CreateContext(window);
  2000     if (!data->context) {
  2001         GLES2_DestroyRenderer(renderer);
  2002         goto error;
  2003     }
  2004     if (SDL_GL_MakeCurrent(window, data->context) < 0) {
  2005         GLES2_DestroyRenderer(renderer);
  2006         goto error;
  2007     }
  2008 
  2009     if (GLES2_LoadFunctions(data) < 0) {
  2010         GLES2_DestroyRenderer(renderer);
  2011         goto error;
  2012     }
  2013 
  2014 #if __WINRT__
  2015     /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync
  2016      * is turned on.  Not doing so will freeze the screen's contents to that
  2017      * of the first drawn frame.
  2018      */
  2019     flags |= SDL_RENDERER_PRESENTVSYNC;
  2020 #endif
  2021 
  2022     if (flags & SDL_RENDERER_PRESENTVSYNC) {
  2023         SDL_GL_SetSwapInterval(1);
  2024     } else {
  2025         SDL_GL_SetSwapInterval(0);
  2026     }
  2027     if (SDL_GL_GetSwapInterval() > 0) {
  2028         renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
  2029     }
  2030 
  2031     /* Check for debug output support */
  2032     if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
  2033         (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
  2034         data->debug_enabled = SDL_TRUE;
  2035     }
  2036 
  2037     value = 0;
  2038     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
  2039     renderer->info.max_texture_width = value;
  2040     value = 0;
  2041     data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
  2042     renderer->info.max_texture_height = value;
  2043 
  2044     /* Determine supported shader formats */
  2045     /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
  2046 #ifdef ZUNE_HD
  2047     nFormats = 1;
  2048 #else /* !ZUNE_HD */
  2049     data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
  2050     data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
  2051     if (hasCompiler) {
  2052         ++nFormats;
  2053     }
  2054 #endif /* ZUNE_HD */
  2055     data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
  2056     if (!data->shader_formats) {
  2057         GLES2_DestroyRenderer(renderer);
  2058         SDL_OutOfMemory();
  2059         goto error;
  2060     }
  2061     data->shader_format_count = nFormats;
  2062 #ifdef ZUNE_HD
  2063     data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
  2064 #else /* !ZUNE_HD */
  2065     data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats);
  2066     if (hasCompiler) {
  2067         data->shader_formats[nFormats - 1] = (GLenum)-1;
  2068     }
  2069 #endif /* ZUNE_HD */
  2070 
  2071     data->framebuffers = NULL;
  2072     data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
  2073     data->window_framebuffer = (GLuint)window_framebuffer;
  2074 
  2075     /* Populate the function pointers for the module */
  2076     renderer->WindowEvent         = &GLES2_WindowEvent;
  2077     renderer->GetOutputSize       = &GLES2_GetOutputSize;
  2078     renderer->CreateTexture       = &GLES2_CreateTexture;
  2079     renderer->UpdateTexture       = &GLES2_UpdateTexture;
  2080     renderer->UpdateTextureYUV    = &GLES2_UpdateTextureYUV;
  2081     renderer->LockTexture         = &GLES2_LockTexture;
  2082     renderer->UnlockTexture       = &GLES2_UnlockTexture;
  2083     renderer->SetRenderTarget     = &GLES2_SetRenderTarget;
  2084     renderer->UpdateViewport      = &GLES2_UpdateViewport;
  2085     renderer->UpdateClipRect      = &GLES2_UpdateClipRect;
  2086     renderer->RenderClear         = &GLES2_RenderClear;
  2087     renderer->RenderDrawPoints    = &GLES2_RenderDrawPoints;
  2088     renderer->RenderDrawLines     = &GLES2_RenderDrawLines;
  2089     renderer->RenderFillRects     = &GLES2_RenderFillRects;
  2090     renderer->RenderCopy          = &GLES2_RenderCopy;
  2091     renderer->RenderCopyEx        = &GLES2_RenderCopyEx;
  2092     renderer->RenderReadPixels    = &GLES2_RenderReadPixels;
  2093     renderer->RenderPresent       = &GLES2_RenderPresent;
  2094     renderer->DestroyTexture      = &GLES2_DestroyTexture;
  2095     renderer->DestroyRenderer     = &GLES2_DestroyRenderer;
  2096     renderer->GL_BindTexture      = &GLES2_BindTexture;
  2097     renderer->GL_UnbindTexture    = &GLES2_UnbindTexture;
  2098 
  2099     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
  2100     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
  2101     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
  2102     renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
  2103 
  2104     GLES2_ResetState(renderer);
  2105 
  2106     return renderer;
  2107 
  2108 error:
  2109     if (changed_window) {
  2110         /* Uh oh, better try to put it back... */
  2111         SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
  2112         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
  2113         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
  2114         SDL_RecreateWindow(window, window_flags);
  2115     }
  2116     return NULL;
  2117 }
  2118 
  2119 #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
  2120 
  2121 /* vi: set ts=4 sw=4 expandtab: */