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