src/render/opengles/SDL_render_gles.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 14 Jun 2019 13:56:42 -0700
changeset 12860 0f52dd40abe5
parent 12665 4743da9c3eea
child 13037 d465f3a64af6
permissions -rw-r--r--
Worked around "Undefined symbol: ___isPlatformVersionAtLeast()" link error on Xcode 11 beta
hfutrell@2739
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@12503
     3
  Copyright (C) 1997-2019 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
sylvain@12531
    29
/* To prevent unnecessary window recreation,
sylvain@12531
    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
slouken@6232
    55
typedef struct GLES_FBOList GLES_FBOList;
slouken@6232
    56
slouken@6232
    57
struct GLES_FBOList
slouken@6232
    58
{
slouken@6232
    59
   Uint32 w, h;
slouken@6232
    60
   GLuint FBO;
slouken@6232
    61
   GLES_FBOList *next;
slouken@6232
    62
};
hfutrell@2739
    63
hfutrell@2739
    64
typedef struct
hfutrell@2739
    65
{
icculus@12238
    66
    SDL_Rect viewport;
icculus@12282
    67
    SDL_bool viewport_dirty;
icculus@12238
    68
    SDL_Texture *texture;
icculus@12282
    69
    SDL_Texture *target;
icculus@12282
    70
    int drawablew;
icculus@12282
    71
    int drawableh;
icculus@12238
    72
    SDL_BlendMode blend;
icculus@12282
    73
    SDL_bool cliprect_enabled_dirty;
icculus@12238
    74
    SDL_bool cliprect_enabled;
icculus@12282
    75
    SDL_bool cliprect_dirty;
icculus@12238
    76
    SDL_Rect cliprect;
icculus@12238
    77
    SDL_bool texturing;
icculus@12238
    78
    Uint32 color;
icculus@12238
    79
    Uint32 clear_color;
icculus@12238
    80
} GLES_DrawStateCache;
icculus@12238
    81
icculus@12238
    82
typedef struct
icculus@12238
    83
{
hfutrell@2739
    84
    SDL_GLContext context;
slouken@2753
    85
slouken@6188
    86
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
gabomdq@7642
    87
#define SDL_PROC_OES SDL_PROC
slouken@6188
    88
#include "SDL_glesfuncs.h"
slouken@6188
    89
#undef SDL_PROC
gabomdq@7642
    90
#undef SDL_PROC_OES
slouken@6232
    91
    SDL_bool GL_OES_framebuffer_object_supported;
slouken@6232
    92
    GLES_FBOList *framebuffers;
slouken@6271
    93
    GLuint window_framebuffer;
slouken@6188
    94
slouken@7502
    95
    SDL_bool GL_OES_blend_func_separate_supported;
slouken@11282
    96
    SDL_bool GL_OES_blend_equation_separate_supported;
slouken@11282
    97
    SDL_bool GL_OES_blend_subtract_supported;
icculus@12238
    98
icculus@12238
    99
    GLES_DrawStateCache drawstate;
hfutrell@2739
   100
} GLES_RenderData;
hfutrell@2739
   101
hfutrell@2739
   102
typedef struct
hfutrell@2739
   103
{
hfutrell@2739
   104
    GLuint texture;
hfutrell@2739
   105
    GLenum type;
hfutrell@2739
   106
    GLfloat texw;
hfutrell@2739
   107
    GLfloat texh;
hfutrell@2739
   108
    GLenum format;
hfutrell@2739
   109
    GLenum formattype;
hfutrell@2739
   110
    void *pixels;
hfutrell@2739
   111
    int pitch;
slouken@6232
   112
    GLES_FBOList *fbo;
hfutrell@2739
   113
} GLES_TextureData;
hfutrell@2739
   114
icculus@7037
   115
static int
hfutrell@2739
   116
GLES_SetError(const char *prefix, GLenum result)
hfutrell@2739
   117
{
hfutrell@2739
   118
    const char *error;
hfutrell@2739
   119
hfutrell@2739
   120
    switch (result) {
hfutrell@2739
   121
    case GL_NO_ERROR:
hfutrell@2739
   122
        error = "GL_NO_ERROR";
hfutrell@2739
   123
        break;
hfutrell@2739
   124
    case GL_INVALID_ENUM:
hfutrell@2739
   125
        error = "GL_INVALID_ENUM";
hfutrell@2739
   126
        break;
hfutrell@2739
   127
    case GL_INVALID_VALUE:
hfutrell@2739
   128
        error = "GL_INVALID_VALUE";
hfutrell@2739
   129
        break;
hfutrell@2739
   130
    case GL_INVALID_OPERATION:
hfutrell@2739
   131
        error = "GL_INVALID_OPERATION";
hfutrell@2739
   132
        break;
hfutrell@2739
   133
    case GL_STACK_OVERFLOW:
hfutrell@2739
   134
        error = "GL_STACK_OVERFLOW";
hfutrell@2739
   135
        break;
hfutrell@2739
   136
    case GL_STACK_UNDERFLOW:
hfutrell@2739
   137
        error = "GL_STACK_UNDERFLOW";
hfutrell@2739
   138
        break;
hfutrell@2739
   139
    case GL_OUT_OF_MEMORY:
hfutrell@2739
   140
        error = "GL_OUT_OF_MEMORY";
hfutrell@2739
   141
        break;
hfutrell@2739
   142
    default:
hfutrell@2739
   143
        error = "UNKNOWN";
hfutrell@2739
   144
        break;
hfutrell@2739
   145
    }
icculus@7037
   146
    return SDL_SetError("%s: %s", prefix, error);
hfutrell@2739
   147
}
hfutrell@2739
   148
slouken@6188
   149
static int GLES_LoadFunctions(GLES_RenderData * data)
slouken@6188
   150
{
slouken@6190
   151
#if SDL_VIDEO_DRIVER_UIKIT
slouken@6190
   152
#define __SDL_NOGETPROCADDR__
slouken@6190
   153
#elif SDL_VIDEO_DRIVER_ANDROID
slouken@6190
   154
#define __SDL_NOGETPROCADDR__
slouken@6190
   155
#elif SDL_VIDEO_DRIVER_PANDORA
slouken@6190
   156
#define __SDL_NOGETPROCADDR__
slouken@6190
   157
#endif
slouken@6190
   158
slouken@6188
   159
#ifdef __SDL_NOGETPROCADDR__
slouken@6188
   160
#define SDL_PROC(ret,func,params) data->func=func;
icculus@7643
   161
#define SDL_PROC_OES(ret,func,params) data->func=func;
slouken@6188
   162
#else
slouken@6188
   163
#define SDL_PROC(ret,func,params) \
slouken@6188
   164
    do { \
sezero@11872
   165
        data->func = SDL_GL_GetProcAddress(#func); \
slouken@6188
   166
        if ( ! data->func ) { \
philipp@10945
   167
            return SDL_SetError("Couldn't load GLES function %s: %s", #func, SDL_GetError()); \
slouken@6188
   168
        } \
slouken@7191
   169
    } while ( 0 );
gabomdq@7642
   170
#define SDL_PROC_OES(ret,func,params) \
gabomdq@7642
   171
    do { \
sezero@11872
   172
        data->func = SDL_GL_GetProcAddress(#func); \
sylvain@12531
   173
    } while ( 0 );
philipp@9709
   174
#endif /* __SDL_NOGETPROCADDR__ */
slouken@6188
   175
slouken@6188
   176
#include "SDL_glesfuncs.h"
slouken@6188
   177
#undef SDL_PROC
gabomdq@7642
   178
#undef SDL_PROC_OES
slouken@6188
   179
    return 0;
slouken@6188
   180
}
slouken@6188
   181
slouken@10609
   182
static GLES_FBOList *
slouken@6232
   183
GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h)
slouken@6232
   184
{
slouken@6232
   185
   GLES_FBOList *result = data->framebuffers;
slime73@9604
   186
   while ((result) && ((result->w != w) || (result->h != h)) ) {
slouken@6232
   187
       result = result->next;
slouken@6232
   188
   }
slime73@9604
   189
   if (result == NULL) {
slouken@6232
   190
       result = SDL_malloc(sizeof(GLES_FBOList));
slouken@6232
   191
       result->w = w;
slouken@6232
   192
       result->h = h;
slouken@6269
   193
       data->glGenFramebuffersOES(1, &result->FBO);
slouken@6232
   194
       result->next = data->framebuffers;
slouken@6232
   195
       data->framebuffers = result;
slouken@6232
   196
   }
slouken@6232
   197
   return result;
slouken@6232
   198
}
slouken@6232
   199
slouken@6232
   200
slouken@5297
   201
static int
slouken@5297
   202
GLES_ActivateRenderer(SDL_Renderer * renderer)
slouken@5297
   203
{
slouken@5297
   204
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@5297
   205
icculus@12219
   206
    if (SDL_GL_GetCurrentContext() != data->context) {
slouken@5297
   207
        if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
slouken@5297
   208
            return -1;
slouken@5297
   209
        }
slouken@5355
   210
    }
slouken@5355
   211
icculus@12219
   212
    return 0;
hfutrell@2739
   213
}
hfutrell@2739
   214
slouken@5147
   215
static void
slouken@5147
   216
GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
hfutrell@2739
   217
{
slouken@6190
   218
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@7191
   219
slouken@6060
   220
    if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
slouken@6060
   221
        /* According to Apple documentation, we need to finish drawing NOW! */
slouken@6232
   222
        data->glFinish();
slouken@6060
   223
    }
hfutrell@2739
   224
}
hfutrell@2739
   225
slime73@9530
   226
static int
slime73@9530
   227
GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
slime73@9530
   228
{
slime73@9530
   229
    SDL_GL_GetDrawableSize(renderer->window, w, h);
slime73@9530
   230
    return 0;
slime73@9530
   231
}
slime73@9530
   232
slouken@11282
   233
static GLenum GetBlendFunc(SDL_BlendFactor factor)
slouken@11282
   234
{
slouken@11282
   235
    switch (factor) {
slouken@11282
   236
    case SDL_BLENDFACTOR_ZERO:
slouken@11282
   237
        return GL_ZERO;
slouken@11282
   238
    case SDL_BLENDFACTOR_ONE:
slouken@11282
   239
        return GL_ONE;
slouken@11282
   240
    case SDL_BLENDFACTOR_SRC_COLOR:
slouken@11282
   241
        return GL_SRC_COLOR;
slouken@11282
   242
    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
slouken@11282
   243
        return GL_ONE_MINUS_SRC_COLOR;
slouken@11282
   244
    case SDL_BLENDFACTOR_SRC_ALPHA:
slouken@11282
   245
        return GL_SRC_ALPHA;
slouken@11282
   246
    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
slouken@11282
   247
        return GL_ONE_MINUS_SRC_ALPHA;
slouken@11282
   248
    case SDL_BLENDFACTOR_DST_COLOR:
slouken@11282
   249
        return GL_DST_COLOR;
slouken@11282
   250
    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
slouken@11282
   251
        return GL_ONE_MINUS_DST_COLOR;
slouken@11282
   252
    case SDL_BLENDFACTOR_DST_ALPHA:
slouken@11282
   253
        return GL_DST_ALPHA;
slouken@11282
   254
    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
slouken@11282
   255
        return GL_ONE_MINUS_DST_ALPHA;
slouken@11282
   256
    default:
slouken@11282
   257
        return GL_INVALID_ENUM;
slouken@11282
   258
    }
slouken@11282
   259
}
slouken@11282
   260
slouken@11282
   261
static GLenum GetBlendEquation(SDL_BlendOperation operation)
slouken@11282
   262
{
slouken@11282
   263
    switch (operation) {
slouken@11282
   264
    case SDL_BLENDOPERATION_ADD:
slouken@11282
   265
        return GL_FUNC_ADD_OES;
slouken@11282
   266
    case SDL_BLENDOPERATION_SUBTRACT:
slouken@11282
   267
        return GL_FUNC_SUBTRACT_OES;
slouken@11282
   268
    case SDL_BLENDOPERATION_REV_SUBTRACT:
slouken@11282
   269
        return GL_FUNC_REVERSE_SUBTRACT_OES;
slouken@11282
   270
    default:
slouken@11282
   271
        return GL_INVALID_ENUM;
slouken@11282
   272
    }
slouken@11282
   273
}
slouken@11282
   274
slouken@11282
   275
static SDL_bool
slouken@11282
   276
GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
slouken@11282
   277
{
slouken@11282
   278
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@11282
   279
    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
slouken@11282
   280
    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
slouken@11282
   281
    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
slouken@11282
   282
    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
slouken@11282
   283
    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
slouken@11282
   284
    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
slouken@11282
   285
slouken@11282
   286
    if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
slouken@11282
   287
        GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
slouken@11282
   288
        GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
slouken@11282
   289
        GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
slouken@11282
   290
        GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
slouken@11282
   291
        GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
slouken@11282
   292
        return SDL_FALSE;
slouken@11282
   293
    }
slouken@11282
   294
    if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) {
slouken@11282
   295
        return SDL_FALSE;
slouken@11282
   296
    }
slouken@11282
   297
    if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) {
slouken@11282
   298
        return SDL_FALSE;
slouken@11282
   299
    }
slouken@11282
   300
    if (colorOperation != SDL_BLENDOPERATION_ADD && !data->GL_OES_blend_subtract_supported) {
slouken@11282
   301
        return SDL_FALSE;
slouken@11282
   302
    }
slouken@11282
   303
    return SDL_TRUE;
slouken@11282
   304
}
slouken@11282
   305
slouken@7860
   306
static SDL_INLINE int
hfutrell@2739
   307
power_of_2(int input)
hfutrell@2739
   308
{
hfutrell@2739
   309
    int value = 1;
hfutrell@2739
   310
hfutrell@2739
   311
    while (value < input) {
hfutrell@2739
   312
        value <<= 1;
hfutrell@2739
   313
    }
hfutrell@2739
   314
    return value;
hfutrell@2739
   315
}
hfutrell@2739
   316
hfutrell@2739
   317
static int
slouken@3139
   318
GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   319
{
slouken@6188
   320
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   321
    GLES_TextureData *data;
hfutrell@2739
   322
    GLint internalFormat;
hfutrell@2739
   323
    GLenum format, type;
hfutrell@2739
   324
    int texture_w, texture_h;
slouken@5503
   325
    GLenum scaleMode;
hfutrell@2739
   326
    GLenum result;
slouken@3099
   327
slouken@5147
   328
    GLES_ActivateRenderer(renderer);
slouken@5147
   329
slouken@2753
   330
    switch (texture->format) {
slouken@2753
   331
    case SDL_PIXELFORMAT_ABGR8888:
slouken@3139
   332
        internalFormat = GL_RGBA;
slouken@3139
   333
        format = GL_RGBA;
slouken@3139
   334
        type = GL_UNSIGNED_BYTE;
slouken@3139
   335
        break;
slouken@2753
   336
    default:
icculus@7037
   337
        return SDL_SetError("Texture format not supported");
hfutrell@2739
   338
    }
slouken@2753
   339
slouken@2753
   340
    data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
hfutrell@2739
   341
    if (!data) {
icculus@7037
   342
        return SDL_OutOfMemory();
hfutrell@2739
   343
    }
hfutrell@2739
   344
hfutrell@2739
   345
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
hfutrell@2739
   346
        data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
slouken@5402
   347
        data->pixels = SDL_calloc(1, texture->h * data->pitch);
hfutrell@2739
   348
        if (!data->pixels) {
hfutrell@2739
   349
            SDL_free(data);
icculus@7037
   350
            return SDL_OutOfMemory();
hfutrell@2739
   351
        }
hfutrell@2739
   352
    }
hfutrell@2739
   353
sylvain@12531
   354
slouken@6232
   355
    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
gabomdq@7642
   356
        if (!renderdata->GL_OES_framebuffer_object_supported) {
gabomdq@7642
   357
            SDL_free(data);
gabomdq@7642
   358
            return SDL_SetError("GL_OES_framebuffer_object not supported");
gabomdq@7642
   359
        }
gabomdq@7642
   360
        data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h);
slouken@6232
   361
    } else {
gabomdq@7642
   362
        data->fbo = NULL;
slouken@6232
   363
    }
sylvain@12531
   364
hfutrell@2739
   365
slouken@6188
   366
    renderdata->glGetError();
slouken@6188
   367
    renderdata->glEnable(GL_TEXTURE_2D);
slouken@6188
   368
    renderdata->glGenTextures(1, &data->texture);
slouken@7624
   369
    result = renderdata->glGetError();
slouken@7624
   370
    if (result != GL_NO_ERROR) {
slouken@7624
   371
        SDL_free(data);
slouken@7624
   372
        return GLES_SetError("glGenTextures()", result);
slouken@7624
   373
    }
slouken@2753
   374
slouken@2753
   375
    data->type = GL_TEXTURE_2D;
slouken@2753
   376
    /* no NPOV textures allowed in OpenGL ES (yet) */
slouken@2753
   377
    texture_w = power_of_2(texture->w);
slouken@2753
   378
    texture_h = power_of_2(texture->h);
slouken@2753
   379
    data->texw = (GLfloat) texture->w / texture_w;
slouken@2753
   380
    data->texh = (GLfloat) texture->h / texture_h;
slouken@2753
   381
hfutrell@2739
   382
    data->format = format;
hfutrell@2739
   383
    data->formattype = type;
slouken@11958
   384
    scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
slouken@6188
   385
    renderdata->glBindTexture(data->type, data->texture);
slouken@6188
   386
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
slouken@6188
   387
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
slouken@6188
   388
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
slouken@6188
   389
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
slouken@2753
   390
slouken@6188
   391
    renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
slouken@2753
   392
                             texture_h, 0, format, type, NULL);
slouken@6188
   393
    renderdata->glDisable(GL_TEXTURE_2D);
icculus@12593
   394
    renderdata->drawstate.texture = texture;
icculus@12593
   395
    renderdata->drawstate.texturing = SDL_FALSE;
hfutrell@2739
   396
slouken@6188
   397
    result = renderdata->glGetError();
hfutrell@2739
   398
    if (result != GL_NO_ERROR) {
gabomdq@7642
   399
        SDL_free(data);
icculus@7037
   400
        return GLES_SetError("glTexImage2D()", result);
hfutrell@2739
   401
    }
sylvain@12531
   402
gabomdq@7642
   403
    texture->driverdata = data;
hfutrell@2739
   404
    return 0;
hfutrell@2739
   405
}
hfutrell@2739
   406
hfutrell@2739
   407
static int
slouken@3139
   408
GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@3139
   409
                   const SDL_Rect * rect, const void *pixels, int pitch)
hfutrell@2739
   410
{
slouken@6188
   411
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   412
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
slouken@5227
   413
    Uint8 *blob = NULL;
slouken@5227
   414
    Uint8 *src;
slouken@5227
   415
    int srcPitch;
slouken@5227
   416
    int y;
hfutrell@2739
   417
slouken@5147
   418
    GLES_ActivateRenderer(renderer);
slouken@5147
   419
slouken@5227
   420
    /* Bail out if we're supposed to update an empty rectangle */
slime73@9604
   421
    if (rect->w <= 0 || rect->h <= 0) {
slouken@5227
   422
        return 0;
slime73@9604
   423
    }
slouken@5227
   424
slouken@5227
   425
    /* Reformat the texture data into a tightly packed array */
slouken@5227
   426
    srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
slouken@5227
   427
    src = (Uint8 *)pixels;
icculus@7037
   428
    if (pitch != srcPitch) {
slouken@5227
   429
        blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
icculus@7037
   430
        if (!blob) {
icculus@7037
   431
            return SDL_OutOfMemory();
slouken@5227
   432
        }
slouken@5227
   433
        src = blob;
icculus@7037
   434
        for (y = 0; y < rect->h; ++y) {
slouken@5227
   435
            SDL_memcpy(src, pixels, srcPitch);
slouken@5227
   436
            src += srcPitch;
slouken@5227
   437
            pixels = (Uint8 *)pixels + pitch;
slouken@5227
   438
        }
slouken@5227
   439
        src = blob;
slouken@5227
   440
    }
slouken@5227
   441
slouken@5227
   442
    /* Create a texture subimage with the supplied data */
slouken@6188
   443
    renderdata->glGetError();
slouken@6188
   444
    renderdata->glEnable(data->type);
slouken@6188
   445
    renderdata->glBindTexture(data->type, data->texture);
slouken@6188
   446
    renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
slouken@6188
   447
    renderdata->glTexSubImage2D(data->type,
slouken@5227
   448
                    0,
slouken@5227
   449
                    rect->x,
slouken@5227
   450
                    rect->y,
slouken@5227
   451
                    rect->w,
slouken@5227
   452
                    rect->h,
slouken@5227
   453
                    data->format,
slouken@5227
   454
                    data->formattype,
slouken@5227
   455
                    src);
slouken@10425
   456
    renderdata->glDisable(data->type);
slouken@7719
   457
    SDL_free(blob);
slouken@5052
   458
icculus@12593
   459
    renderdata->drawstate.texture = texture;
icculus@12593
   460
    renderdata->drawstate.texturing = SDL_FALSE;
icculus@12593
   461
slime73@9604
   462
    if (renderdata->glGetError() != GL_NO_ERROR) {
icculus@7037
   463
        return SDL_SetError("Failed to update texture");
hfutrell@2739
   464
    }
hfutrell@2739
   465
    return 0;
hfutrell@2739
   466
}
hfutrell@2739
   467
hfutrell@2739
   468
static int
hfutrell@2739
   469
GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   470
                 const SDL_Rect * rect, void **pixels, int *pitch)
hfutrell@2739
   471
{
hfutrell@2739
   472
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   473
hfutrell@2739
   474
    *pixels =
hfutrell@2739
   475
        (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
hfutrell@2739
   476
                  rect->x * SDL_BYTESPERPIXEL(texture->format));
hfutrell@2739
   477
    *pitch = data->pitch;
hfutrell@2739
   478
    return 0;
hfutrell@2739
   479
}
hfutrell@2739
   480
hfutrell@2739
   481
static void
hfutrell@2739
   482
GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   483
{
slouken@5156
   484
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
slouken@5227
   485
    SDL_Rect rect;
hfutrell@2739
   486
slouken@5227
   487
    /* We do whole texture updates, at least for now */
slouken@5227
   488
    rect.x = 0;
slouken@5227
   489
    rect.y = 0;
slouken@5227
   490
    rect.w = texture->w;
slouken@5227
   491
    rect.h = texture->h;
slouken@5227
   492
    GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
hfutrell@2739
   493
}
hfutrell@2739
   494
slouken@5297
   495
static int
slouken@6247
   496
GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@6246
   497
{
slouken@6246
   498
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@6246
   499
    GLES_TextureData *texturedata = NULL;
slouken@6246
   500
    GLenum status;
slouken@6246
   501
gabomdq@7642
   502
    if (!data->GL_OES_framebuffer_object_supported) {
gabomdq@7642
   503
        return SDL_SetError("Can't enable render target support in this renderer");
gabomdq@7642
   504
    }
slouken@6246
   505
sylvain@12621
   506
    data->drawstate.viewport_dirty = SDL_TRUE;
sylvain@12621
   507
slouken@6246
   508
    if (texture == NULL) {
slouken@6271
   509
        data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
slouken@6246
   510
        return 0;
slouken@6246
   511
    }
slouken@6246
   512
slouken@6246
   513
    texturedata = (GLES_TextureData *) texture->driverdata;
slouken@6246
   514
    data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
slouken@6246
   515
    /* TODO: check if texture pixel format allows this operation */
slouken@6246
   516
    data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
slouken@6246
   517
    /* Check FBO status */
slouken@6246
   518
    status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
slouken@6246
   519
    if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
icculus@7037
   520
        return SDL_SetError("glFramebufferTexture2DOES() failed");
slouken@6246
   521
    }
slouken@6246
   522
    return 0;
slouken@6246
   523
}
slouken@6246
   524
icculus@12219
   525
slouken@6246
   526
static int
icculus@12219
   527
GLES_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
slouken@5224
   528
{
icculus@12219
   529
    return 0;  /* nothing to do in this backend. */
slouken@5224
   530
}
slouken@5224
   531
slouken@7141
   532
static int
icculus@12219
   533
GLES_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
slouken@7141
   534
{
icculus@12219
   535
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
slouken@12665
   536
    int i;
slouken@7141
   537
icculus@12219
   538
    if (!verts) {
icculus@12219
   539
        return -1;
gabomdq@7160
   540
    }
gabomdq@7160
   541
icculus@12219
   542
    cmd->data.draw.count = count;
icculus@12219
   543
    for (i = 0; i < count; i++) {
icculus@12219
   544
        *(verts++) = 0.5f + points[i].x;
icculus@12219
   545
        *(verts++) = 0.5f + points[i].y;
slouken@10408
   546
    }
slouken@10408
   547
slouken@5355
   548
    return 0;
slouken@5355
   549
}
slouken@5355
   550
hfutrell@2739
   551
static int
icculus@12219
   552
GLES_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
hfutrell@2739
   553
{
icculus@12219
   554
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
slouken@12665
   555
    int i;
slouken@2753
   556
icculus@12219
   557
    if (!verts) {
icculus@12219
   558
        return -1;
slouken@8993
   559
    }
slouken@8993
   560
icculus@12219
   561
    cmd->data.draw.count = count;
slouken@2936
   562
icculus@12219
   563
    for (i = 0; i < count; i++) {
slouken@6528
   564
        const SDL_FRect *rect = &rects[i];
icculus@12219
   565
        const GLfloat minx = rect->x;
icculus@12219
   566
        const GLfloat maxx = rect->x + rect->w;
icculus@12219
   567
        const GLfloat miny = rect->y;
icculus@12219
   568
        const GLfloat maxy = rect->y + rect->h;
icculus@12219
   569
        *(verts++) = minx;
icculus@12219
   570
        *(verts++) = miny;
icculus@12219
   571
        *(verts++) = maxx;
icculus@12219
   572
        *(verts++) = miny;
icculus@12219
   573
        *(verts++) = minx;
icculus@12219
   574
        *(verts++) = maxy;
icculus@12219
   575
        *(verts++) = maxx;
icculus@12219
   576
        *(verts++) = maxy;
slouken@3536
   577
    }
hfutrell@2949
   578
slouken@2753
   579
    return 0;
hfutrell@2739
   580
}
hfutrell@2739
   581
hfutrell@2739
   582
static int
icculus@12219
   583
GLES_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
icculus@12219
   584
                          const SDL_Rect * srcrect, const SDL_FRect * dstrect)
hfutrell@2739
   585
{
icculus@12235
   586
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
slouken@6528
   587
    GLfloat minx, miny, maxx, maxy;
hfutrell@2739
   588
    GLfloat minu, maxu, minv, maxv;
icculus@12219
   589
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
slouken@2753
   590
icculus@12219
   591
    if (!verts) {
icculus@12219
   592
        return -1;
hfutrell@2739
   593
    }
hfutrell@2739
   594
icculus@12219
   595
    cmd->data.draw.count = 1;
slouken@5355
   596
slouken@10399
   597
    minx = dstrect->x;
slouken@10399
   598
    miny = dstrect->y;
slouken@10399
   599
    maxx = dstrect->x + dstrect->w;
slouken@10399
   600
    maxy = dstrect->y + dstrect->h;
slouken@5154
   601
slouken@10399
   602
    minu = (GLfloat) srcrect->x / texture->w;
slouken@10399
   603
    minu *= texturedata->texw;
slouken@10399
   604
    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
slouken@10399
   605
    maxu *= texturedata->texw;
slouken@10399
   606
    minv = (GLfloat) srcrect->y / texture->h;
slouken@10399
   607
    minv *= texturedata->texh;
slouken@10399
   608
    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
slouken@10399
   609
    maxv *= texturedata->texh;
slouken@2753
   610
icculus@12219
   611
    *(verts++) = minx;
icculus@12219
   612
    *(verts++) = miny;
icculus@12219
   613
    *(verts++) = maxx;
icculus@12219
   614
    *(verts++) = miny;
icculus@12219
   615
    *(verts++) = minx;
icculus@12219
   616
    *(verts++) = maxy;
icculus@12219
   617
    *(verts++) = maxx;
icculus@12219
   618
    *(verts++) = maxy;
slouken@2753
   619
icculus@12219
   620
    *(verts++) = minu;
icculus@12219
   621
    *(verts++) = minv;
icculus@12219
   622
    *(verts++) = maxu;
icculus@12219
   623
    *(verts++) = minv;
icculus@12219
   624
    *(verts++) = minu;
icculus@12219
   625
    *(verts++) = maxv;
icculus@12219
   626
    *(verts++) = maxu;
icculus@12219
   627
    *(verts++) = maxv;
slouken@2753
   628
hfutrell@2739
   629
    return 0;
hfutrell@2739
   630
}
hfutrell@2739
   631
slouken@6043
   632
static int
icculus@12219
   633
GLES_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
icculus@12219
   634
                        const SDL_Rect * srcquad, const SDL_FRect * dstrect,
icculus@12219
   635
                        const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
slouken@6528
   636
{
icculus@12235
   637
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
icculus@12219
   638
    GLfloat minx, miny, maxx, maxy;
icculus@12219
   639
    GLfloat centerx, centery;
icculus@12219
   640
    GLfloat minu, maxu, minv, maxv;
icculus@12219
   641
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 19 * sizeof (GLfloat), 0, &cmd->data.draw.first);
slouken@6528
   642
icculus@12219
   643
    if (!verts) {
icculus@12219
   644
        return -1;
slouken@6528
   645
    }
slouken@6528
   646
slouken@6528
   647
    centerx = center->x;
slouken@6528
   648
    centery = center->y;
slouken@6528
   649
slouken@6528
   650
    if (flip & SDL_FLIP_HORIZONTAL) {
slouken@6528
   651
        minx =  dstrect->w - centerx;
slouken@6528
   652
        maxx = -centerx;
icculus@12219
   653
    }
icculus@12219
   654
    else {
slouken@6528
   655
        minx = -centerx;
icculus@12219
   656
        maxx =  dstrect->w - centerx;
slouken@6528
   657
    }
slouken@6528
   658
slouken@6528
   659
    if (flip & SDL_FLIP_VERTICAL) {
icculus@12219
   660
        miny =  dstrect->h - centery;
slouken@6528
   661
        maxy = -centery;
icculus@12219
   662
    }
icculus@12219
   663
    else {
slouken@6528
   664
        miny = -centery;
icculus@12219
   665
        maxy =  dstrect->h - centery;
slouken@6528
   666
    }
slouken@6528
   667
icculus@12235
   668
    minu = (GLfloat) srcquad->x / texture->w;
slouken@6528
   669
    minu *= texturedata->texw;
icculus@12235
   670
    maxu = (GLfloat) (srcquad->x + srcquad->w) / texture->w;
slouken@6528
   671
    maxu *= texturedata->texw;
icculus@12235
   672
    minv = (GLfloat) srcquad->y / texture->h;
slouken@6528
   673
    minv *= texturedata->texh;
icculus@12235
   674
    maxv = (GLfloat) (srcquad->y + srcquad->h) / texture->h;
slouken@6528
   675
    maxv *= texturedata->texh;
slouken@6528
   676
icculus@12219
   677
    cmd->data.draw.count = 1;
slouken@6528
   678
icculus@12219
   679
    *(verts++) = minx;
icculus@12219
   680
    *(verts++) = miny;
icculus@12219
   681
    *(verts++) = maxx;
icculus@12219
   682
    *(verts++) = miny;
icculus@12219
   683
    *(verts++) = minx;
icculus@12219
   684
    *(verts++) = maxy;
icculus@12219
   685
    *(verts++) = maxx;
icculus@12219
   686
    *(verts++) = maxy;
icculus@12219
   687
icculus@12219
   688
    *(verts++) = minu;
icculus@12219
   689
    *(verts++) = minv;
icculus@12219
   690
    *(verts++) = maxu;
icculus@12219
   691
    *(verts++) = minv;
icculus@12219
   692
    *(verts++) = minu;
icculus@12219
   693
    *(verts++) = maxv;
icculus@12219
   694
    *(verts++) = maxu;
icculus@12219
   695
    *(verts++) = maxv;
icculus@12219
   696
icculus@12219
   697
    *(verts++) = (GLfloat) dstrect->x + centerx;
icculus@12219
   698
    *(verts++) = (GLfloat) dstrect->y + centery;
icculus@12219
   699
    *(verts++) = (GLfloat) angle;
slouken@6528
   700
slouken@6528
   701
    return 0;
slouken@6528
   702
}
slouken@6528
   703
icculus@12219
   704
static void
icculus@12238
   705
SetDrawState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
icculus@12219
   706
{
icculus@12219
   707
    const SDL_BlendMode blend = cmd->data.draw.blend;
sylvain@12484
   708
    const Uint8 r = cmd->data.draw.r;
sylvain@12484
   709
    const Uint8 g = cmd->data.draw.g;
sylvain@12484
   710
    const Uint8 b = cmd->data.draw.b;
sylvain@12484
   711
    const Uint8 a = cmd->data.draw.a;
icculus@12282
   712
    const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
icculus@12282
   713
icculus@12282
   714
    if (color != data->drawstate.color) {
icculus@12282
   715
        const GLfloat fr = ((GLfloat) r) * inv255f;
icculus@12282
   716
        const GLfloat fg = ((GLfloat) g) * inv255f;
icculus@12282
   717
        const GLfloat fb = ((GLfloat) b) * inv255f;
icculus@12282
   718
        const GLfloat fa = ((GLfloat) a) * inv255f;
icculus@12282
   719
        data->glColor4f(fr, fg, fb, fa);
icculus@12282
   720
        data->drawstate.color = color;
icculus@12282
   721
    }
icculus@12282
   722
icculus@12282
   723
    if (data->drawstate.viewport_dirty) {
icculus@12282
   724
        const SDL_Rect *viewport = &data->drawstate.viewport;
icculus@12282
   725
        const SDL_bool istarget = (data->drawstate.target != NULL);
icculus@12282
   726
        data->glMatrixMode(GL_PROJECTION);
icculus@12282
   727
        data->glLoadIdentity();
icculus@12282
   728
        data->glViewport(viewport->x,
icculus@12282
   729
                         istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
icculus@12282
   730
                         viewport->w, viewport->h);
icculus@12282
   731
        if (viewport->w && viewport->h) {
icculus@12282
   732
            data->glOrthof((GLfloat) 0, (GLfloat) viewport->w,
icculus@12418
   733
                           (GLfloat) (istarget ? 0 : viewport->h),
icculus@12418
   734
                           (GLfloat) (istarget ? viewport->h : 0),
icculus@12282
   735
                           0.0, 1.0);
icculus@12282
   736
        }
icculus@12282
   737
        data->glMatrixMode(GL_MODELVIEW);
icculus@12282
   738
        data->drawstate.viewport_dirty = SDL_FALSE;
icculus@12282
   739
    }
icculus@12282
   740
icculus@12282
   741
    if (data->drawstate.cliprect_enabled_dirty) {
icculus@12282
   742
        if (data->drawstate.cliprect_enabled) {
icculus@12282
   743
            data->glEnable(GL_SCISSOR_TEST);
icculus@12282
   744
        } else {
icculus@12282
   745
            data->glDisable(GL_SCISSOR_TEST);
icculus@12282
   746
        }
icculus@12282
   747
        data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
icculus@12282
   748
    }
icculus@12282
   749
icculus@12282
   750
    if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
icculus@12282
   751
        const SDL_Rect *viewport = &data->drawstate.viewport;
icculus@12282
   752
        const SDL_Rect *rect = &data->drawstate.cliprect;
icculus@12282
   753
        const SDL_bool istarget = (data->drawstate.target != NULL);
icculus@12282
   754
        data->glScissor(viewport->x + rect->x,
icculus@12282
   755
                        istarget ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
icculus@12282
   756
                        rect->w, rect->h);
icculus@12282
   757
        data->drawstate.cliprect_dirty = SDL_FALSE;
icculus@12282
   758
    }
icculus@12219
   759
icculus@12238
   760
    if (blend != data->drawstate.blend) {
icculus@12219
   761
        if (blend == SDL_BLENDMODE_NONE) {
icculus@12219
   762
            data->glDisable(GL_BLEND);
icculus@12219
   763
        } else {
icculus@12219
   764
            data->glEnable(GL_BLEND);
icculus@12219
   765
            if (data->GL_OES_blend_func_separate_supported) {
icculus@12219
   766
                data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
icculus@12219
   767
                                             GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
icculus@12219
   768
                                             GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
icculus@12219
   769
                                             GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
icculus@12219
   770
            } else {
icculus@12219
   771
                data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
icculus@12219
   772
                                  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
icculus@12219
   773
            }
icculus@12219
   774
            if (data->GL_OES_blend_equation_separate_supported) {
icculus@12219
   775
                data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
icculus@12219
   776
                                                 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
icculus@12219
   777
            } else if (data->GL_OES_blend_subtract_supported) {
icculus@12219
   778
                data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
icculus@12219
   779
            }
icculus@12219
   780
        }
icculus@12238
   781
        data->drawstate.blend = blend;
icculus@12219
   782
    }
icculus@12219
   783
icculus@12238
   784
    if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
icculus@12219
   785
        if (cmd->data.draw.texture == NULL) {
icculus@12219
   786
            data->glDisable(GL_TEXTURE_2D);
icculus@12219
   787
            data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
icculus@12238
   788
            data->drawstate.texturing = SDL_FALSE;
icculus@12219
   789
        } else {
icculus@12219
   790
            data->glEnable(GL_TEXTURE_2D);
icculus@12219
   791
            data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
icculus@12238
   792
            data->drawstate.texturing = SDL_TRUE;
icculus@12219
   793
        }
icculus@12219
   794
    }
icculus@12219
   795
}
icculus@12219
   796
icculus@12219
   797
static void
icculus@12264
   798
SetCopyState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
icculus@12219
   799
{
icculus@12219
   800
    SDL_Texture *texture = cmd->data.draw.texture;
icculus@12238
   801
    SetDrawState(data, cmd);
icculus@12219
   802
icculus@12238
   803
    if (texture != data->drawstate.texture) {
icculus@12235
   804
        GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
icculus@12235
   805
        data->glBindTexture(GL_TEXTURE_2D, texturedata->texture);
icculus@12238
   806
        data->drawstate.texture = texture;
icculus@12219
   807
    }
icculus@12219
   808
}
icculus@12219
   809
icculus@12219
   810
static int
icculus@12219
   811
GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
icculus@12219
   812
{
icculus@12219
   813
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
icculus@12219
   814
    size_t i;
icculus@12219
   815
icculus@12219
   816
    if (GLES_ActivateRenderer(renderer) < 0) {
icculus@12219
   817
        return -1;
icculus@12219
   818
    }
icculus@12219
   819
icculus@12282
   820
    data->drawstate.target = renderer->target;
icculus@12282
   821
icculus@12282
   822
    if (!renderer->target) {
icculus@12282
   823
        SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
icculus@12219
   824
    }
icculus@12219
   825
icculus@12219
   826
    while (cmd) {
icculus@12219
   827
        switch (cmd->command) {
icculus@12219
   828
            case SDL_RENDERCMD_SETDRAWCOLOR: {
icculus@12282
   829
                break;  /* not used in this render backend. */
icculus@12219
   830
            }
icculus@12219
   831
icculus@12219
   832
            case SDL_RENDERCMD_SETVIEWPORT: {
icculus@12238
   833
                SDL_Rect *viewport = &data->drawstate.viewport;
icculus@12238
   834
                if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
icculus@12238
   835
                    SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
icculus@12282
   836
                    data->drawstate.viewport_dirty = SDL_TRUE;
icculus@12264
   837
                }
icculus@12219
   838
                break;
icculus@12219
   839
            }
icculus@12219
   840
icculus@12219
   841
            case SDL_RENDERCMD_SETCLIPRECT: {
icculus@12219
   842
                const SDL_Rect *rect = &cmd->data.cliprect.rect;
icculus@12238
   843
                if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
icculus@12238
   844
                    data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
icculus@12282
   845
                    data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
icculus@12282
   846
                }
icculus@12282
   847
                if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
icculus@12282
   848
                    SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
icculus@12282
   849
                    data->drawstate.cliprect_dirty = SDL_TRUE;
icculus@12219
   850
                }
icculus@12219
   851
                break;
icculus@12219
   852
            }
icculus@12219
   853
icculus@12219
   854
            case SDL_RENDERCMD_CLEAR: {
icculus@12238
   855
                const Uint8 r = cmd->data.color.r;
icculus@12238
   856
                const Uint8 g = cmd->data.color.g;
icculus@12238
   857
                const Uint8 b = cmd->data.color.b;
icculus@12238
   858
                const Uint8 a = cmd->data.color.a;
icculus@12238
   859
                const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
icculus@12238
   860
                if (color != data->drawstate.clear_color) {
icculus@12238
   861
                    const GLfloat fr = ((GLfloat) r) * inv255f;
icculus@12238
   862
                    const GLfloat fg = ((GLfloat) g) * inv255f;
icculus@12238
   863
                    const GLfloat fb = ((GLfloat) b) * inv255f;
icculus@12238
   864
                    const GLfloat fa = ((GLfloat) a) * inv255f;
icculus@12238
   865
                    data->glClearColor(fr, fg, fb, fa);
icculus@12238
   866
                    data->drawstate.clear_color = color;
icculus@12238
   867
                }
icculus@12219
   868
icculus@12264
   869
                if (data->drawstate.cliprect_enabled) {
icculus@12219
   870
                    data->glDisable(GL_SCISSOR_TEST);
icculus@12282
   871
                    data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
icculus@12219
   872
                }
icculus@12219
   873
icculus@12219
   874
                data->glClear(GL_COLOR_BUFFER_BIT);
icculus@12219
   875
icculus@12219
   876
                break;
icculus@12219
   877
            }
icculus@12219
   878
icculus@12219
   879
            case SDL_RENDERCMD_DRAW_POINTS: {
icculus@12219
   880
                const size_t count = cmd->data.draw.count;
icculus@12219
   881
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12238
   882
                SetDrawState(data, cmd);
icculus@12235
   883
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12418
   884
                data->glDrawArrays(GL_POINTS, 0, (GLsizei) count);
icculus@12219
   885
                break;
icculus@12219
   886
            }
icculus@12219
   887
icculus@12219
   888
            case SDL_RENDERCMD_DRAW_LINES: {
icculus@12219
   889
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12235
   890
                const size_t count = cmd->data.draw.count;
icculus@12238
   891
                SetDrawState(data, cmd);
icculus@12219
   892
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12235
   893
                if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
icculus@12219
   894
                    /* GL_LINE_LOOP takes care of the final segment */
icculus@12418
   895
                    data->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) (count - 1));
icculus@12219
   896
                } else {
icculus@12418
   897
                    data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
icculus@12219
   898
                    /* We need to close the endpoint of the line */
icculus@12418
   899
                    data->glDrawArrays(GL_POINTS, (GLsizei) (count - 1), 1);
icculus@12219
   900
                }
icculus@12219
   901
                break;
icculus@12219
   902
            }
icculus@12219
   903
icculus@12219
   904
            case SDL_RENDERCMD_FILL_RECTS: {
icculus@12219
   905
                const size_t count = cmd->data.draw.count;
icculus@12219
   906
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12418
   907
                GLsizei offset = 0;
icculus@12238
   908
                SetDrawState(data, cmd);
icculus@12219
   909
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12219
   910
                for (i = 0; i < count; ++i, offset += 4) {
icculus@12219
   911
                    data->glDrawArrays(GL_TRIANGLE_STRIP, offset, 4);
icculus@12219
   912
                }
icculus@12219
   913
                break;
icculus@12219
   914
            }
icculus@12219
   915
icculus@12219
   916
            case SDL_RENDERCMD_COPY: {
icculus@12219
   917
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12238
   918
                SetCopyState(data, cmd);
icculus@12219
   919
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12219
   920
                data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
icculus@12219
   921
                data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
icculus@12219
   922
                break;
icculus@12219
   923
            }
icculus@12219
   924
icculus@12219
   925
            case SDL_RENDERCMD_COPY_EX: {
icculus@12219
   926
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12219
   927
                const GLfloat translatex = verts[16];
icculus@12219
   928
                const GLfloat translatey = verts[17];
icculus@12219
   929
                const GLfloat angle = verts[18];
icculus@12238
   930
                SetCopyState(data, cmd);
icculus@12219
   931
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12219
   932
                data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
icculus@12219
   933
icculus@12219
   934
                /* Translate to flip, rotate, translate to position */
icculus@12219
   935
                data->glPushMatrix();
icculus@12219
   936
                data->glTranslatef(translatex, translatey, 0.0f);
icculus@12219
   937
                data->glRotatef(angle, 0.0, 0.0, 1.0);
icculus@12219
   938
                data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
icculus@12219
   939
                data->glPopMatrix();
icculus@12219
   940
                break;
icculus@12219
   941
            }
icculus@12219
   942
icculus@12219
   943
            case SDL_RENDERCMD_NO_OP:
icculus@12219
   944
                break;
icculus@12219
   945
        }
icculus@12219
   946
icculus@12219
   947
        cmd = cmd->next;
icculus@12219
   948
    }
icculus@12219
   949
icculus@12235
   950
    return 0;
icculus@12219
   951
}
icculus@12219
   952
slouken@6528
   953
static int
slouken@6043
   954
GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
icculus@12264
   955
                      Uint32 pixel_format, void * pixels, int pitch)
slouken@6043
   956
{
slouken@6188
   957
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@10406
   958
    Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
slouken@6043
   959
    void *temp_pixels;
slouken@6043
   960
    int temp_pitch;
slouken@6043
   961
    Uint8 *src, *dst, *tmp;
slouken@6043
   962
    int w, h, length, rows;
slouken@6043
   963
    int status;
slouken@6043
   964
slouken@6043
   965
    GLES_ActivateRenderer(renderer);
slouken@6043
   966
slouken@6043
   967
    temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@6043
   968
    temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@6043
   969
    if (!temp_pixels) {
icculus@7037
   970
        return SDL_OutOfMemory();
slouken@6043
   971
    }
slouken@6043
   972
slouken@7420
   973
    SDL_GetRendererOutputSize(renderer, &w, &h);
slouken@6043
   974
slouken@6188
   975
    data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
slouken@6043
   976
slouken@10405
   977
    data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
slouken@10405
   978
                       rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
slouken@6043
   979
slouken@10405
   980
    /* Flip the rows to be top-down if necessary */
slouken@10405
   981
    if (!renderer->target) {
icculus@12349
   982
        SDL_bool isstack;
slouken@10405
   983
        length = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@10405
   984
        src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
slouken@10405
   985
        dst = (Uint8*)temp_pixels;
icculus@12349
   986
        tmp = SDL_small_alloc(Uint8, length, &isstack);
slouken@10405
   987
        rows = rect->h / 2;
slouken@10405
   988
        while (rows--) {
slouken@10405
   989
            SDL_memcpy(tmp, dst, length);
slouken@10405
   990
            SDL_memcpy(dst, src, length);
slouken@10405
   991
            SDL_memcpy(src, tmp, length);
slouken@10405
   992
            dst += temp_pitch;
slouken@10405
   993
            src -= temp_pitch;
slouken@10405
   994
        }
icculus@12349
   995
        SDL_small_free(tmp, isstack);
slouken@6043
   996
    }
slouken@6043
   997
slouken@6043
   998
    status = SDL_ConvertPixels(rect->w, rect->h,
slouken@6043
   999
                               temp_format, temp_pixels, temp_pitch,
slouken@6043
  1000
                               pixel_format, pixels, pitch);
slouken@6043
  1001
    SDL_free(temp_pixels);
slouken@6043
  1002
slouken@6043
  1003
    return status;
slouken@6043
  1004
}
slouken@6043
  1005
hfutrell@2739
  1006
static void
slouken@3139
  1007
GLES_RenderPresent(SDL_Renderer * renderer)
hfutrell@2739
  1008
{
slouken@5147
  1009
    GLES_ActivateRenderer(renderer);
slouken@5147
  1010
hfutrell@2739
  1011
    SDL_GL_SwapWindow(renderer->window);
hfutrell@2739
  1012
}
hfutrell@2739
  1013
hfutrell@2739
  1014
static void
hfutrell@2739
  1015
GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
  1016
{
slouken@6188
  1017
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
slouken@6188
  1018
hfutrell@2739
  1019
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
  1020
slouken@5147
  1021
    GLES_ActivateRenderer(renderer);
slouken@5147
  1022
sylvain@12485
  1023
    if (renderdata->drawstate.texture == texture) {
sylvain@12485
  1024
        renderdata->drawstate.texture = NULL;
sylvain@12485
  1025
    }
sylvain@12485
  1026
    if (renderdata->drawstate.target == texture) {
sylvain@12485
  1027
        renderdata->drawstate.target = NULL;
sylvain@12485
  1028
    }
sylvain@12485
  1029
hfutrell@2739
  1030
    if (!data) {
hfutrell@2739
  1031
        return;
hfutrell@2739
  1032
    }
hfutrell@2739
  1033
    if (data->texture) {
slouken@6188
  1034
        renderdata->glDeleteTextures(1, &data->texture);
hfutrell@2739
  1035
    }
slouken@7719
  1036
    SDL_free(data->pixels);
hfutrell@2739
  1037
    SDL_free(data);
hfutrell@2739
  1038
    texture->driverdata = NULL;
hfutrell@2739
  1039
}
hfutrell@2739
  1040
hfutrell@2739
  1041
static void
hfutrell@2739
  1042
GLES_DestroyRenderer(SDL_Renderer * renderer)
hfutrell@2739
  1043
{
hfutrell@2739
  1044
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
  1045
hfutrell@2739
  1046
    if (data) {
hfutrell@2739
  1047
        if (data->context) {
slouken@6232
  1048
            while (data->framebuffers) {
slouken@6232
  1049
               GLES_FBOList *nextnode = data->framebuffers->next;
slouken@6232
  1050
               data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
slouken@6232
  1051
               SDL_free(data->framebuffers);
slouken@6232
  1052
               data->framebuffers = nextnode;
slouken@6232
  1053
            }
hfutrell@2739
  1054
            SDL_GL_DeleteContext(data->context);
hfutrell@2739
  1055
        }
hfutrell@2739
  1056
        SDL_free(data);
hfutrell@2739
  1057
    }
hfutrell@2739
  1058
    SDL_free(renderer);
hfutrell@2739
  1059
}
hfutrell@2739
  1060
slouken@6954
  1061
static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
slouken@6954
  1062
{
gabomdq@6414
  1063
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
gabomdq@6414
  1064
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
gabomdq@6414
  1065
    GLES_ActivateRenderer(renderer);
gabomdq@6414
  1066
gabomdq@6414
  1067
    data->glEnable(GL_TEXTURE_2D);
gabomdq@6414
  1068
    data->glBindTexture(texturedata->type, texturedata->texture);
gabomdq@6414
  1069
icculus@12593
  1070
    data->drawstate.texture = texture;
icculus@12593
  1071
    data->drawstate.texturing = SDL_TRUE;
icculus@12593
  1072
slime73@9604
  1073
    if (texw) {
slime73@9604
  1074
        *texw = (float)texturedata->texw;
slime73@9604
  1075
    }
slime73@9604
  1076
    if (texh) {
slime73@9604
  1077
        *texh = (float)texturedata->texh;
slime73@9604
  1078
    }
gabomdq@6414
  1079
gabomdq@6414
  1080
    return 0;
gabomdq@6414
  1081
}
gabomdq@6414
  1082
slouken@6954
  1083
static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
slouken@6954
  1084
{
gabomdq@6414
  1085
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
gabomdq@6414
  1086
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
gabomdq@6414
  1087
    GLES_ActivateRenderer(renderer);
gabomdq@6414
  1088
    data->glDisable(texturedata->type);
gabomdq@6414
  1089
icculus@12593
  1090
    data->drawstate.texture = NULL;
icculus@12593
  1091
    data->drawstate.texturing = SDL_FALSE;
icculus@12593
  1092
gabomdq@6414
  1093
    return 0;
gabomdq@6414
  1094
}
gabomdq@6414
  1095
icculus@12418
  1096
static SDL_Renderer *
icculus@12219
  1097
GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
icculus@12219
  1098
{
icculus@12219
  1099
    SDL_Renderer *renderer;
icculus@12219
  1100
    GLES_RenderData *data;
icculus@12219
  1101
    GLint value;
icculus@12219
  1102
    Uint32 window_flags;
icculus@12219
  1103
    int profile_mask = 0, major = 0, minor = 0;
icculus@12219
  1104
    SDL_bool changed_window = SDL_FALSE;
icculus@12219
  1105
icculus@12219
  1106
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
icculus@12219
  1107
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
icculus@12219
  1108
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
icculus@12219
  1109
icculus@12219
  1110
    window_flags = SDL_GetWindowFlags(window);
icculus@12219
  1111
    if (!(window_flags & SDL_WINDOW_OPENGL) ||
icculus@12219
  1112
        profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
icculus@12219
  1113
icculus@12219
  1114
        changed_window = SDL_TRUE;
icculus@12219
  1115
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
icculus@12219
  1116
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
icculus@12219
  1117
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
icculus@12219
  1118
icculus@12219
  1119
        if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
icculus@12219
  1120
            goto error;
icculus@12219
  1121
        }
icculus@12219
  1122
    }
icculus@12219
  1123
icculus@12219
  1124
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
icculus@12219
  1125
    if (!renderer) {
icculus@12219
  1126
        SDL_OutOfMemory();
icculus@12219
  1127
        goto error;
icculus@12219
  1128
    }
icculus@12219
  1129
icculus@12219
  1130
    data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
icculus@12219
  1131
    if (!data) {
icculus@12219
  1132
        GLES_DestroyRenderer(renderer);
icculus@12219
  1133
        SDL_OutOfMemory();
icculus@12219
  1134
        goto error;
icculus@12219
  1135
    }
icculus@12219
  1136
icculus@12219
  1137
    renderer->WindowEvent = GLES_WindowEvent;
icculus@12219
  1138
    renderer->GetOutputSize = GLES_GetOutputSize;
icculus@12219
  1139
    renderer->SupportsBlendMode = GLES_SupportsBlendMode;
icculus@12219
  1140
    renderer->CreateTexture = GLES_CreateTexture;
icculus@12219
  1141
    renderer->UpdateTexture = GLES_UpdateTexture;
icculus@12219
  1142
    renderer->LockTexture = GLES_LockTexture;
icculus@12219
  1143
    renderer->UnlockTexture = GLES_UnlockTexture;
icculus@12219
  1144
    renderer->SetRenderTarget = GLES_SetRenderTarget;
icculus@12219
  1145
    renderer->QueueSetViewport = GLES_QueueSetViewport;
icculus@12219
  1146
    renderer->QueueSetDrawColor = GLES_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
icculus@12219
  1147
    renderer->QueueDrawPoints = GLES_QueueDrawPoints;
icculus@12219
  1148
    renderer->QueueDrawLines = GLES_QueueDrawPoints;  /* lines and points queue vertices the same way. */
icculus@12219
  1149
    renderer->QueueFillRects = GLES_QueueFillRects;
icculus@12219
  1150
    renderer->QueueCopy = GLES_QueueCopy;
icculus@12219
  1151
    renderer->QueueCopyEx = GLES_QueueCopyEx;
icculus@12219
  1152
    renderer->RunCommandQueue = GLES_RunCommandQueue;
icculus@12219
  1153
    renderer->RenderReadPixels = GLES_RenderReadPixels;
icculus@12219
  1154
    renderer->RenderPresent = GLES_RenderPresent;
icculus@12219
  1155
    renderer->DestroyTexture = GLES_DestroyTexture;
icculus@12219
  1156
    renderer->DestroyRenderer = GLES_DestroyRenderer;
icculus@12219
  1157
    renderer->GL_BindTexture = GLES_BindTexture;
icculus@12219
  1158
    renderer->GL_UnbindTexture = GLES_UnbindTexture;
icculus@12219
  1159
    renderer->info = GLES_RenderDriver.info;
icculus@12219
  1160
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
icculus@12219
  1161
    renderer->driverdata = data;
icculus@12219
  1162
    renderer->window = window;
icculus@12219
  1163
icculus@12219
  1164
    data->context = SDL_GL_CreateContext(window);
icculus@12219
  1165
    if (!data->context) {
icculus@12219
  1166
        GLES_DestroyRenderer(renderer);
icculus@12219
  1167
        goto error;
icculus@12219
  1168
    }
icculus@12219
  1169
    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
icculus@12219
  1170
        GLES_DestroyRenderer(renderer);
icculus@12219
  1171
        goto error;
icculus@12219
  1172
    }
icculus@12219
  1173
icculus@12219
  1174
    if (GLES_LoadFunctions(data) < 0) {
icculus@12219
  1175
        GLES_DestroyRenderer(renderer);
icculus@12219
  1176
        goto error;
icculus@12219
  1177
    }
icculus@12219
  1178
icculus@12219
  1179
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
icculus@12219
  1180
        SDL_GL_SetSwapInterval(1);
icculus@12219
  1181
    } else {
icculus@12219
  1182
        SDL_GL_SetSwapInterval(0);
icculus@12219
  1183
    }
icculus@12219
  1184
    if (SDL_GL_GetSwapInterval() > 0) {
icculus@12219
  1185
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
icculus@12219
  1186
    }
icculus@12219
  1187
icculus@12219
  1188
    value = 0;
icculus@12219
  1189
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
icculus@12219
  1190
    renderer->info.max_texture_width = value;
icculus@12219
  1191
    value = 0;
icculus@12219
  1192
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
icculus@12219
  1193
    renderer->info.max_texture_height = value;
icculus@12219
  1194
icculus@12219
  1195
    /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
icculus@12219
  1196
    if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
icculus@12219
  1197
        data->GL_OES_framebuffer_object_supported = SDL_TRUE;
icculus@12219
  1198
        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
icculus@12219
  1199
icculus@12219
  1200
        value = 0;
icculus@12219
  1201
        data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
icculus@12219
  1202
        data->window_framebuffer = (GLuint)value;
icculus@12219
  1203
    }
icculus@12219
  1204
    data->framebuffers = NULL;
icculus@12219
  1205
icculus@12219
  1206
    if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
icculus@12219
  1207
        data->GL_OES_blend_func_separate_supported = SDL_TRUE;
icculus@12219
  1208
    }
icculus@12219
  1209
    if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
icculus@12219
  1210
        data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
icculus@12219
  1211
    }
icculus@12219
  1212
    if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
icculus@12219
  1213
        data->GL_OES_blend_subtract_supported = SDL_TRUE;
icculus@12219
  1214
    }
icculus@12219
  1215
icculus@12219
  1216
    /* Set up parameters for rendering */
icculus@12219
  1217
    data->glDisable(GL_DEPTH_TEST);
icculus@12219
  1218
    data->glDisable(GL_CULL_FACE);
icculus@12219
  1219
icculus@12219
  1220
    data->glMatrixMode(GL_MODELVIEW);
icculus@12219
  1221
    data->glLoadIdentity();
icculus@12219
  1222
icculus@12219
  1223
    data->glEnableClientState(GL_VERTEX_ARRAY);
icculus@12219
  1224
    data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
icculus@12219
  1225
sylvain@12531
  1226
    data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
sylvain@12531
  1227
slouken@12417
  1228
    data->drawstate.blend = SDL_BLENDMODE_INVALID;
icculus@12263
  1229
    data->drawstate.color = 0xFFFFFFFF;
icculus@12263
  1230
    data->drawstate.clear_color = 0xFFFFFFFF;
icculus@12263
  1231
icculus@12219
  1232
    return renderer;
icculus@12219
  1233
icculus@12219
  1234
error:
icculus@12219
  1235
    if (changed_window) {
icculus@12219
  1236
        /* Uh oh, better try to put it back... */
icculus@12219
  1237
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
icculus@12219
  1238
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
icculus@12219
  1239
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
icculus@12219
  1240
        SDL_RecreateWindow(window, window_flags);
icculus@12219
  1241
    }
icculus@12219
  1242
    return NULL;
icculus@12219
  1243
}
icculus@12219
  1244
icculus@12219
  1245
SDL_RenderDriver GLES_RenderDriver = {
icculus@12219
  1246
    GLES_CreateRenderer,
icculus@12219
  1247
    {
icculus@12219
  1248
     "opengles",
icculus@12219
  1249
     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
icculus@12219
  1250
     1,
icculus@12219
  1251
     {SDL_PIXELFORMAT_ABGR8888},
icculus@12219
  1252
     0,
icculus@12418
  1253
     0
icculus@12418
  1254
    }
icculus@12219
  1255
};
icculus@12219
  1256
slouken@5226
  1257
#endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
hfutrell@2739
  1258
hfutrell@2739
  1259
/* vi: set ts=4 sw=4 expandtab: */