src/render/opengles2/SDL_render_gles2.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 02 Feb 2014 00:53:27 -0800
changeset 8149 681eb46b8ac4
parent 8093 b43765095a6f
child 8192 560c66a04082
permissions -rw-r--r--
Fixed bug 2374 - Update copyright for 2014...

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