src/render/opengles2/SDL_render_gles2.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Wed, 29 Oct 2014 20:20:47 +0100
changeset 9201 21d9f9babb30
parent 9057 8a1d9a60f9be
child 9278 8900afb78a19
child 9530 ac0885050d79
permissions -rw-r--r--
Fixed bug 2647 - Memory leak in SDL_AddHintCallback function - SDL_hints.c

Nitz

Variable entry going out of scope leaks the storage it points to, at:

/* Need to add a hint entry for this watcher */
hint = (SDL_Hint *)SDL_malloc(sizeof(*hint));
if (!hint) {
return;
}

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