src/render/opengles2/SDL_render_gles2.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 18 Oct 2017 08:52:04 -0700
changeset 11630 ad4b5d85edee
parent 11574 696d0036f442
child 11702 cf166abbde4a
permissions -rw-r--r--
Fixed bug 3821 - Allow SDL_CreateWindow and SDL_CreateRenderer with OpenGL ES 3.0 (GLES3) for Angle (Windows)

Carlos

Angle supports GLES3 but when using these functions (SDL_CreateWindow and SDL_CreateRenderer), defaults again to GLES2.0.

A current workaround (hack) to retrieve a GLES3.0 context with Angle is:

1) set

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

after InitSDL AND after calling SDL_CreateWindow (before SDL_CreateRenderer)

2) Comment lines 2032-2044 in SDL_render_gles2.c, funtion GLES2_CreateRenderer

window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {

changed_window = SDL_TRUE;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);

if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
goto error;
}
}

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