src/render/opengles/SDL_render_gles.c
author Ryan C. Gordon <icculus@icculus.org>
Mon, 04 Feb 2019 23:24:10 -0500
changeset 12593 307b9da13612
parent 12531 af47ff0de5ab
child 12621 6a60a1e87d10
permissions -rw-r--r--
opengles1: keep cached texturing state correct.
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
slouken@6246
   506
    if (texture == NULL) {
slouken@6271
   507
        data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
slouken@6246
   508
        return 0;
slouken@6246
   509
    }
slouken@6246
   510
slouken@6246
   511
    texturedata = (GLES_TextureData *) texture->driverdata;
slouken@6246
   512
    data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
slouken@6246
   513
    /* TODO: check if texture pixel format allows this operation */
slouken@6246
   514
    data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
slouken@6246
   515
    /* Check FBO status */
slouken@6246
   516
    status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
slouken@6246
   517
    if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
icculus@7037
   518
        return SDL_SetError("glFramebufferTexture2DOES() failed");
slouken@6246
   519
    }
slouken@6246
   520
    return 0;
slouken@6246
   521
}
slouken@6246
   522
icculus@12219
   523
slouken@6246
   524
static int
icculus@12219
   525
GLES_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
slouken@5224
   526
{
icculus@12219
   527
    return 0;  /* nothing to do in this backend. */
slouken@5224
   528
}
slouken@5224
   529
slouken@7141
   530
static int
icculus@12219
   531
GLES_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
slouken@7141
   532
{
icculus@12219
   533
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
icculus@12219
   534
    size_t i;
slouken@7141
   535
icculus@12219
   536
    if (!verts) {
icculus@12219
   537
        return -1;
gabomdq@7160
   538
    }
gabomdq@7160
   539
icculus@12219
   540
    cmd->data.draw.count = count;
icculus@12219
   541
    for (i = 0; i < count; i++) {
icculus@12219
   542
        *(verts++) = 0.5f + points[i].x;
icculus@12219
   543
        *(verts++) = 0.5f + points[i].y;
slouken@10408
   544
    }
slouken@10408
   545
slouken@5355
   546
    return 0;
slouken@5355
   547
}
slouken@5355
   548
hfutrell@2739
   549
static int
icculus@12219
   550
GLES_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
hfutrell@2739
   551
{
icculus@12219
   552
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
icculus@12219
   553
    size_t i;
slouken@2753
   554
icculus@12219
   555
    if (!verts) {
icculus@12219
   556
        return -1;
slouken@8993
   557
    }
slouken@8993
   558
icculus@12219
   559
    cmd->data.draw.count = count;
slouken@2936
   560
icculus@12219
   561
    for (i = 0; i < count; i++) {
slouken@6528
   562
        const SDL_FRect *rect = &rects[i];
icculus@12219
   563
        const GLfloat minx = rect->x;
icculus@12219
   564
        const GLfloat maxx = rect->x + rect->w;
icculus@12219
   565
        const GLfloat miny = rect->y;
icculus@12219
   566
        const GLfloat maxy = rect->y + rect->h;
icculus@12219
   567
        *(verts++) = minx;
icculus@12219
   568
        *(verts++) = miny;
icculus@12219
   569
        *(verts++) = maxx;
icculus@12219
   570
        *(verts++) = miny;
icculus@12219
   571
        *(verts++) = minx;
icculus@12219
   572
        *(verts++) = maxy;
icculus@12219
   573
        *(verts++) = maxx;
icculus@12219
   574
        *(verts++) = maxy;
slouken@3536
   575
    }
hfutrell@2949
   576
slouken@2753
   577
    return 0;
hfutrell@2739
   578
}
hfutrell@2739
   579
hfutrell@2739
   580
static int
icculus@12219
   581
GLES_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
icculus@12219
   582
                          const SDL_Rect * srcrect, const SDL_FRect * dstrect)
hfutrell@2739
   583
{
icculus@12235
   584
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
slouken@6528
   585
    GLfloat minx, miny, maxx, maxy;
hfutrell@2739
   586
    GLfloat minu, maxu, minv, maxv;
icculus@12219
   587
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
slouken@2753
   588
icculus@12219
   589
    if (!verts) {
icculus@12219
   590
        return -1;
hfutrell@2739
   591
    }
hfutrell@2739
   592
icculus@12219
   593
    cmd->data.draw.count = 1;
slouken@5355
   594
slouken@10399
   595
    minx = dstrect->x;
slouken@10399
   596
    miny = dstrect->y;
slouken@10399
   597
    maxx = dstrect->x + dstrect->w;
slouken@10399
   598
    maxy = dstrect->y + dstrect->h;
slouken@5154
   599
slouken@10399
   600
    minu = (GLfloat) srcrect->x / texture->w;
slouken@10399
   601
    minu *= texturedata->texw;
slouken@10399
   602
    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
slouken@10399
   603
    maxu *= texturedata->texw;
slouken@10399
   604
    minv = (GLfloat) srcrect->y / texture->h;
slouken@10399
   605
    minv *= texturedata->texh;
slouken@10399
   606
    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
slouken@10399
   607
    maxv *= texturedata->texh;
slouken@2753
   608
icculus@12219
   609
    *(verts++) = minx;
icculus@12219
   610
    *(verts++) = miny;
icculus@12219
   611
    *(verts++) = maxx;
icculus@12219
   612
    *(verts++) = miny;
icculus@12219
   613
    *(verts++) = minx;
icculus@12219
   614
    *(verts++) = maxy;
icculus@12219
   615
    *(verts++) = maxx;
icculus@12219
   616
    *(verts++) = maxy;
slouken@2753
   617
icculus@12219
   618
    *(verts++) = minu;
icculus@12219
   619
    *(verts++) = minv;
icculus@12219
   620
    *(verts++) = maxu;
icculus@12219
   621
    *(verts++) = minv;
icculus@12219
   622
    *(verts++) = minu;
icculus@12219
   623
    *(verts++) = maxv;
icculus@12219
   624
    *(verts++) = maxu;
icculus@12219
   625
    *(verts++) = maxv;
slouken@2753
   626
hfutrell@2739
   627
    return 0;
hfutrell@2739
   628
}
hfutrell@2739
   629
slouken@6043
   630
static int
icculus@12219
   631
GLES_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
icculus@12219
   632
                        const SDL_Rect * srcquad, const SDL_FRect * dstrect,
icculus@12219
   633
                        const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
slouken@6528
   634
{
icculus@12235
   635
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
icculus@12219
   636
    GLfloat minx, miny, maxx, maxy;
icculus@12219
   637
    GLfloat centerx, centery;
icculus@12219
   638
    GLfloat minu, maxu, minv, maxv;
icculus@12219
   639
    GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 19 * sizeof (GLfloat), 0, &cmd->data.draw.first);
slouken@6528
   640
icculus@12219
   641
    if (!verts) {
icculus@12219
   642
        return -1;
slouken@6528
   643
    }
slouken@6528
   644
slouken@6528
   645
    centerx = center->x;
slouken@6528
   646
    centery = center->y;
slouken@6528
   647
slouken@6528
   648
    if (flip & SDL_FLIP_HORIZONTAL) {
slouken@6528
   649
        minx =  dstrect->w - centerx;
slouken@6528
   650
        maxx = -centerx;
icculus@12219
   651
    }
icculus@12219
   652
    else {
slouken@6528
   653
        minx = -centerx;
icculus@12219
   654
        maxx =  dstrect->w - centerx;
slouken@6528
   655
    }
slouken@6528
   656
slouken@6528
   657
    if (flip & SDL_FLIP_VERTICAL) {
icculus@12219
   658
        miny =  dstrect->h - centery;
slouken@6528
   659
        maxy = -centery;
icculus@12219
   660
    }
icculus@12219
   661
    else {
slouken@6528
   662
        miny = -centery;
icculus@12219
   663
        maxy =  dstrect->h - centery;
slouken@6528
   664
    }
slouken@6528
   665
icculus@12235
   666
    minu = (GLfloat) srcquad->x / texture->w;
slouken@6528
   667
    minu *= texturedata->texw;
icculus@12235
   668
    maxu = (GLfloat) (srcquad->x + srcquad->w) / texture->w;
slouken@6528
   669
    maxu *= texturedata->texw;
icculus@12235
   670
    minv = (GLfloat) srcquad->y / texture->h;
slouken@6528
   671
    minv *= texturedata->texh;
icculus@12235
   672
    maxv = (GLfloat) (srcquad->y + srcquad->h) / texture->h;
slouken@6528
   673
    maxv *= texturedata->texh;
slouken@6528
   674
icculus@12219
   675
    cmd->data.draw.count = 1;
slouken@6528
   676
icculus@12219
   677
    *(verts++) = minx;
icculus@12219
   678
    *(verts++) = miny;
icculus@12219
   679
    *(verts++) = maxx;
icculus@12219
   680
    *(verts++) = miny;
icculus@12219
   681
    *(verts++) = minx;
icculus@12219
   682
    *(verts++) = maxy;
icculus@12219
   683
    *(verts++) = maxx;
icculus@12219
   684
    *(verts++) = maxy;
icculus@12219
   685
icculus@12219
   686
    *(verts++) = minu;
icculus@12219
   687
    *(verts++) = minv;
icculus@12219
   688
    *(verts++) = maxu;
icculus@12219
   689
    *(verts++) = minv;
icculus@12219
   690
    *(verts++) = minu;
icculus@12219
   691
    *(verts++) = maxv;
icculus@12219
   692
    *(verts++) = maxu;
icculus@12219
   693
    *(verts++) = maxv;
icculus@12219
   694
icculus@12219
   695
    *(verts++) = (GLfloat) dstrect->x + centerx;
icculus@12219
   696
    *(verts++) = (GLfloat) dstrect->y + centery;
icculus@12219
   697
    *(verts++) = (GLfloat) angle;
slouken@6528
   698
slouken@6528
   699
    return 0;
slouken@6528
   700
}
slouken@6528
   701
icculus@12219
   702
static void
icculus@12238
   703
SetDrawState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
icculus@12219
   704
{
icculus@12219
   705
    const SDL_BlendMode blend = cmd->data.draw.blend;
sylvain@12484
   706
    const Uint8 r = cmd->data.draw.r;
sylvain@12484
   707
    const Uint8 g = cmd->data.draw.g;
sylvain@12484
   708
    const Uint8 b = cmd->data.draw.b;
sylvain@12484
   709
    const Uint8 a = cmd->data.draw.a;
icculus@12282
   710
    const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
icculus@12282
   711
icculus@12282
   712
    if (color != data->drawstate.color) {
icculus@12282
   713
        const GLfloat fr = ((GLfloat) r) * inv255f;
icculus@12282
   714
        const GLfloat fg = ((GLfloat) g) * inv255f;
icculus@12282
   715
        const GLfloat fb = ((GLfloat) b) * inv255f;
icculus@12282
   716
        const GLfloat fa = ((GLfloat) a) * inv255f;
icculus@12282
   717
        data->glColor4f(fr, fg, fb, fa);
icculus@12282
   718
        data->drawstate.color = color;
icculus@12282
   719
    }
icculus@12282
   720
icculus@12282
   721
    if (data->drawstate.viewport_dirty) {
icculus@12282
   722
        const SDL_Rect *viewport = &data->drawstate.viewport;
icculus@12282
   723
        const SDL_bool istarget = (data->drawstate.target != NULL);
icculus@12282
   724
        data->glMatrixMode(GL_PROJECTION);
icculus@12282
   725
        data->glLoadIdentity();
icculus@12282
   726
        data->glViewport(viewport->x,
icculus@12282
   727
                         istarget ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
icculus@12282
   728
                         viewport->w, viewport->h);
icculus@12282
   729
        if (viewport->w && viewport->h) {
icculus@12282
   730
            data->glOrthof((GLfloat) 0, (GLfloat) viewport->w,
icculus@12418
   731
                           (GLfloat) (istarget ? 0 : viewport->h),
icculus@12418
   732
                           (GLfloat) (istarget ? viewport->h : 0),
icculus@12282
   733
                           0.0, 1.0);
icculus@12282
   734
        }
icculus@12282
   735
        data->glMatrixMode(GL_MODELVIEW);
icculus@12282
   736
        data->drawstate.viewport_dirty = SDL_FALSE;
icculus@12282
   737
    }
icculus@12282
   738
icculus@12282
   739
    if (data->drawstate.cliprect_enabled_dirty) {
icculus@12282
   740
        if (data->drawstate.cliprect_enabled) {
icculus@12282
   741
            data->glEnable(GL_SCISSOR_TEST);
icculus@12282
   742
        } else {
icculus@12282
   743
            data->glDisable(GL_SCISSOR_TEST);
icculus@12282
   744
        }
icculus@12282
   745
        data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
icculus@12282
   746
    }
icculus@12282
   747
icculus@12282
   748
    if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
icculus@12282
   749
        const SDL_Rect *viewport = &data->drawstate.viewport;
icculus@12282
   750
        const SDL_Rect *rect = &data->drawstate.cliprect;
icculus@12282
   751
        const SDL_bool istarget = (data->drawstate.target != NULL);
icculus@12282
   752
        data->glScissor(viewport->x + rect->x,
icculus@12282
   753
                        istarget ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
icculus@12282
   754
                        rect->w, rect->h);
icculus@12282
   755
        data->drawstate.cliprect_dirty = SDL_FALSE;
icculus@12282
   756
    }
icculus@12219
   757
icculus@12238
   758
    if (blend != data->drawstate.blend) {
icculus@12219
   759
        if (blend == SDL_BLENDMODE_NONE) {
icculus@12219
   760
            data->glDisable(GL_BLEND);
icculus@12219
   761
        } else {
icculus@12219
   762
            data->glEnable(GL_BLEND);
icculus@12219
   763
            if (data->GL_OES_blend_func_separate_supported) {
icculus@12219
   764
                data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
icculus@12219
   765
                                             GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
icculus@12219
   766
                                             GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
icculus@12219
   767
                                             GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
icculus@12219
   768
            } else {
icculus@12219
   769
                data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
icculus@12219
   770
                                  GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)));
icculus@12219
   771
            }
icculus@12219
   772
            if (data->GL_OES_blend_equation_separate_supported) {
icculus@12219
   773
                data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
icculus@12219
   774
                                                 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
icculus@12219
   775
            } else if (data->GL_OES_blend_subtract_supported) {
icculus@12219
   776
                data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)));
icculus@12219
   777
            }
icculus@12219
   778
        }
icculus@12238
   779
        data->drawstate.blend = blend;
icculus@12219
   780
    }
icculus@12219
   781
icculus@12238
   782
    if ((cmd->data.draw.texture != NULL) != data->drawstate.texturing) {
icculus@12219
   783
        if (cmd->data.draw.texture == NULL) {
icculus@12219
   784
            data->glDisable(GL_TEXTURE_2D);
icculus@12219
   785
            data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
icculus@12238
   786
            data->drawstate.texturing = SDL_FALSE;
icculus@12219
   787
        } else {
icculus@12219
   788
            data->glEnable(GL_TEXTURE_2D);
icculus@12219
   789
            data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
icculus@12238
   790
            data->drawstate.texturing = SDL_TRUE;
icculus@12219
   791
        }
icculus@12219
   792
    }
icculus@12219
   793
}
icculus@12219
   794
icculus@12219
   795
static void
icculus@12264
   796
SetCopyState(GLES_RenderData *data, const SDL_RenderCommand *cmd)
icculus@12219
   797
{
icculus@12219
   798
    SDL_Texture *texture = cmd->data.draw.texture;
icculus@12238
   799
    SetDrawState(data, cmd);
icculus@12219
   800
icculus@12238
   801
    if (texture != data->drawstate.texture) {
icculus@12235
   802
        GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
icculus@12235
   803
        data->glBindTexture(GL_TEXTURE_2D, texturedata->texture);
icculus@12238
   804
        data->drawstate.texture = texture;
icculus@12219
   805
    }
icculus@12219
   806
}
icculus@12219
   807
icculus@12219
   808
static int
icculus@12219
   809
GLES_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
icculus@12219
   810
{
icculus@12219
   811
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
icculus@12219
   812
    size_t i;
icculus@12219
   813
icculus@12219
   814
    if (GLES_ActivateRenderer(renderer) < 0) {
icculus@12219
   815
        return -1;
icculus@12219
   816
    }
icculus@12219
   817
icculus@12282
   818
    data->drawstate.target = renderer->target;
icculus@12282
   819
icculus@12282
   820
    if (!renderer->target) {
icculus@12282
   821
        SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
icculus@12219
   822
    }
icculus@12219
   823
icculus@12219
   824
    while (cmd) {
icculus@12219
   825
        switch (cmd->command) {
icculus@12219
   826
            case SDL_RENDERCMD_SETDRAWCOLOR: {
icculus@12282
   827
                break;  /* not used in this render backend. */
icculus@12219
   828
            }
icculus@12219
   829
icculus@12219
   830
            case SDL_RENDERCMD_SETVIEWPORT: {
icculus@12238
   831
                SDL_Rect *viewport = &data->drawstate.viewport;
icculus@12238
   832
                if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
icculus@12238
   833
                    SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
icculus@12282
   834
                    data->drawstate.viewport_dirty = SDL_TRUE;
icculus@12264
   835
                }
icculus@12219
   836
                break;
icculus@12219
   837
            }
icculus@12219
   838
icculus@12219
   839
            case SDL_RENDERCMD_SETCLIPRECT: {
icculus@12219
   840
                const SDL_Rect *rect = &cmd->data.cliprect.rect;
icculus@12238
   841
                if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
icculus@12238
   842
                    data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
icculus@12282
   843
                    data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
icculus@12282
   844
                }
icculus@12282
   845
                if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
icculus@12282
   846
                    SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
icculus@12282
   847
                    data->drawstate.cliprect_dirty = SDL_TRUE;
icculus@12219
   848
                }
icculus@12219
   849
                break;
icculus@12219
   850
            }
icculus@12219
   851
icculus@12219
   852
            case SDL_RENDERCMD_CLEAR: {
icculus@12238
   853
                const Uint8 r = cmd->data.color.r;
icculus@12238
   854
                const Uint8 g = cmd->data.color.g;
icculus@12238
   855
                const Uint8 b = cmd->data.color.b;
icculus@12238
   856
                const Uint8 a = cmd->data.color.a;
icculus@12238
   857
                const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
icculus@12238
   858
                if (color != data->drawstate.clear_color) {
icculus@12238
   859
                    const GLfloat fr = ((GLfloat) r) * inv255f;
icculus@12238
   860
                    const GLfloat fg = ((GLfloat) g) * inv255f;
icculus@12238
   861
                    const GLfloat fb = ((GLfloat) b) * inv255f;
icculus@12238
   862
                    const GLfloat fa = ((GLfloat) a) * inv255f;
icculus@12238
   863
                    data->glClearColor(fr, fg, fb, fa);
icculus@12238
   864
                    data->drawstate.clear_color = color;
icculus@12238
   865
                }
icculus@12219
   866
icculus@12264
   867
                if (data->drawstate.cliprect_enabled) {
icculus@12219
   868
                    data->glDisable(GL_SCISSOR_TEST);
icculus@12282
   869
                    data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
icculus@12219
   870
                }
icculus@12219
   871
icculus@12219
   872
                data->glClear(GL_COLOR_BUFFER_BIT);
icculus@12219
   873
icculus@12219
   874
                break;
icculus@12219
   875
            }
icculus@12219
   876
icculus@12219
   877
            case SDL_RENDERCMD_DRAW_POINTS: {
icculus@12219
   878
                const size_t count = cmd->data.draw.count;
icculus@12219
   879
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12238
   880
                SetDrawState(data, cmd);
icculus@12235
   881
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12418
   882
                data->glDrawArrays(GL_POINTS, 0, (GLsizei) count);
icculus@12219
   883
                break;
icculus@12219
   884
            }
icculus@12219
   885
icculus@12219
   886
            case SDL_RENDERCMD_DRAW_LINES: {
icculus@12219
   887
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12235
   888
                const size_t count = cmd->data.draw.count;
icculus@12238
   889
                SetDrawState(data, cmd);
icculus@12219
   890
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12235
   891
                if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
icculus@12219
   892
                    /* GL_LINE_LOOP takes care of the final segment */
icculus@12418
   893
                    data->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) (count - 1));
icculus@12219
   894
                } else {
icculus@12418
   895
                    data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
icculus@12219
   896
                    /* We need to close the endpoint of the line */
icculus@12418
   897
                    data->glDrawArrays(GL_POINTS, (GLsizei) (count - 1), 1);
icculus@12219
   898
                }
icculus@12219
   899
                break;
icculus@12219
   900
            }
icculus@12219
   901
icculus@12219
   902
            case SDL_RENDERCMD_FILL_RECTS: {
icculus@12219
   903
                const size_t count = cmd->data.draw.count;
icculus@12219
   904
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12418
   905
                GLsizei offset = 0;
icculus@12238
   906
                SetDrawState(data, cmd);
icculus@12219
   907
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12219
   908
                for (i = 0; i < count; ++i, offset += 4) {
icculus@12219
   909
                    data->glDrawArrays(GL_TRIANGLE_STRIP, offset, 4);
icculus@12219
   910
                }
icculus@12219
   911
                break;
icculus@12219
   912
            }
icculus@12219
   913
icculus@12219
   914
            case SDL_RENDERCMD_COPY: {
icculus@12219
   915
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12238
   916
                SetCopyState(data, cmd);
icculus@12219
   917
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12219
   918
                data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
icculus@12219
   919
                data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
icculus@12219
   920
                break;
icculus@12219
   921
            }
icculus@12219
   922
icculus@12219
   923
            case SDL_RENDERCMD_COPY_EX: {
icculus@12219
   924
                const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
icculus@12219
   925
                const GLfloat translatex = verts[16];
icculus@12219
   926
                const GLfloat translatey = verts[17];
icculus@12219
   927
                const GLfloat angle = verts[18];
icculus@12238
   928
                SetCopyState(data, cmd);
icculus@12219
   929
                data->glVertexPointer(2, GL_FLOAT, 0, verts);
icculus@12219
   930
                data->glTexCoordPointer(2, GL_FLOAT, 0, verts + 8);
icculus@12219
   931
icculus@12219
   932
                /* Translate to flip, rotate, translate to position */
icculus@12219
   933
                data->glPushMatrix();
icculus@12219
   934
                data->glTranslatef(translatex, translatey, 0.0f);
icculus@12219
   935
                data->glRotatef(angle, 0.0, 0.0, 1.0);
icculus@12219
   936
                data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
icculus@12219
   937
                data->glPopMatrix();
icculus@12219
   938
                break;
icculus@12219
   939
            }
icculus@12219
   940
icculus@12219
   941
            case SDL_RENDERCMD_NO_OP:
icculus@12219
   942
                break;
icculus@12219
   943
        }
icculus@12219
   944
icculus@12219
   945
        cmd = cmd->next;
icculus@12219
   946
    }
icculus@12219
   947
icculus@12235
   948
    return 0;
icculus@12219
   949
}
icculus@12219
   950
slouken@6528
   951
static int
slouken@6043
   952
GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
icculus@12264
   953
                      Uint32 pixel_format, void * pixels, int pitch)
slouken@6043
   954
{
slouken@6188
   955
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@10406
   956
    Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
slouken@6043
   957
    void *temp_pixels;
slouken@6043
   958
    int temp_pitch;
slouken@6043
   959
    Uint8 *src, *dst, *tmp;
slouken@6043
   960
    int w, h, length, rows;
slouken@6043
   961
    int status;
slouken@6043
   962
slouken@6043
   963
    GLES_ActivateRenderer(renderer);
slouken@6043
   964
slouken@6043
   965
    temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@6043
   966
    temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@6043
   967
    if (!temp_pixels) {
icculus@7037
   968
        return SDL_OutOfMemory();
slouken@6043
   969
    }
slouken@6043
   970
slouken@7420
   971
    SDL_GetRendererOutputSize(renderer, &w, &h);
slouken@6043
   972
slouken@6188
   973
    data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
slouken@6043
   974
slouken@10405
   975
    data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
slouken@10405
   976
                       rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
slouken@6043
   977
slouken@10405
   978
    /* Flip the rows to be top-down if necessary */
slouken@10405
   979
    if (!renderer->target) {
icculus@12349
   980
        SDL_bool isstack;
slouken@10405
   981
        length = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@10405
   982
        src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
slouken@10405
   983
        dst = (Uint8*)temp_pixels;
icculus@12349
   984
        tmp = SDL_small_alloc(Uint8, length, &isstack);
slouken@10405
   985
        rows = rect->h / 2;
slouken@10405
   986
        while (rows--) {
slouken@10405
   987
            SDL_memcpy(tmp, dst, length);
slouken@10405
   988
            SDL_memcpy(dst, src, length);
slouken@10405
   989
            SDL_memcpy(src, tmp, length);
slouken@10405
   990
            dst += temp_pitch;
slouken@10405
   991
            src -= temp_pitch;
slouken@10405
   992
        }
icculus@12349
   993
        SDL_small_free(tmp, isstack);
slouken@6043
   994
    }
slouken@6043
   995
slouken@6043
   996
    status = SDL_ConvertPixels(rect->w, rect->h,
slouken@6043
   997
                               temp_format, temp_pixels, temp_pitch,
slouken@6043
   998
                               pixel_format, pixels, pitch);
slouken@6043
   999
    SDL_free(temp_pixels);
slouken@6043
  1000
slouken@6043
  1001
    return status;
slouken@6043
  1002
}
slouken@6043
  1003
hfutrell@2739
  1004
static void
slouken@3139
  1005
GLES_RenderPresent(SDL_Renderer * renderer)
hfutrell@2739
  1006
{
slouken@5147
  1007
    GLES_ActivateRenderer(renderer);
slouken@5147
  1008
hfutrell@2739
  1009
    SDL_GL_SwapWindow(renderer->window);
hfutrell@2739
  1010
}
hfutrell@2739
  1011
hfutrell@2739
  1012
static void
hfutrell@2739
  1013
GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
  1014
{
slouken@6188
  1015
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
slouken@6188
  1016
hfutrell@2739
  1017
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
  1018
slouken@5147
  1019
    GLES_ActivateRenderer(renderer);
slouken@5147
  1020
sylvain@12485
  1021
    if (renderdata->drawstate.texture == texture) {
sylvain@12485
  1022
        renderdata->drawstate.texture = NULL;
sylvain@12485
  1023
    }
sylvain@12485
  1024
    if (renderdata->drawstate.target == texture) {
sylvain@12485
  1025
        renderdata->drawstate.target = NULL;
sylvain@12485
  1026
    }
sylvain@12485
  1027
hfutrell@2739
  1028
    if (!data) {
hfutrell@2739
  1029
        return;
hfutrell@2739
  1030
    }
hfutrell@2739
  1031
    if (data->texture) {
slouken@6188
  1032
        renderdata->glDeleteTextures(1, &data->texture);
hfutrell@2739
  1033
    }
slouken@7719
  1034
    SDL_free(data->pixels);
hfutrell@2739
  1035
    SDL_free(data);
hfutrell@2739
  1036
    texture->driverdata = NULL;
hfutrell@2739
  1037
}
hfutrell@2739
  1038
hfutrell@2739
  1039
static void
hfutrell@2739
  1040
GLES_DestroyRenderer(SDL_Renderer * renderer)
hfutrell@2739
  1041
{
hfutrell@2739
  1042
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
  1043
hfutrell@2739
  1044
    if (data) {
hfutrell@2739
  1045
        if (data->context) {
slouken@6232
  1046
            while (data->framebuffers) {
slouken@6232
  1047
               GLES_FBOList *nextnode = data->framebuffers->next;
slouken@6232
  1048
               data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
slouken@6232
  1049
               SDL_free(data->framebuffers);
slouken@6232
  1050
               data->framebuffers = nextnode;
slouken@6232
  1051
            }
hfutrell@2739
  1052
            SDL_GL_DeleteContext(data->context);
hfutrell@2739
  1053
        }
hfutrell@2739
  1054
        SDL_free(data);
hfutrell@2739
  1055
    }
hfutrell@2739
  1056
    SDL_free(renderer);
hfutrell@2739
  1057
}
hfutrell@2739
  1058
slouken@6954
  1059
static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
slouken@6954
  1060
{
gabomdq@6414
  1061
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
gabomdq@6414
  1062
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
gabomdq@6414
  1063
    GLES_ActivateRenderer(renderer);
gabomdq@6414
  1064
gabomdq@6414
  1065
    data->glEnable(GL_TEXTURE_2D);
gabomdq@6414
  1066
    data->glBindTexture(texturedata->type, texturedata->texture);
gabomdq@6414
  1067
icculus@12593
  1068
    data->drawstate.texture = texture;
icculus@12593
  1069
    data->drawstate.texturing = SDL_TRUE;
icculus@12593
  1070
slime73@9604
  1071
    if (texw) {
slime73@9604
  1072
        *texw = (float)texturedata->texw;
slime73@9604
  1073
    }
slime73@9604
  1074
    if (texh) {
slime73@9604
  1075
        *texh = (float)texturedata->texh;
slime73@9604
  1076
    }
gabomdq@6414
  1077
gabomdq@6414
  1078
    return 0;
gabomdq@6414
  1079
}
gabomdq@6414
  1080
slouken@6954
  1081
static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
slouken@6954
  1082
{
gabomdq@6414
  1083
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
gabomdq@6414
  1084
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
gabomdq@6414
  1085
    GLES_ActivateRenderer(renderer);
gabomdq@6414
  1086
    data->glDisable(texturedata->type);
gabomdq@6414
  1087
icculus@12593
  1088
    data->drawstate.texture = NULL;
icculus@12593
  1089
    data->drawstate.texturing = SDL_FALSE;
icculus@12593
  1090
gabomdq@6414
  1091
    return 0;
gabomdq@6414
  1092
}
gabomdq@6414
  1093
icculus@12418
  1094
static SDL_Renderer *
icculus@12219
  1095
GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
icculus@12219
  1096
{
icculus@12219
  1097
    SDL_Renderer *renderer;
icculus@12219
  1098
    GLES_RenderData *data;
icculus@12219
  1099
    GLint value;
icculus@12219
  1100
    Uint32 window_flags;
icculus@12219
  1101
    int profile_mask = 0, major = 0, minor = 0;
icculus@12219
  1102
    SDL_bool changed_window = SDL_FALSE;
icculus@12219
  1103
icculus@12219
  1104
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
icculus@12219
  1105
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
icculus@12219
  1106
    SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
icculus@12219
  1107
icculus@12219
  1108
    window_flags = SDL_GetWindowFlags(window);
icculus@12219
  1109
    if (!(window_flags & SDL_WINDOW_OPENGL) ||
icculus@12219
  1110
        profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
icculus@12219
  1111
icculus@12219
  1112
        changed_window = SDL_TRUE;
icculus@12219
  1113
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
icculus@12219
  1114
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
icculus@12219
  1115
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
icculus@12219
  1116
icculus@12219
  1117
        if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
icculus@12219
  1118
            goto error;
icculus@12219
  1119
        }
icculus@12219
  1120
    }
icculus@12219
  1121
icculus@12219
  1122
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
icculus@12219
  1123
    if (!renderer) {
icculus@12219
  1124
        SDL_OutOfMemory();
icculus@12219
  1125
        goto error;
icculus@12219
  1126
    }
icculus@12219
  1127
icculus@12219
  1128
    data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
icculus@12219
  1129
    if (!data) {
icculus@12219
  1130
        GLES_DestroyRenderer(renderer);
icculus@12219
  1131
        SDL_OutOfMemory();
icculus@12219
  1132
        goto error;
icculus@12219
  1133
    }
icculus@12219
  1134
icculus@12219
  1135
    renderer->WindowEvent = GLES_WindowEvent;
icculus@12219
  1136
    renderer->GetOutputSize = GLES_GetOutputSize;
icculus@12219
  1137
    renderer->SupportsBlendMode = GLES_SupportsBlendMode;
icculus@12219
  1138
    renderer->CreateTexture = GLES_CreateTexture;
icculus@12219
  1139
    renderer->UpdateTexture = GLES_UpdateTexture;
icculus@12219
  1140
    renderer->LockTexture = GLES_LockTexture;
icculus@12219
  1141
    renderer->UnlockTexture = GLES_UnlockTexture;
icculus@12219
  1142
    renderer->SetRenderTarget = GLES_SetRenderTarget;
icculus@12219
  1143
    renderer->QueueSetViewport = GLES_QueueSetViewport;
icculus@12219
  1144
    renderer->QueueSetDrawColor = GLES_QueueSetViewport;  /* SetViewport and SetDrawColor are (currently) no-ops. */
icculus@12219
  1145
    renderer->QueueDrawPoints = GLES_QueueDrawPoints;
icculus@12219
  1146
    renderer->QueueDrawLines = GLES_QueueDrawPoints;  /* lines and points queue vertices the same way. */
icculus@12219
  1147
    renderer->QueueFillRects = GLES_QueueFillRects;
icculus@12219
  1148
    renderer->QueueCopy = GLES_QueueCopy;
icculus@12219
  1149
    renderer->QueueCopyEx = GLES_QueueCopyEx;
icculus@12219
  1150
    renderer->RunCommandQueue = GLES_RunCommandQueue;
icculus@12219
  1151
    renderer->RenderReadPixels = GLES_RenderReadPixels;
icculus@12219
  1152
    renderer->RenderPresent = GLES_RenderPresent;
icculus@12219
  1153
    renderer->DestroyTexture = GLES_DestroyTexture;
icculus@12219
  1154
    renderer->DestroyRenderer = GLES_DestroyRenderer;
icculus@12219
  1155
    renderer->GL_BindTexture = GLES_BindTexture;
icculus@12219
  1156
    renderer->GL_UnbindTexture = GLES_UnbindTexture;
icculus@12219
  1157
    renderer->info = GLES_RenderDriver.info;
icculus@12219
  1158
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
icculus@12219
  1159
    renderer->driverdata = data;
icculus@12219
  1160
    renderer->window = window;
icculus@12219
  1161
icculus@12219
  1162
    data->context = SDL_GL_CreateContext(window);
icculus@12219
  1163
    if (!data->context) {
icculus@12219
  1164
        GLES_DestroyRenderer(renderer);
icculus@12219
  1165
        goto error;
icculus@12219
  1166
    }
icculus@12219
  1167
    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
icculus@12219
  1168
        GLES_DestroyRenderer(renderer);
icculus@12219
  1169
        goto error;
icculus@12219
  1170
    }
icculus@12219
  1171
icculus@12219
  1172
    if (GLES_LoadFunctions(data) < 0) {
icculus@12219
  1173
        GLES_DestroyRenderer(renderer);
icculus@12219
  1174
        goto error;
icculus@12219
  1175
    }
icculus@12219
  1176
icculus@12219
  1177
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
icculus@12219
  1178
        SDL_GL_SetSwapInterval(1);
icculus@12219
  1179
    } else {
icculus@12219
  1180
        SDL_GL_SetSwapInterval(0);
icculus@12219
  1181
    }
icculus@12219
  1182
    if (SDL_GL_GetSwapInterval() > 0) {
icculus@12219
  1183
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
icculus@12219
  1184
    }
icculus@12219
  1185
icculus@12219
  1186
    value = 0;
icculus@12219
  1187
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
icculus@12219
  1188
    renderer->info.max_texture_width = value;
icculus@12219
  1189
    value = 0;
icculus@12219
  1190
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
icculus@12219
  1191
    renderer->info.max_texture_height = value;
icculus@12219
  1192
icculus@12219
  1193
    /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */
icculus@12219
  1194
    if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) {
icculus@12219
  1195
        data->GL_OES_framebuffer_object_supported = SDL_TRUE;
icculus@12219
  1196
        renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE;
icculus@12219
  1197
icculus@12219
  1198
        value = 0;
icculus@12219
  1199
        data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
icculus@12219
  1200
        data->window_framebuffer = (GLuint)value;
icculus@12219
  1201
    }
icculus@12219
  1202
    data->framebuffers = NULL;
icculus@12219
  1203
icculus@12219
  1204
    if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) {
icculus@12219
  1205
        data->GL_OES_blend_func_separate_supported = SDL_TRUE;
icculus@12219
  1206
    }
icculus@12219
  1207
    if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) {
icculus@12219
  1208
        data->GL_OES_blend_equation_separate_supported = SDL_TRUE;
icculus@12219
  1209
    }
icculus@12219
  1210
    if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) {
icculus@12219
  1211
        data->GL_OES_blend_subtract_supported = SDL_TRUE;
icculus@12219
  1212
    }
icculus@12219
  1213
icculus@12219
  1214
    /* Set up parameters for rendering */
icculus@12219
  1215
    data->glDisable(GL_DEPTH_TEST);
icculus@12219
  1216
    data->glDisable(GL_CULL_FACE);
icculus@12219
  1217
icculus@12219
  1218
    data->glMatrixMode(GL_MODELVIEW);
icculus@12219
  1219
    data->glLoadIdentity();
icculus@12219
  1220
icculus@12219
  1221
    data->glEnableClientState(GL_VERTEX_ARRAY);
icculus@12219
  1222
    data->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
icculus@12219
  1223
sylvain@12531
  1224
    data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
sylvain@12531
  1225
slouken@12417
  1226
    data->drawstate.blend = SDL_BLENDMODE_INVALID;
icculus@12263
  1227
    data->drawstate.color = 0xFFFFFFFF;
icculus@12263
  1228
    data->drawstate.clear_color = 0xFFFFFFFF;
icculus@12263
  1229
icculus@12219
  1230
    return renderer;
icculus@12219
  1231
icculus@12219
  1232
error:
icculus@12219
  1233
    if (changed_window) {
icculus@12219
  1234
        /* Uh oh, better try to put it back... */
icculus@12219
  1235
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
icculus@12219
  1236
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
icculus@12219
  1237
        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
icculus@12219
  1238
        SDL_RecreateWindow(window, window_flags);
icculus@12219
  1239
    }
icculus@12219
  1240
    return NULL;
icculus@12219
  1241
}
icculus@12219
  1242
icculus@12219
  1243
SDL_RenderDriver GLES_RenderDriver = {
icculus@12219
  1244
    GLES_CreateRenderer,
icculus@12219
  1245
    {
icculus@12219
  1246
     "opengles",
icculus@12219
  1247
     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
icculus@12219
  1248
     1,
icculus@12219
  1249
     {SDL_PIXELFORMAT_ABGR8888},
icculus@12219
  1250
     0,
icculus@12418
  1251
     0
icculus@12418
  1252
    }
icculus@12219
  1253
};
icculus@12219
  1254
slouken@5226
  1255
#endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */
hfutrell@2739
  1256
hfutrell@2739
  1257
/* vi: set ts=4 sw=4 expandtab: */