src/render/opengles/SDL_render_gles.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sat, 06 Sep 2014 23:20:14 +0200
changeset 9125 e004bdb812ce
parent 8993 bc47cf4c679d
child 9530 ac0885050d79
permissions -rw-r--r--
Fixed example in header file.

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