src/render/opengles/SDL_render_gles.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 20 Oct 2013 21:56:15 -0700
changeset 7860 2b0bcdea3a79
parent 7723 aea98cc3e696
child 8093 b43765095a6f
permissions -rw-r--r--
Fixed bug 2129 - fix for bug 2121 breaks linking for mingw and throws multiple warnings

Andreas Ertelt

The problem in question is caused by changeset 7771 (http://hg.libsdl.org/SDL/rev/4434498bf4b9 / https://bugzilla.libsdl.org/show_bug.cgi?id=2121)

The redefinition of __inline__ (introduced by the addition of begin_code.h:128's "|| __STRICT_ANSI__") results in mingw's gcc throwing multiple

warning: always_inline function might not be inlinable [-Wattributes]

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