src/render/opengles/SDL_render_gles.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 28 Dec 2015 15:15:58 -0500
changeset 9977 f9cd179cf50e
parent 9958 687e118144c7
child 9998 f67cf37e9cd4
permissions -rw-r--r--
OpenGL+GLES renderers: Fixed incorrect clip rectangle coords (thanks, Marcel!).

Fixes Bugzilla #2700.
hfutrell@2739
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@9619
     3
  Copyright (C) 1997-2015 Sam Lantinga <slouken@libsdl.org>
hfutrell@2739
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
hfutrell@2739
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
hfutrell@2739
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
hfutrell@2739
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
hfutrell@2739
    22
slouken@5226
    23
#if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED
hfutrell@2739
    24
slouken@5484
    25
#include "SDL_hints.h"
hfutrell@2739
    26
#include "SDL_opengles.h"
slouken@5154
    27
#include "../SDL_sysrender.h"
hfutrell@2739
    28
gabomdq@8264
    29
/* To prevent unnecessary window recreation, 
gabomdq@8264
    30
 * these should match the defaults selected in SDL_GL_ResetAttributes 
gabomdq@8264
    31
 */
gabomdq@8264
    32
gabomdq@8257
    33
#define RENDERER_CONTEXT_MAJOR 1
gabomdq@8257
    34
#define RENDERER_CONTEXT_MINOR 1
gabomdq@8257
    35
slouken@5150
    36
#if defined(SDL_VIDEO_DRIVER_PANDORA)
lestat@3165
    37
lestat@3165
    38
/* Empty function stub to get OpenGL ES 1.x support without  */
lestat@3165
    39
/* OpenGL ES extension GL_OES_draw_texture supported         */
slouken@3139
    40
GL_API void GL_APIENTRY
slouken@3139
    41
glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height)
slouken@3099
    42
{
slouken@3139
    43
    return;
slouken@3099
    44
}
slouken@3099
    45
philipp@9709
    46
#endif /* SDL_VIDEO_DRIVER_PANDORA */
slouken@3161
    47
hfutrell@2739
    48
/* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */
hfutrell@2739
    49
slouken@6190
    50
/* Used to re-create the window with OpenGL ES capability */
slouken@6188
    51
extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
slouken@6188
    52
hfutrell@2739
    53
static const float inv255f = 1.0f / 255.0f;
hfutrell@2739
    54
hfutrell@2739
    55
static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@5147
    56
static void GLES_WindowEvent(SDL_Renderer * renderer,
slouken@5147
    57
                             const SDL_WindowEvent *event);
slime73@9530
    58
static int GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h);
hfutrell@2739
    59
static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
hfutrell@2739
    60
static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
    61
                              const SDL_Rect * rect, const void *pixels,
slouken@2753
    62
                              int pitch);
hfutrell@2739
    63
static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
    64
                            const SDL_Rect * rect, void **pixels, int *pitch);
slouken@2753
    65
static void GLES_UnlockTexture(SDL_Renderer * renderer,
slouken@2753
    66
                               SDL_Texture * texture);
slouken@6247
    67
static int GLES_SetRenderTarget(SDL_Renderer * renderer,
slouken@6246
    68
                                 SDL_Texture * texture);
slouken@5297
    69
static int GLES_UpdateViewport(SDL_Renderer * renderer);
slouken@7141
    70
static int GLES_UpdateClipRect(SDL_Renderer * renderer);
slouken@5333
    71
static int GLES_RenderClear(SDL_Renderer * renderer);
slouken@3641
    72
static int GLES_RenderDrawPoints(SDL_Renderer * renderer,
slouken@6528
    73
                                 const SDL_FPoint * points, int count);
slouken@3641
    74
static int GLES_RenderDrawLines(SDL_Renderer * renderer,
slouken@6528
    75
                                const SDL_FPoint * points, int count);
slouken@3641
    76
static int GLES_RenderFillRects(SDL_Renderer * renderer,
slouken@6528
    77
                                const SDL_FRect * rects, int count);
hfutrell@2739
    78
static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
    79
                           const SDL_Rect * srcrect,
slouken@6528
    80
                           const SDL_FRect * dstrect);
slouken@6528
    81
static int GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
    82
                         const SDL_Rect * srcrect, const SDL_FRect * dstrect,
slouken@6528
    83
                         const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
slouken@6043
    84
static int GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@6043
    85
                    Uint32 pixel_format, void * pixels, int pitch);
hfutrell@2739
    86
static void GLES_RenderPresent(SDL_Renderer * renderer);
slouken@2753
    87
static void GLES_DestroyTexture(SDL_Renderer * renderer,
slouken@2753
    88
                                SDL_Texture * texture);
hfutrell@2739
    89
static void GLES_DestroyRenderer(SDL_Renderer * renderer);
gabomdq@6414
    90
static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
gabomdq@6414
    91
static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
slouken@6232
    92
slouken@6232
    93
typedef struct GLES_FBOList GLES_FBOList;
slouken@6232
    94
slouken@6232
    95
struct GLES_FBOList
slouken@6232
    96
{
slouken@6232
    97
   Uint32 w, h;
slouken@6232
    98
   GLuint FBO;
slouken@6232
    99
   GLES_FBOList *next;
slouken@6232
   100
};
hfutrell@2739
   101
hfutrell@2739
   102
slouken@5201
   103
SDL_RenderDriver GLES_RenderDriver = {
hfutrell@2739
   104
    GLES_CreateRenderer,
hfutrell@2739
   105
    {
slouken@5203
   106
     "opengles",
slouken@8590
   107
     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
slouken@5156
   108
     1,
slouken@5156
   109
     {SDL_PIXELFORMAT_ABGR8888},
slouken@2753
   110
     0,
hfutrell@2739
   111
     0}
hfutrell@2739
   112
};
hfutrell@2739
   113
hfutrell@2739
   114
typedef struct
hfutrell@2739
   115
{
hfutrell@2739
   116
    SDL_GLContext context;
slouken@5355
   117
    struct {
slouken@5355
   118
        Uint32 color;
slouken@5355
   119
        int blendMode;
slouken@5355
   120
        SDL_bool tex_coords;
slouken@5355
   121
    } current;
slouken@2753
   122
slouken@6188
   123
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
gabomdq@7642
   124
#define SDL_PROC_OES SDL_PROC
slouken@6188
   125
#include "SDL_glesfuncs.h"
slouken@6188
   126
#undef SDL_PROC
gabomdq@7642
   127
#undef SDL_PROC_OES
slouken@6232
   128
    SDL_bool GL_OES_framebuffer_object_supported;
slouken@6232
   129
    GLES_FBOList *framebuffers;
slouken@6271
   130
    GLuint window_framebuffer;
slouken@6188
   131
slouken@2753
   132
    SDL_bool useDrawTexture;
slouken@2753
   133
    SDL_bool GL_OES_draw_texture_supported;
slouken@7502
   134
    SDL_bool GL_OES_blend_func_separate_supported;
hfutrell@2739
   135
} GLES_RenderData;
hfutrell@2739
   136
hfutrell@2739
   137
typedef struct
hfutrell@2739
   138
{
hfutrell@2739
   139
    GLuint texture;
hfutrell@2739
   140
    GLenum type;
hfutrell@2739
   141
    GLfloat texw;
hfutrell@2739
   142
    GLfloat texh;
hfutrell@2739
   143
    GLenum format;
hfutrell@2739
   144
    GLenum formattype;
hfutrell@2739
   145
    void *pixels;
hfutrell@2739
   146
    int pitch;
slouken@6232
   147
    GLES_FBOList *fbo;
hfutrell@2739
   148
} GLES_TextureData;
hfutrell@2739
   149
icculus@7037
   150
static int
hfutrell@2739
   151
GLES_SetError(const char *prefix, GLenum result)
hfutrell@2739
   152
{
hfutrell@2739
   153
    const char *error;
hfutrell@2739
   154
hfutrell@2739
   155
    switch (result) {
hfutrell@2739
   156
    case GL_NO_ERROR:
hfutrell@2739
   157
        error = "GL_NO_ERROR";
hfutrell@2739
   158
        break;
hfutrell@2739
   159
    case GL_INVALID_ENUM:
hfutrell@2739
   160
        error = "GL_INVALID_ENUM";
hfutrell@2739
   161
        break;
hfutrell@2739
   162
    case GL_INVALID_VALUE:
hfutrell@2739
   163
        error = "GL_INVALID_VALUE";
hfutrell@2739
   164
        break;
hfutrell@2739
   165
    case GL_INVALID_OPERATION:
hfutrell@2739
   166
        error = "GL_INVALID_OPERATION";
hfutrell@2739
   167
        break;
hfutrell@2739
   168
    case GL_STACK_OVERFLOW:
hfutrell@2739
   169
        error = "GL_STACK_OVERFLOW";
hfutrell@2739
   170
        break;
hfutrell@2739
   171
    case GL_STACK_UNDERFLOW:
hfutrell@2739
   172
        error = "GL_STACK_UNDERFLOW";
hfutrell@2739
   173
        break;
hfutrell@2739
   174
    case GL_OUT_OF_MEMORY:
hfutrell@2739
   175
        error = "GL_OUT_OF_MEMORY";
hfutrell@2739
   176
        break;
hfutrell@2739
   177
    default:
hfutrell@2739
   178
        error = "UNKNOWN";
hfutrell@2739
   179
        break;
hfutrell@2739
   180
    }
icculus@7037
   181
    return SDL_SetError("%s: %s", prefix, error);
hfutrell@2739
   182
}
hfutrell@2739
   183
slouken@6188
   184
static int GLES_LoadFunctions(GLES_RenderData * data)
slouken@6188
   185
{
slouken@6190
   186
#if SDL_VIDEO_DRIVER_UIKIT
slouken@6190
   187
#define __SDL_NOGETPROCADDR__
slouken@6190
   188
#elif SDL_VIDEO_DRIVER_ANDROID
slouken@6190
   189
#define __SDL_NOGETPROCADDR__
slouken@6190
   190
#elif SDL_VIDEO_DRIVER_PANDORA
slouken@6190
   191
#define __SDL_NOGETPROCADDR__
slouken@6190
   192
#endif
slouken@6190
   193
slouken@6188
   194
#ifdef __SDL_NOGETPROCADDR__
slouken@6188
   195
#define SDL_PROC(ret,func,params) data->func=func;
icculus@7643
   196
#define SDL_PROC_OES(ret,func,params) data->func=func;
slouken@6188
   197
#else
slouken@6188
   198
#define SDL_PROC(ret,func,params) \
slouken@6188
   199
    do { \
slouken@6188
   200
        data->func = SDL_GL_GetProcAddress(#func); \
slouken@6188
   201
        if ( ! data->func ) { \
icculus@7037
   202
            return SDL_SetError("Couldn't load GLES function %s: %s\n", #func, SDL_GetError()); \
slouken@6188
   203
        } \
slouken@7191
   204
    } while ( 0 );
gabomdq@7642
   205
#define SDL_PROC_OES(ret,func,params) \
gabomdq@7642
   206
    do { \
gabomdq@7642
   207
        data->func = SDL_GL_GetProcAddress(#func); \
gabomdq@7642
   208
    } while ( 0 );    
philipp@9709
   209
#endif /* __SDL_NOGETPROCADDR__ */
slouken@6188
   210
slouken@6188
   211
#include "SDL_glesfuncs.h"
slouken@6188
   212
#undef SDL_PROC
gabomdq@7642
   213
#undef SDL_PROC_OES
slouken@6188
   214
    return 0;
slouken@6188
   215
}
slouken@6188
   216
slouken@5297
   217
static SDL_GLContext SDL_CurrentContext = NULL;
slouken@5297
   218
slouken@6232
   219
GLES_FBOList *
slouken@6232
   220
GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h)
slouken@6232
   221
{
slouken@6232
   222
   GLES_FBOList *result = data->framebuffers;
slime73@9604
   223
   while ((result) && ((result->w != w) || (result->h != h)) ) {
slouken@6232
   224
       result = result->next;
slouken@6232
   225
   }
slime73@9604
   226
   if (result == NULL) {
slouken@6232
   227
       result = SDL_malloc(sizeof(GLES_FBOList));
slouken@6232
   228
       result->w = w;
slouken@6232
   229
       result->h = h;
slouken@6269
   230
       data->glGenFramebuffersOES(1, &result->FBO);
slouken@6232
   231
       result->next = data->framebuffers;
slouken@6232
   232
       data->framebuffers = result;
slouken@6232
   233
   }
slouken@6232
   234
   return result;
slouken@6232
   235
}
slouken@6232
   236
slouken@6232
   237
slouken@5297
   238
static int
slouken@5297
   239
GLES_ActivateRenderer(SDL_Renderer * renderer)
slouken@5297
   240
{
slouken@5297
   241
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@5297
   242
slouken@5297
   243
    if (SDL_CurrentContext != data->context) {
slouken@5297
   244
        if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
slouken@5297
   245
            return -1;
slouken@5297
   246
        }
slouken@5297
   247
        SDL_CurrentContext = data->context;
slouken@5297
   248
slouken@5297
   249
        GLES_UpdateViewport(renderer);
slouken@5297
   250
    }
slouken@5297
   251
    return 0;
slouken@5297
   252
}
slouken@5297
   253
slouken@5355
   254
/* This is called if we need to invalidate all of the SDL OpenGL state */
slouken@5355
   255
static void
slouken@5355
   256
GLES_ResetState(SDL_Renderer *renderer)
slouken@5355
   257
{
slouken@5355
   258
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@5355
   259
slouken@5355
   260
    if (SDL_CurrentContext == data->context) {
slouken@5355
   261
        GLES_UpdateViewport(renderer);
slouken@5355
   262
    } else {
slouken@5355
   263
        GLES_ActivateRenderer(renderer);
slouken@5355
   264
    }
slouken@5355
   265
slouken@5355
   266
    data->current.color = 0;
slouken@5355
   267
    data->current.blendMode = -1;
slouken@5355
   268
    data->current.tex_coords = SDL_FALSE;
slouken@5355
   269
slouken@6188
   270
    data->glDisable(GL_DEPTH_TEST);
slouken@6188
   271
    data->glDisable(GL_CULL_FACE);
slouken@5355
   272
slouken@6188
   273
    data->glMatrixMode(GL_MODELVIEW);
slouken@6188
   274
    data->glLoadIdentity();
slouken@5355
   275
slouken@6188
   276
    data->glEnableClientState(GL_VERTEX_ARRAY);
slouken@6188
   277
    data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
slouken@5355
   278
}
slouken@5355
   279
hfutrell@2739
   280
SDL_Renderer *
hfutrell@2739
   281
GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
hfutrell@2739
   282
{
slouken@2753
   283
hfutrell@2739
   284
    SDL_Renderer *renderer;
hfutrell@2739
   285
    GLES_RenderData *data;
hfutrell@2739
   286
    GLint value;
slouken@8906
   287
    Uint32 window_flags;
slime73@9958
   288
    int profile_mask = 0, major = 0, minor = 0;
slouken@8906
   289
    SDL_bool changed_window = SDL_FALSE;
CarniBlood@8256
   290
gabomdq@8257
   291
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
gabomdq@8257
   292
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
gabomdq@8257
   293
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
slouken@7191
   294
slouken@8906
   295
    window_flags = SDL_GetWindowFlags(window);
slouken@8906
   296
    if (!(window_flags & SDL_WINDOW_OPENGL) ||
gabomdq@8257
   297
        profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
gabomdq@8264
   298
slouken@8906
   299
        changed_window = SDL_TRUE;
gabomdq@8264
   300
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
gabomdq@8264
   301
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
gabomdq@8264
   302
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
gabomdq@8264
   303
slouken@8906
   304
        if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
slouken@8906
   305
            goto error;
slouken@6188
   306
        }
slouken@6188
   307
    }
hfutrell@2739
   308
hfutrell@2739
   309
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
hfutrell@2739
   310
    if (!renderer) {
hfutrell@2739
   311
        SDL_OutOfMemory();
slouken@8906
   312
        goto error;
hfutrell@2739
   313
    }
hfutrell@2739
   314
hfutrell@2739
   315
    data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
hfutrell@2739
   316
    if (!data) {
hfutrell@2739
   317
        GLES_DestroyRenderer(renderer);
hfutrell@2739
   318
        SDL_OutOfMemory();
slouken@8906
   319
        goto error;
hfutrell@2739
   320
    }
hfutrell@2739
   321
slouken@5147
   322
    renderer->WindowEvent = GLES_WindowEvent;
slime73@9530
   323
    renderer->GetOutputSize = GLES_GetOutputSize;
hfutrell@2739
   324
    renderer->CreateTexture = GLES_CreateTexture;
hfutrell@2739
   325
    renderer->UpdateTexture = GLES_UpdateTexture;
hfutrell@2739
   326
    renderer->LockTexture = GLES_LockTexture;
hfutrell@2739
   327
    renderer->UnlockTexture = GLES_UnlockTexture;
slouken@6247
   328
    renderer->SetRenderTarget = GLES_SetRenderTarget;
slouken@5297
   329
    renderer->UpdateViewport = GLES_UpdateViewport;
slouken@7141
   330
    renderer->UpdateClipRect = GLES_UpdateClipRect;
slouken@5333
   331
    renderer->RenderClear = GLES_RenderClear;
slouken@3641
   332
    renderer->RenderDrawPoints = GLES_RenderDrawPoints;
slouken@3641
   333
    renderer->RenderDrawLines = GLES_RenderDrawLines;
slouken@3641
   334
    renderer->RenderFillRects = GLES_RenderFillRects;
hfutrell@2739
   335
    renderer->RenderCopy = GLES_RenderCopy;
slouken@6528
   336
    renderer->RenderCopyEx = GLES_RenderCopyEx;
slouken@6043
   337
    renderer->RenderReadPixels = GLES_RenderReadPixels;
hfutrell@2739
   338
    renderer->RenderPresent = GLES_RenderPresent;
hfutrell@2739
   339
    renderer->DestroyTexture = GLES_DestroyTexture;
hfutrell@2739
   340
    renderer->DestroyRenderer = GLES_DestroyRenderer;
gabomdq@6414
   341
    renderer->GL_BindTexture = GLES_BindTexture;
gabomdq@6414
   342
    renderer->GL_UnbindTexture = GLES_UnbindTexture;
slouken@5201
   343
    renderer->info = GLES_RenderDriver.info;
slouken@6246
   344
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
hfutrell@2739
   345
    renderer->driverdata = data;
slouken@6171
   346
    renderer->window = window;
slouken@2753
   347
slouken@3688
   348
    data->context = SDL_GL_CreateContext(window);
hfutrell@2739
   349
    if (!data->context) {
hfutrell@2739
   350
        GLES_DestroyRenderer(renderer);
slouken@8906
   351
        goto error;
hfutrell@2739
   352
    }
slouken@3688
   353
    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
hfutrell@2739
   354
        GLES_DestroyRenderer(renderer);
slouken@8906
   355
        goto error;
hfutrell@2739
   356
    }
hfutrell@2739
   357
slouken@6188
   358
    if (GLES_LoadFunctions(data) < 0) {
slouken@6188
   359
        GLES_DestroyRenderer(renderer);
slouken@8906
   360
        goto error;
slouken@6188
   361
    }
slouken@6188
   362
hfutrell@2739
   363
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
hfutrell@2739
   364
        SDL_GL_SetSwapInterval(1);
hfutrell@2739
   365
    } else {
hfutrell@2739
   366
        SDL_GL_SetSwapInterval(0);
hfutrell@2739
   367
    }
hfutrell@2739
   368
    if (SDL_GL_GetSwapInterval() > 0) {
hfutrell@2739
   369
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
hfutrell@2739
   370
    }
hfutrell@2739
   371
slouken@3161
   372
#if SDL_VIDEO_DRIVER_PANDORA
slouken@3161
   373
    data->GL_OES_draw_texture_supported = SDL_FALSE;
slouken@3161
   374
    data->useDrawTexture = SDL_FALSE;
slouken@3161
   375
#else
slouken@2753
   376
    if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) {
slouken@2753
   377
        data->GL_OES_draw_texture_supported = SDL_TRUE;
slouken@2753
   378
        data->useDrawTexture = SDL_TRUE;
slouken@2753
   379
    } else {
slouken@2753
   380
        data->GL_OES_draw_texture_supported = SDL_FALSE;
slouken@2753
   381
        data->useDrawTexture = SDL_FALSE;
slouken@2753
   382
    }
slouken@3161
   383
#endif
hfutrell@2739
   384
slouken@6274
   385
    value = 0;
slouken@6188
   386
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
hfutrell@2739
   387
    renderer->info.max_texture_width = value;
slouken@6274
   388
    value = 0;
slouken@6188
   389
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
hfutrell@2739
   390
    renderer->info.max_texture_height = value;
hfutrell@2739
   391
gabomdq@7644
   392
    /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
gabomdq@7644
   393
    if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
slouken@6232
   394
        data->GL_OES_framebuffer_object_supported = SDL_TRUE;
slouken@6246
   395
        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
slouken@6271
   396
slouken@6274
   397
        value = 0;
slouken@6271
   398
        data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
slouken@6271
   399
        data->window_framebuffer = (GLuint)value;
slouken@6232
   400
    }
slouken@6232
   401
    data->framebuffers = NULL;
slouken@6232
   402
slouken@7502
   403
    if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
slouken@7502
   404
        data->GL_OES_blend_func_separate_supported = SDL_TRUE;
slouken@7502
   405
    }
slouken@7502
   406
hfutrell@2739
   407
    /* Set up parameters for rendering */
slouken@5355
   408
    GLES_ResetState(renderer);
hfutrell@2739
   409
hfutrell@2739
   410
    return renderer;
slouken@8906
   411
slouken@8906
   412
error:
slouken@8906
   413
    if (changed_window) {
slouken@8906
   414
        /* Uh oh, better try to put it back... */
slouken@8906
   415
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
slouken@8906
   416
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
slouken@8906
   417
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
slouken@8906
   418
        SDL_RecreateWindow(window, window_flags);
slouken@8906
   419
    }
slouken@8906
   420
    return NULL;
hfutrell@2739
   421
}
hfutrell@2739
   422
slouken@5147
   423
static void
slouken@5147
   424
GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
hfutrell@2739
   425
{
slouken@6190
   426
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@7191
   427
slouken@6260
   428
    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
slouken@6260
   429
        event->event == SDL_WINDOWEVENT_SHOWN ||
slouken@6260
   430
        event->event == SDL_WINDOWEVENT_HIDDEN) {
slouken@5147
   431
        /* Rebind the context to the window area and update matrices */
slouken@5147
   432
        SDL_CurrentContext = NULL;
slouken@5147
   433
    }
slouken@6060
   434
slouken@6060
   435
    if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
slouken@6060
   436
        /* According to Apple documentation, we need to finish drawing NOW! */
slouken@6232
   437
        data->glFinish();
slouken@6060
   438
    }
hfutrell@2739
   439
}
hfutrell@2739
   440
slime73@9530
   441
static int
slime73@9530
   442
GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
slime73@9530
   443
{
slime73@9530
   444
    SDL_GL_GetDrawableSize(renderer->window, w, h);
slime73@9530
   445
    return 0;
slime73@9530
   446
}
slime73@9530
   447
slouken@7860
   448
static SDL_INLINE int
hfutrell@2739
   449
power_of_2(int input)
hfutrell@2739
   450
{
hfutrell@2739
   451
    int value = 1;
hfutrell@2739
   452
hfutrell@2739
   453
    while (value < input) {
hfutrell@2739
   454
        value <<= 1;
hfutrell@2739
   455
    }
hfutrell@2739
   456
    return value;
hfutrell@2739
   457
}
hfutrell@2739
   458
slouken@5484
   459
static GLenum
slouken@5484
   460
GetScaleQuality(void)
slouken@5484
   461
{
slouken@5484
   462
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
slouken@5484
   463
slouken@5484
   464
    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
slouken@5484
   465
        return GL_NEAREST;
slouken@5484
   466
    } else {
slouken@5484
   467
        return GL_LINEAR;
slouken@5484
   468
    }
slouken@5484
   469
}
slouken@5484
   470
hfutrell@2739
   471
static int
slouken@3139
   472
GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   473
{
slouken@6188
   474
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   475
    GLES_TextureData *data;
hfutrell@2739
   476
    GLint internalFormat;
hfutrell@2739
   477
    GLenum format, type;
hfutrell@2739
   478
    int texture_w, texture_h;
slouken@5503
   479
    GLenum scaleMode;
hfutrell@2739
   480
    GLenum result;
slouken@3099
   481
slouken@5147
   482
    GLES_ActivateRenderer(renderer);
slouken@5147
   483
slouken@2753
   484
    switch (texture->format) {
slouken@2753
   485
    case SDL_PIXELFORMAT_ABGR8888:
slouken@3139
   486
        internalFormat = GL_RGBA;
slouken@3139
   487
        format = GL_RGBA;
slouken@3139
   488
        type = GL_UNSIGNED_BYTE;
slouken@3139
   489
        break;
slouken@2753
   490
    default:
icculus@7037
   491
        return SDL_SetError("Texture format not supported");
hfutrell@2739
   492
    }
slouken@2753
   493
slouken@2753
   494
    data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
hfutrell@2739
   495
    if (!data) {
icculus@7037
   496
        return SDL_OutOfMemory();
hfutrell@2739
   497
    }
hfutrell@2739
   498
hfutrell@2739
   499
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
hfutrell@2739
   500
        data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
slouken@5402
   501
        data->pixels = SDL_calloc(1, texture->h * data->pitch);
hfutrell@2739
   502
        if (!data->pixels) {
hfutrell@2739
   503
            SDL_free(data);
icculus@7037
   504
            return SDL_OutOfMemory();
hfutrell@2739
   505
        }
hfutrell@2739
   506
    }
hfutrell@2739
   507
gabomdq@7642
   508
    
slouken@6232
   509
    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
gabomdq@7642
   510
        if (!renderdata->GL_OES_framebuffer_object_supported) {
gabomdq@7642
   511
            SDL_free(data);
gabomdq@7642
   512
            return SDL_SetError("GL_OES_framebuffer_object not supported");
gabomdq@7642
   513
        }
gabomdq@7642
   514
        data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h);
slouken@6232
   515
    } else {
gabomdq@7642
   516
        data->fbo = NULL;
slouken@6232
   517
    }
gabomdq@7642
   518
    
hfutrell@2739
   519
slouken@6188
   520
    renderdata->glGetError();
slouken@6188
   521
    renderdata->glEnable(GL_TEXTURE_2D);
slouken@6188
   522
    renderdata->glGenTextures(1, &data->texture);
slouken@7624
   523
    result = renderdata->glGetError();
slouken@7624
   524
    if (result != GL_NO_ERROR) {
slouken@7624
   525
        SDL_free(data);
slouken@7624
   526
        return GLES_SetError("glGenTextures()", result);
slouken@7624
   527
    }
slouken@2753
   528
slouken@2753
   529
    data->type = GL_TEXTURE_2D;
slouken@2753
   530
    /* no NPOV textures allowed in OpenGL ES (yet) */
slouken@2753
   531
    texture_w = power_of_2(texture->w);
slouken@2753
   532
    texture_h = power_of_2(texture->h);
slouken@2753
   533
    data->texw = (GLfloat) texture->w / texture_w;
slouken@2753
   534
    data->texh = (GLfloat) texture->h / texture_h;
slouken@2753
   535
hfutrell@2739
   536
    data->format = format;
hfutrell@2739
   537
    data->formattype = type;
slouken@5503
   538
    scaleMode = GetScaleQuality();
slouken@6188
   539
    renderdata->glBindTexture(data->type, data->texture);
slouken@6188
   540
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
slouken@6188
   541
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
slouken@6188
   542
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
slouken@6188
   543
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
slouken@2753
   544
slouken@6188
   545
    renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
slouken@2753
   546
                             texture_h, 0, format, type, NULL);
slouken@6188
   547
    renderdata->glDisable(GL_TEXTURE_2D);
hfutrell@2739
   548
slouken@6188
   549
    result = renderdata->glGetError();
hfutrell@2739
   550
    if (result != GL_NO_ERROR) {
gabomdq@7642
   551
        SDL_free(data);
icculus@7037
   552
        return GLES_SetError("glTexImage2D()", result);
hfutrell@2739
   553
    }
gabomdq@7642
   554
    
gabomdq@7642
   555
    texture->driverdata = data;
hfutrell@2739
   556
    return 0;
hfutrell@2739
   557
}
hfutrell@2739
   558
hfutrell@2739
   559
static int
slouken@3139
   560
GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@3139
   561
                   const SDL_Rect * rect, const void *pixels, int pitch)
hfutrell@2739
   562
{
slouken@6188
   563
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   564
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
slouken@5227
   565
    Uint8 *blob = NULL;
slouken@5227
   566
    Uint8 *src;
slouken@5227
   567
    int srcPitch;
slouken@5227
   568
    int y;
hfutrell@2739
   569
slouken@5147
   570
    GLES_ActivateRenderer(renderer);
slouken@5147
   571
slouken@5227
   572
    /* Bail out if we're supposed to update an empty rectangle */
slime73@9604
   573
    if (rect->w <= 0 || rect->h <= 0) {
slouken@5227
   574
        return 0;
slime73@9604
   575
    }
slouken@5227
   576
slouken@5227
   577
    /* Reformat the texture data into a tightly packed array */
slouken@5227
   578
    srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@5227
   579
    src = (Uint8 *)pixels;
icculus@7037
   580
    if (pitch != srcPitch) {
slouken@5227
   581
        blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
icculus@7037
   582
        if (!blob) {
icculus@7037
   583
            return SDL_OutOfMemory();
slouken@5227
   584
        }
slouken@5227
   585
        src = blob;
icculus@7037
   586
        for (y = 0; y < rect->h; ++y) {
slouken@5227
   587
            SDL_memcpy(src, pixels, srcPitch);
slouken@5227
   588
            src += srcPitch;
slouken@5227
   589
            pixels = (Uint8 *)pixels + pitch;
slouken@5227
   590
        }
slouken@5227
   591
        src = blob;
slouken@5227
   592
    }
slouken@5227
   593
slouken@5227
   594
    /* Create a texture subimage with the supplied data */
slouken@6188
   595
    renderdata->glGetError();
slouken@6188
   596
    renderdata->glEnable(data->type);
slouken@6188
   597
    renderdata->glBindTexture(data->type, data->texture);
slouken@6188
   598
    renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
slouken@6188
   599
    renderdata->glTexSubImage2D(data->type,
slouken@5227
   600
                    0,
slouken@5227
   601
                    rect->x,
slouken@5227
   602
                    rect->y,
slouken@5227
   603
                    rect->w,
slouken@5227
   604
                    rect->h,
slouken@5227
   605
                    data->format,
slouken@5227
   606
                    data->formattype,
slouken@5227
   607
                    src);
slouken@7719
   608
    SDL_free(blob);
slouken@5052
   609
slime73@9604
   610
    if (renderdata->glGetError() != GL_NO_ERROR) {
icculus@7037
   611
        return SDL_SetError("Failed to update texture");
hfutrell@2739
   612
    }
hfutrell@2739
   613
    return 0;
hfutrell@2739
   614
}
hfutrell@2739
   615
hfutrell@2739
   616
static int
hfutrell@2739
   617
GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   618
                 const SDL_Rect * rect, void **pixels, int *pitch)
hfutrell@2739
   619
{
hfutrell@2739
   620
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   621
hfutrell@2739
   622
    *pixels =
hfutrell@2739
   623
        (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
hfutrell@2739
   624
                  rect->x * SDL_BYTESPERPIXEL(texture->format));
hfutrell@2739
   625
    *pitch = data->pitch;
hfutrell@2739
   626
    return 0;
hfutrell@2739
   627
}
hfutrell@2739
   628
hfutrell@2739
   629
static void
hfutrell@2739
   630
GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   631
{
slouken@5156
   632
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
slouken@5227
   633
    SDL_Rect rect;
hfutrell@2739
   634
slouken@5227
   635
    /* We do whole texture updates, at least for now */
slouken@5227
   636
    rect.x = 0;
slouken@5227
   637
    rect.y = 0;
slouken@5227
   638
    rect.w = texture->w;
slouken@5227
   639
    rect.h = texture->h;
slouken@5227
   640
    GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
hfutrell@2739
   641
}
hfutrell@2739
   642
slouken@5297
   643
static int
slouken@6247
   644
GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@6246
   645
{
slouken@6246
   646
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@6246
   647
    GLES_TextureData *texturedata = NULL;
slouken@6246
   648
    GLenum status;
slouken@6246
   649
slouken@6246
   650
    GLES_ActivateRenderer(renderer);
slime73@9604
   651
gabomdq@7642
   652
    if (!data->GL_OES_framebuffer_object_supported) {
gabomdq@7642
   653
        return SDL_SetError("Can't enable render target support in this renderer");
gabomdq@7642
   654
    }
slouken@6246
   655
slouken@6246
   656
    if (texture == NULL) {
slouken@6271
   657
        data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
slouken@6246
   658
        return 0;
slouken@6246
   659
    }
slouken@6246
   660
slouken@6246
   661
    texturedata = (GLES_TextureData *) texture->driverdata;
slouken@6246
   662
    data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
slouken@6246
   663
    /* TODO: check if texture pixel format allows this operation */
slouken@6246
   664
    data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
slouken@6246
   665
    /* Check FBO status */
slouken@6246
   666
    status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
slouken@6246
   667
    if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
icculus@7037
   668
        return SDL_SetError("glFramebufferTexture2DOES() failed");
slouken@6246
   669
    }
slouken@6246
   670
    return 0;
slouken@6246
   671
}
slouken@6246
   672
slouken@6246
   673
static int
slouken@5297
   674
GLES_UpdateViewport(SDL_Renderer * renderer)
slouken@5224
   675
{
slouken@5297
   676
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@5297
   677
slouken@5297
   678
    if (SDL_CurrentContext != data->context) {
slouken@5297
   679
        /* We'll update the viewport after we rebind the context */
slouken@5297
   680
        return 0;
slouken@5297
   681
    }
slouken@5224
   682
slouken@9680
   683
    if (renderer->target) {
slouken@9680
   684
        data->glViewport(renderer->viewport.x, renderer->viewport.y,
slouken@9680
   685
                         renderer->viewport.w, renderer->viewport.h);
slouken@9680
   686
    } else {
slouken@9680
   687
        int w, h;
slouken@9680
   688
slouken@9680
   689
        SDL_GetRendererOutputSize(renderer, &w, &h);
slouken@9680
   690
        data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
slouken@9680
   691
                         renderer->viewport.w, renderer->viewport.h);
slouken@9680
   692
    }
slouken@5224
   693
slouken@7239
   694
    if (renderer->viewport.w && renderer->viewport.h) {
slouken@7239
   695
        data->glMatrixMode(GL_PROJECTION);
slouken@7239
   696
        data->glLoadIdentity();
slouken@7239
   697
        data->glOrthof((GLfloat) 0,
slouken@7239
   698
                 (GLfloat) renderer->viewport.w,
slouken@7239
   699
                 (GLfloat) renderer->viewport.h,
slouken@7239
   700
                 (GLfloat) 0, 0.0, 1.0);
slouken@7239
   701
    }
slouken@5297
   702
    return 0;
slouken@5224
   703
}
slouken@5224
   704
slouken@7141
   705
static int
slouken@7141
   706
GLES_UpdateClipRect(SDL_Renderer * renderer)
slouken@7141
   707
{
gabomdq@7160
   708
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@7141
   709
gabomdq@7160
   710
    if (SDL_CurrentContext != data->context) {
gabomdq@7160
   711
        /* We'll update the clip rect after we rebind the context */
gabomdq@7160
   712
        return 0;
gabomdq@7160
   713
    }
gabomdq@7160
   714
jorgenpt@8728
   715
    if (renderer->clipping_enabled) {
jorgenpt@8728
   716
        const SDL_Rect *rect = &renderer->clip_rect;
gabomdq@7160
   717
        data->glEnable(GL_SCISSOR_TEST);
slouken@9680
   718
        if (renderer->target) {
slouken@9680
   719
            data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h);
slouken@9680
   720
        } else {
slouken@9680
   721
            int w, h;
slouken@9680
   722
slouken@9680
   723
            SDL_GetRendererOutputSize(renderer, &w, &h);
icculus@9977
   724
            data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
slouken@9680
   725
        }
slouken@7141
   726
    } else {
gabomdq@7160
   727
        data->glDisable(GL_SCISSOR_TEST);
slouken@7141
   728
    }
slouken@7141
   729
    return 0;
slouken@7141
   730
}
slouken@7141
   731
slouken@5355
   732
static void
slouken@5355
   733
GLES_SetColor(GLES_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5333
   734
{
slouken@5355
   735
    Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
slouken@5333
   736
slouken@5355
   737
    if (color != data->current.color) {
slouken@6188
   738
        data->glColor4f((GLfloat) r * inv255f,
slouken@5355
   739
                        (GLfloat) g * inv255f,
slouken@5355
   740
                        (GLfloat) b * inv255f,
slouken@5355
   741
                        (GLfloat) a * inv255f);
slouken@5355
   742
        data->current.color = color;
slouken@5355
   743
    }
slouken@5333
   744
}
slouken@5333
   745
slouken@5224
   746
static void
slouken@5140
   747
GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
slouken@2936
   748
{
slouken@5355
   749
    if (blendMode != data->current.blendMode) {
slouken@2936
   750
        switch (blendMode) {
slouken@2936
   751
        case SDL_BLENDMODE_NONE:
slouken@6188
   752
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
slouken@6188
   753
            data->glDisable(GL_BLEND);
slouken@2936
   754
            break;
slouken@2936
   755
        case SDL_BLENDMODE_BLEND:
slouken@6188
   756
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@6188
   757
            data->glEnable(GL_BLEND);
slouken@7502
   758
            if (data->GL_OES_blend_func_separate_supported) {
slouken@7502
   759
                data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
slouken@7502
   760
            } else {
slouken@7502
   761
                data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
slouken@7502
   762
            }
slouken@2936
   763
            break;
slouken@2936
   764
        case SDL_BLENDMODE_ADD:
slouken@6188
   765
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@6188
   766
            data->glEnable(GL_BLEND);
slouken@7502
   767
            if (data->GL_OES_blend_func_separate_supported) {
slouken@7502
   768
                data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
slouken@7502
   769
            } else {
slouken@7502
   770
                data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
slouken@7502
   771
            }
slouken@2936
   772
            break;
slouken@5184
   773
        case SDL_BLENDMODE_MOD:
slouken@6188
   774
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@6188
   775
            data->glEnable(GL_BLEND);
slouken@7502
   776
            if (data->GL_OES_blend_func_separate_supported) {
slouken@7502
   777
                data->glBlendFuncSeparateOES(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
slouken@7502
   778
            } else {
slouken@7502
   779
                data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
slouken@7502
   780
            }
slouken@5184
   781
            break;
slouken@2936
   782
        }
slouken@5355
   783
        data->current.blendMode = blendMode;
slouken@5355
   784
    }
slouken@5355
   785
}
slouken@5355
   786
slouken@5355
   787
static void
slouken@5355
   788
GLES_SetTexCoords(GLES_RenderData * data, SDL_bool enabled)
slouken@5355
   789
{
slouken@5355
   790
    if (enabled != data->current.tex_coords) {
slouken@5355
   791
        if (enabled) {
slouken@6188
   792
            data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
slouken@5355
   793
        } else {
slouken@6188
   794
            data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
slouken@5355
   795
        }
slouken@5355
   796
        data->current.tex_coords = enabled;
slouken@2936
   797
    }
slouken@2936
   798
}
slouken@2936
   799
slouken@5355
   800
static void
slouken@5355
   801
GLES_SetDrawingState(SDL_Renderer * renderer)
slouken@5355
   802
{
slouken@5355
   803
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@5355
   804
slouken@5355
   805
    GLES_ActivateRenderer(renderer);
slouken@5355
   806
slouken@5355
   807
    GLES_SetColor(data, (GLfloat) renderer->r,
slouken@5355
   808
                        (GLfloat) renderer->g,
slouken@5355
   809
                        (GLfloat) renderer->b,
slouken@5355
   810
                        (GLfloat) renderer->a);
slouken@5355
   811
slouken@5355
   812
    GLES_SetBlendMode(data, renderer->blendMode);
slouken@5355
   813
slouken@5355
   814
    GLES_SetTexCoords(data, SDL_FALSE);
slouken@5355
   815
}
slouken@5355
   816
slouken@5355
   817
static int
slouken@5355
   818
GLES_RenderClear(SDL_Renderer * renderer)
slouken@5355
   819
{
slouken@6188
   820
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@6188
   821
slouken@5355
   822
    GLES_ActivateRenderer(renderer);
slouken@5355
   823
slouken@6188
   824
    data->glClearColor((GLfloat) renderer->r * inv255f,
slouken@5355
   825
                 (GLfloat) renderer->g * inv255f,
slouken@5355
   826
                 (GLfloat) renderer->b * inv255f,
slouken@5355
   827
                 (GLfloat) renderer->a * inv255f);
slouken@5355
   828
slouken@6188
   829
    data->glClear(GL_COLOR_BUFFER_BIT);
slouken@5355
   830
slouken@5355
   831
    return 0;
slouken@5355
   832
}
slouken@5355
   833
hfutrell@2739
   834
static int
slouken@6528
   835
GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points,
slouken@3641
   836
                      int count)
slouken@2936
   837
{
slouken@6188
   838
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@8993
   839
    GLfloat *vertices;
slouken@8993
   840
    int idx;
slouken@2936
   841
slouken@5355
   842
    GLES_SetDrawingState(renderer);
slouken@2936
   843
slouken@8993
   844
    /* Emit the specified vertices as points */
slouken@8993
   845
    vertices = SDL_stack_alloc(GLfloat, count * 2);
slouken@8993
   846
    for (idx = 0; idx < count; ++idx) {
slouken@8993
   847
        GLfloat x = points[idx].x + 0.5f;
slouken@8993
   848
        GLfloat y = points[idx].y + 0.5f;
slouken@8993
   849
slouken@8993
   850
        vertices[idx * 2] = x;
slouken@8993
   851
        vertices[(idx * 2) + 1] = y;
slouken@8993
   852
    }
slouken@8993
   853
slouken@8993
   854
    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
slouken@6188
   855
    data->glDrawArrays(GL_POINTS, 0, count);
slouken@8993
   856
    SDL_stack_free(vertices);
slouken@2936
   857
    return 0;
slouken@2936
   858
}
slouken@2936
   859
slouken@2936
   860
static int
slouken@6528
   861
GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points,
slouken@3641
   862
                     int count)
hfutrell@2739
   863
{
slouken@6188
   864
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@8993
   865
    GLfloat *vertices;
slouken@8993
   866
    int idx;
slouken@2753
   867
slouken@5355
   868
    GLES_SetDrawingState(renderer);
slouken@2936
   869
slouken@8993
   870
    /* Emit a line strip including the specified vertices */
slouken@8993
   871
    vertices = SDL_stack_alloc(GLfloat, count * 2);
slouken@8993
   872
    for (idx = 0; idx < count; ++idx) {
slouken@8993
   873
        GLfloat x = points[idx].x + 0.5f;
slouken@8993
   874
        GLfloat y = points[idx].y + 0.5f;
slouken@8993
   875
slouken@8993
   876
        vertices[idx * 2] = x;
slouken@8993
   877
        vertices[(idx * 2) + 1] = y;
slouken@8993
   878
    }
slouken@8993
   879
slouken@8993
   880
    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
slouken@7191
   881
    if (count > 2 &&
slouken@3536
   882
        points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
slouken@3536
   883
        /* GL_LINE_LOOP takes care of the final segment */
slouken@3536
   884
        --count;
slouken@6188
   885
        data->glDrawArrays(GL_LINE_LOOP, 0, count);
slouken@3536
   886
    } else {
slouken@6188
   887
        data->glDrawArrays(GL_LINE_STRIP, 0, count);
slouken@6076
   888
        /* We need to close the endpoint of the line */
slouken@6188
   889
        data->glDrawArrays(GL_POINTS, count-1, 1);
slouken@3536
   890
    }
slouken@8993
   891
    SDL_stack_free(vertices);
hfutrell@2949
   892
slouken@2936
   893
    return 0;
slouken@2936
   894
}
slouken@2936
   895
slouken@2936
   896
static int
slouken@6528
   897
GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects,
slouken@3641
   898
                     int count)
slouken@2936
   899
{
slouken@6188
   900
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@3536
   901
    int i;
slouken@2753
   902
slouken@5355
   903
    GLES_SetDrawingState(renderer);
slouken@2753
   904
slouken@3536
   905
    for (i = 0; i < count; ++i) {
slouken@6528
   906
        const SDL_FRect *rect = &rects[i];
slouken@6528
   907
        GLfloat minx = rect->x;
slouken@6528
   908
        GLfloat maxx = rect->x + rect->w;
slouken@6528
   909
        GLfloat miny = rect->y;
slouken@6528
   910
        GLfloat maxy = rect->y + rect->h;
slouken@6528
   911
        GLfloat vertices[8];
slouken@3536
   912
        vertices[0] = minx;
slouken@3536
   913
        vertices[1] = miny;
slouken@3536
   914
        vertices[2] = maxx;
slouken@3536
   915
        vertices[3] = miny;
slouken@3536
   916
        vertices[4] = minx;
slouken@3536
   917
        vertices[5] = maxy;
slouken@3536
   918
        vertices[6] = maxx;
slouken@3536
   919
        vertices[7] = maxy;
slouken@2964
   920
slouken@6528
   921
        data->glVertexPointer(2, GL_FLOAT, 0, vertices);
slouken@6188
   922
        data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
slouken@3536
   923
    }
hfutrell@2949
   924
slouken@2753
   925
    return 0;
hfutrell@2739
   926
}
hfutrell@2739
   927
hfutrell@2739
   928
static int
hfutrell@2739
   929
GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
   930
                const SDL_Rect * srcrect, const SDL_FRect * dstrect)
hfutrell@2739
   931
{
hfutrell@2739
   932
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   933
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
slouken@6528
   934
    GLfloat minx, miny, maxx, maxy;
hfutrell@2739
   935
    GLfloat minu, maxu, minv, maxv;
gabomdq@7679
   936
    GLfloat vertices[8];
gabomdq@7679
   937
    GLfloat texCoords[8];
slouken@2753
   938
slouken@5147
   939
    GLES_ActivateRenderer(renderer);
slouken@5147
   940
slouken@6188
   941
    data->glEnable(GL_TEXTURE_2D);
lestat@3122
   942
slouken@6188
   943
    data->glBindTexture(texturedata->type, texturedata->texture);
slouken@2753
   944
hfutrell@2739
   945
    if (texture->modMode) {
slouken@5355
   946
        GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
hfutrell@2739
   947
    } else {
slouken@5355
   948
        GLES_SetColor(data, 255, 255, 255, 255);
hfutrell@2739
   949
    }
hfutrell@2739
   950
slouken@5140
   951
    GLES_SetBlendMode(data, texture->blendMode);
hfutrell@2739
   952
slouken@5355
   953
    GLES_SetTexCoords(data, SDL_TRUE);
slouken@5355
   954
slouken@2753
   955
    if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
slouken@2753
   956
        /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
slouken@5154
   957
        GLint cropRect[4];
slouken@5154
   958
        int w, h;
slouken@3685
   959
        SDL_Window *window = renderer->window;
slouken@5154
   960
slouken@5154
   961
        SDL_GetWindowSize(window, &w, &h);
slouken@6246
   962
        if (renderer->target) {
slouken@6232
   963
            cropRect[0] = srcrect->x;
slouken@6232
   964
            cropRect[1] = srcrect->y;
slouken@6232
   965
            cropRect[2] = srcrect->w;
slouken@6232
   966
            cropRect[3] = srcrect->h;
slouken@6232
   967
            data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
slouken@6232
   968
                                   cropRect);
slouken@6528
   969
            data->glDrawTexfOES(renderer->viewport.x + dstrect->x, renderer->viewport.y + dstrect->y, 0,
slouken@6232
   970
                                dstrect->w, dstrect->h);
slouken@6232
   971
        } else {
slouken@6232
   972
            cropRect[0] = srcrect->x;
slouken@6232
   973
            cropRect[1] = srcrect->y + srcrect->h;
slouken@6232
   974
            cropRect[2] = srcrect->w;
slouken@6232
   975
            cropRect[3] = -srcrect->h;
slouken@6232
   976
            data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
slouken@6232
   977
                                   cropRect);
slouken@6528
   978
            data->glDrawTexfOES(renderer->viewport.x + dstrect->x,
slouken@6232
   979
                        h - (renderer->viewport.y + dstrect->y) - dstrect->h, 0,
slouken@6232
   980
                        dstrect->w, dstrect->h);
slouken@6232
   981
        }
slouken@2753
   982
    } else {
slouken@2753
   983
slouken@2753
   984
        minx = dstrect->x;
slouken@2753
   985
        miny = dstrect->y;
slouken@2753
   986
        maxx = dstrect->x + dstrect->w;
slouken@2753
   987
        maxy = dstrect->y + dstrect->h;
hfutrell@2739
   988
slouken@2753
   989
        minu = (GLfloat) srcrect->x / texture->w;
slouken@2753
   990
        minu *= texturedata->texw;
slouken@2753
   991
        maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
slouken@2753
   992
        maxu *= texturedata->texw;
slouken@2753
   993
        minv = (GLfloat) srcrect->y / texture->h;
slouken@2753
   994
        minv *= texturedata->texh;
slouken@2753
   995
        maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
slouken@2753
   996
        maxv *= texturedata->texh;
slouken@2753
   997
slouken@2753
   998
        vertices[0] = minx;
slouken@2753
   999
        vertices[1] = miny;
slouken@2753
  1000
        vertices[2] = maxx;
slouken@2753
  1001
        vertices[3] = miny;
slouken@2753
  1002
        vertices[4] = minx;
slouken@2753
  1003
        vertices[5] = maxy;
slouken@2753
  1004
        vertices[6] = maxx;
slouken@2753
  1005
        vertices[7] = maxy;
slouken@2753
  1006
slouken@2753
  1007
        texCoords[0] = minu;
slouken@2753
  1008
        texCoords[1] = minv;
slouken@2753
  1009
        texCoords[2] = maxu;
slouken@2753
  1010
        texCoords[3] = minv;
slouken@2753
  1011
        texCoords[4] = minu;
slouken@2753
  1012
        texCoords[5] = maxv;
slouken@2753
  1013
        texCoords[6] = maxu;
slouken@2753
  1014
        texCoords[7] = maxv;
slouken@2753
  1015
slouken@6528
  1016
        data->glVertexPointer(2, GL_FLOAT, 0, vertices);
slouken@6188
  1017
        data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
slouken@6188
  1018
        data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
lestat@3122
  1019
    }
slouken@6188
  1020
    data->glDisable(GL_TEXTURE_2D);
slouken@2753
  1021
hfutrell@2739
  1022
    return 0;
hfutrell@2739
  1023
}
hfutrell@2739
  1024
slouken@6043
  1025
static int
slouken@6528
  1026
GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@6528
  1027
                const SDL_Rect * srcrect, const SDL_FRect * dstrect,
slouken@6528
  1028
                const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
slouken@6528
  1029
{
slouken@6528
  1030
slouken@6528
  1031
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@6528
  1032
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
slouken@6528
  1033
    GLfloat minx, miny, maxx, maxy;
slouken@6528
  1034
    GLfloat minu, maxu, minv, maxv;
slouken@6528
  1035
    GLfloat centerx, centery;
gabomdq@7679
  1036
    GLfloat vertices[8];
gabomdq@7679
  1037
    GLfloat texCoords[8];
gabomdq@7679
  1038
slouken@7191
  1039
slouken@6528
  1040
    GLES_ActivateRenderer(renderer);
slouken@6528
  1041
slouken@6528
  1042
    data->glEnable(GL_TEXTURE_2D);
slouken@6528
  1043
slouken@6528
  1044
    data->glBindTexture(texturedata->type, texturedata->texture);
slouken@6528
  1045
slouken@6528
  1046
    if (texture->modMode) {
slouken@6528
  1047
        GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
slouken@6528
  1048
    } else {
slouken@6528
  1049
        GLES_SetColor(data, 255, 255, 255, 255);
slouken@6528
  1050
    }
slouken@6528
  1051
slouken@6528
  1052
    GLES_SetBlendMode(data, texture->blendMode);
slouken@6528
  1053
slouken@6528
  1054
    GLES_SetTexCoords(data, SDL_TRUE);
slouken@6528
  1055
slouken@6528
  1056
    centerx = center->x;
slouken@6528
  1057
    centery = center->y;
slouken@6528
  1058
slouken@7191
  1059
    /* Rotate and translate */
slouken@6528
  1060
    data->glPushMatrix();
slouken@6528
  1061
    data->glTranslatef(dstrect->x + centerx, dstrect->y + centery, 0.0f);
slouken@6528
  1062
    data->glRotatef((GLfloat)angle, 0.0f, 0.0f, 1.0f);
slouken@6528
  1063
slouken@6528
  1064
    if (flip & SDL_FLIP_HORIZONTAL) {
slouken@6528
  1065
        minx =  dstrect->w - centerx;
slouken@6528
  1066
        maxx = -centerx;
slouken@6528
  1067
    } else {
slouken@6528
  1068
        minx = -centerx;
slouken@6528
  1069
        maxx = dstrect->w - centerx;
slouken@6528
  1070
    }
slouken@6528
  1071
slouken@6528
  1072
    if (flip & SDL_FLIP_VERTICAL) {
slouken@6528
  1073
        miny = dstrect->h - centery;
slouken@6528
  1074
        maxy = -centery;
slouken@6528
  1075
    } else {
slouken@6528
  1076
        miny = -centery;
slouken@6528
  1077
        maxy = dstrect->h - centery;
slouken@6528
  1078
    }
slouken@6528
  1079
slouken@6528
  1080
    minu = (GLfloat) srcrect->x / texture->w;
slouken@6528
  1081
    minu *= texturedata->texw;
slouken@6528
  1082
    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
slouken@6528
  1083
    maxu *= texturedata->texw;
slouken@6528
  1084
    minv = (GLfloat) srcrect->y / texture->h;
slouken@6528
  1085
    minv *= texturedata->texh;
slouken@6528
  1086
    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
slouken@6528
  1087
    maxv *= texturedata->texh;
slouken@6528
  1088
slouken@6528
  1089
    vertices[0] = minx;
slouken@6528
  1090
    vertices[1] = miny;
slouken@6528
  1091
    vertices[2] = maxx;
slouken@6528
  1092
    vertices[3] = miny;
slouken@6528
  1093
    vertices[4] = minx;
slouken@6528
  1094
    vertices[5] = maxy;
slouken@6528
  1095
    vertices[6] = maxx;
slouken@6528
  1096
    vertices[7] = maxy;
slouken@6528
  1097
slouken@6528
  1098
    texCoords[0] = minu;
slouken@6528
  1099
    texCoords[1] = minv;
slouken@6528
  1100
    texCoords[2] = maxu;
slouken@6528
  1101
    texCoords[3] = minv;
slouken@6528
  1102
    texCoords[4] = minu;
slouken@6528
  1103
    texCoords[5] = maxv;
slouken@6528
  1104
    texCoords[6] = maxu;
slouken@6528
  1105
    texCoords[7] = maxv;
slouken@6528
  1106
    data->glVertexPointer(2, GL_FLOAT, 0, vertices);
slouken@6528
  1107
    data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
slouken@6528
  1108
    data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
slouken@6528
  1109
    data->glPopMatrix();
slouken@6528
  1110
    data->glDisable(GL_TEXTURE_2D);
slouken@6528
  1111
slouken@6528
  1112
    return 0;
slouken@6528
  1113
}
slouken@6528
  1114
slouken@6528
  1115
static int
slouken@6043
  1116
GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@6043
  1117
                    Uint32 pixel_format, void * pixels, int pitch)
slouken@6043
  1118
{
slouken@6188
  1119
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@6043
  1120
    Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
slouken@6043
  1121
    void *temp_pixels;
slouken@6043
  1122
    int temp_pitch;
slouken@6043
  1123
    Uint8 *src, *dst, *tmp;
slouken@6043
  1124
    int w, h, length, rows;
slouken@6043
  1125
    int status;
slouken@6043
  1126
slouken@6043
  1127
    GLES_ActivateRenderer(renderer);
slouken@6043
  1128
slouken@6043
  1129
    temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@6043
  1130
    temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@6043
  1131
    if (!temp_pixels) {
icculus@7037
  1132
        return SDL_OutOfMemory();
slouken@6043
  1133
    }
slouken@6043
  1134
slouken@7420
  1135
    SDL_GetRendererOutputSize(renderer, &w, &h);
slouken@6043
  1136
slouken@6188
  1137
    data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
slouken@6043
  1138
slouken@6188
  1139
    data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
slouken@6043
  1140
                       GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
slouken@6043
  1141
slouken@6043
  1142
    /* Flip the rows to be top-down */
slouken@6043
  1143
    length = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@6043
  1144
    src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
slouken@6043
  1145
    dst = (Uint8*)temp_pixels;
slouken@6043
  1146
    tmp = SDL_stack_alloc(Uint8, length);
slouken@6043
  1147
    rows = rect->h / 2;
slouken@6043
  1148
    while (rows--) {
slouken@6043
  1149
        SDL_memcpy(tmp, dst, length);
slouken@6043
  1150
        SDL_memcpy(dst, src, length);
slouken@6043
  1151
        SDL_memcpy(src, tmp, length);
slouken@6043
  1152
        dst += temp_pitch;
slouken@6043
  1153
        src -= temp_pitch;
slouken@6043
  1154
    }
slouken@6043
  1155
    SDL_stack_free(tmp);
slouken@6043
  1156
slouken@6043
  1157
    status = SDL_ConvertPixels(rect->w, rect->h,
slouken@6043
  1158
                               temp_format, temp_pixels, temp_pitch,
slouken@6043
  1159
                               pixel_format, pixels, pitch);
slouken@6043
  1160
    SDL_free(temp_pixels);
slouken@6043
  1161
slouken@6043
  1162
    return status;
slouken@6043
  1163
}
slouken@6043
  1164
hfutrell@2739
  1165
static void
slouken@3139
  1166
GLES_RenderPresent(SDL_Renderer * renderer)
hfutrell@2739
  1167
{
slouken@5147
  1168
    GLES_ActivateRenderer(renderer);
slouken@5147
  1169
hfutrell@2739
  1170
    SDL_GL_SwapWindow(renderer->window);
hfutrell@2739
  1171
}
hfutrell@2739
  1172
hfutrell@2739
  1173
static void
hfutrell@2739
  1174
GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
  1175
{
slouken@6188
  1176
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
slouken@6188
  1177
hfutrell@2739
  1178
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
  1179
slouken@5147
  1180
    GLES_ActivateRenderer(renderer);
slouken@5147
  1181
hfutrell@2739
  1182
    if (!data) {
hfutrell@2739
  1183
        return;
hfutrell@2739
  1184
    }
hfutrell@2739
  1185
    if (data->texture) {
slouken@6188
  1186
        renderdata->glDeleteTextures(1, &data->texture);
hfutrell@2739
  1187
    }
slouken@7719
  1188
    SDL_free(data->pixels);
hfutrell@2739
  1189
    SDL_free(data);
hfutrell@2739
  1190
    texture->driverdata = NULL;
hfutrell@2739
  1191
}
hfutrell@2739
  1192
hfutrell@2739
  1193
static void
hfutrell@2739
  1194
GLES_DestroyRenderer(SDL_Renderer * renderer)
hfutrell@2739
  1195
{
hfutrell@2739
  1196
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
  1197
hfutrell@2739
  1198
    if (data) {
hfutrell@2739
  1199
        if (data->context) {
slouken@6232
  1200
            while (data->framebuffers) {
slouken@6232
  1201
               GLES_FBOList *nextnode = data->framebuffers->next;
slouken@6232
  1202
               data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
slouken@6232
  1203
               SDL_free(data->framebuffers);
slouken@6232
  1204
               data->framebuffers = nextnode;
slouken@6232
  1205
            }
hfutrell@2739
  1206
            SDL_GL_DeleteContext(data->context);
hfutrell@2739
  1207
        }
hfutrell@2739
  1208
        SDL_free(data);
hfutrell@2739
  1209
    }
hfutrell@2739
  1210
    SDL_free(renderer);
hfutrell@2739
  1211
}
hfutrell@2739
  1212
slouken@6954
  1213
static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
slouken@6954
  1214
{
gabomdq@6414
  1215
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
gabomdq@6414
  1216
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
gabomdq@6414
  1217
    GLES_ActivateRenderer(renderer);
gabomdq@6414
  1218
gabomdq@6414
  1219
    data->glEnable(GL_TEXTURE_2D);
gabomdq@6414
  1220
    data->glBindTexture(texturedata->type, texturedata->texture);
gabomdq@6414
  1221
slime73@9604
  1222
    if (texw) {
slime73@9604
  1223
        *texw = (float)texturedata->texw;
slime73@9604
  1224
    }
slime73@9604
  1225
    if (texh) {
slime73@9604
  1226
        *texh = (float)texturedata->texh;
slime73@9604
  1227
    }
gabomdq@6414
  1228
gabomdq@6414
  1229
    return 0;
gabomdq@6414
  1230
}
gabomdq@6414
  1231
slouken@6954
  1232
static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
slouken@6954
  1233
{
gabomdq@6414
  1234
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
gabomdq@6414
  1235
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
gabomdq@6414
  1236
    GLES_ActivateRenderer(renderer);
gabomdq@6414
  1237
    data->glDisable(texturedata->type);
gabomdq@6414
  1238
gabomdq@6414
  1239
    return 0;
gabomdq@6414
  1240
}
gabomdq@6414
  1241
slouken@5226
  1242
#endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
hfutrell@2739
  1243
hfutrell@2739
  1244
/* vi: set ts=4 sw=4 expandtab: */