cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_render_gles2.c (70889B)


      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 */
     38extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
     39
     40/*************************************************************************************************
     41 * Bootstrap data                                                                                *
     42 *************************************************************************************************/
     43
     44static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags);
     45
     46SDL_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
     67typedef struct GLES2_FBOList GLES2_FBOList;
     68
     69struct GLES2_FBOList
     70{
     71   Uint32 w, h;
     72   GLuint FBO;
     73   GLES2_FBOList *next;
     74};
     75
     76typedef 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
     92typedef 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
    103typedef struct GLES2_ShaderCache
    104{
    105    int count;
    106    GLES2_ShaderCacheEntry *head;
    107} GLES2_ShaderCache;
    108
    109typedef 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
    123typedef struct GLES2_ProgramCache
    124{
    125    int count;
    126    GLES2_ProgramCacheEntry *head;
    127    GLES2_ProgramCacheEntry *tail;
    128} GLES2_ProgramCache;
    129
    130typedef 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
    138typedef 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
    148typedef 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
    160typedef 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
    188SDL_FORCE_INLINE const char*
    189GL_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
    204SDL_FORCE_INLINE void
    205GL_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
    218SDL_FORCE_INLINE int
    219GL_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
    257static int GLES2_ActivateRenderer(SDL_Renderer *renderer);
    258static void GLES2_WindowEvent(SDL_Renderer * renderer,
    259                              const SDL_WindowEvent *event);
    260static int GLES2_UpdateViewport(SDL_Renderer * renderer);
    261static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
    262static int GLES2_SetOrthographicProjection(SDL_Renderer *renderer);
    263
    264
    265static SDL_GLContext SDL_CurrentContext = NULL;
    266
    267static 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
    294GLES2_FBOList *
    295GLES2_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
    314static int
    315GLES2_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
    336static void
    337GLES2_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
    354static int
    355GLES2_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
    373static int
    374GLES2_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
    393static void
    394GLES2_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
    445static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
    446static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
    447                               const void *pixels, int pitch);
    448static 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);
    453static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
    454                             void **pixels, int *pitch);
    455static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
    456static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
    457static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
    458
    459static GLenum
    460GetScaleQuality(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
    471static int
    472GLES2_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
    612static int
    613GLES2_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
    645static int
    646GLES2_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
    720static int
    721GLES2_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
    769static int
    770GLES2_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
    784static void
    785GLES2_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
    798static int
    799GLES2_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
    821static void
    822GLES2_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
    849static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type,
    850                                                 SDL_BlendMode blendMode);
    851static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
    852static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer,
    853                                                   GLES2_ShaderCacheEntry *vertex,
    854                                                   GLES2_ShaderCacheEntry *fragment,
    855                                                   SDL_BlendMode blendMode);
    856static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source,
    857                               SDL_BlendMode blendMode);
    858
    859static GLES2_ProgramCacheEntry *
    860GLES2_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
    981static GLES2_ShaderCacheEntry *
    982GLES2_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
   1087static void
   1088GLES2_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
   1106static int
   1107GLES2_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;
   1178fault:
   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
   1187static int
   1188GLES2_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
   1237static const float inv255f = 1.0f / 255.0f;
   1238
   1239static int GLES2_RenderClear(SDL_Renderer *renderer);
   1240static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
   1241static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
   1242static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count);
   1243static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
   1244                            const SDL_FRect *dstrect);
   1245static 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);
   1248static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
   1249                    Uint32 pixel_format, void * pixels, int pitch);
   1250static void GLES2_RenderPresent(SDL_Renderer *renderer);
   1251
   1252static SDL_bool
   1253CompareColors(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
   1262static int
   1263GLES2_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
   1303static void
   1304GLES2_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
   1329static void
   1330GLES2_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
   1342static int
   1343GLES2_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
   1388static int
   1389GLES2_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
   1414static int
   1415GLES2_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
   1447static int
   1448GLES2_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
   1481static int
   1482GLES2_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
   1648static int
   1649GLES2_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
   1686static int
   1687GLES2_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
   1750static int
   1751GLES2_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
   1801static void
   1802GLES2_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 *************************************************************************************************/
   1814static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
   1815static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
   1816
   1817static 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
   1831static 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
   1849static void
   1850GLES2_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
   1878static SDL_Renderer *
   1879GLES2_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
   2037error:
   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: */