src/video/SDL_renderer_gles.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 19 Jan 2011 23:56:16 -0800
changeset 5053 b5b42be9333c
parent 5052 4cb4b18cbae3
child 5138 da10636e5eca
permissions -rw-r--r--
Fixed bug #1026

Vittorio Giovara 2010-07-16 19:09:28 PDT

i was reading SDL_renderer_gles and i noticed that every time we there
is some gl call the gl state is modified with a couple of
glEnableClientState()/glDisableClientState.
While this is completely fine for desktops systems, this is a major
performace kill on mobile devices, right where opengles is
implemented.
Normal practice in this case is to update the glstate once, keep it
always the same and disable/enable other states only in very special
occasions.

On the web there's plenty of documentation (on the top of my head
http://developer.apple.com/iphone/library/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/Performance/Performance.html#//apple_ref/doc/uid/TP40008793-CH105-SW5
) and i personally tried this.
I modified my code and got a 10 fps boost, then modified SDL_render_gles and
shifted from 40 fps to 50 fps alone -- considering that i started from ~30fps i
got an 80% performance increase with this technique.

I have attached a dif of my changes, hope that it will be included in
mainstream.
hfutrell@2739
     1
/*
hfutrell@2739
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 Sam Lantinga
hfutrell@2739
     4
hfutrell@2739
     5
    This library is free software; you can redistribute it and/or
hfutrell@2739
     6
    modify it under the terms of the GNU Lesser General Public
hfutrell@2739
     7
    License as published by the Free Software Foundation; either
hfutrell@2739
     8
    version 2.1 of the License, or (at your option) any later version.
hfutrell@2739
     9
hfutrell@2739
    10
    This library is distributed in the hope that it will be useful,
hfutrell@2739
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
hfutrell@2739
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
hfutrell@2739
    13
    Lesser General Public License for more details.
hfutrell@2739
    14
hfutrell@2739
    15
    You should have received a copy of the GNU Lesser General Public
hfutrell@2739
    16
    License along with this library; if not, write to the Free Software
hfutrell@2739
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
hfutrell@2739
    18
hfutrell@2739
    19
    Sam Lantinga
hfutrell@2739
    20
    slouken@libsdl.org
hfutrell@2739
    21
*/
hfutrell@2739
    22
#include "SDL_config.h"
hfutrell@2739
    23
hfutrell@2739
    24
#if SDL_VIDEO_RENDER_OGL_ES
hfutrell@2739
    25
hfutrell@2739
    26
#include "SDL_video.h"
hfutrell@2739
    27
#include "SDL_opengles.h"
hfutrell@2739
    28
#include "SDL_sysvideo.h"
hfutrell@2739
    29
#include "SDL_pixels_c.h"
hfutrell@2739
    30
#include "SDL_rect_c.h"
hfutrell@2739
    31
#include "SDL_yuv_sw_c.h"
hfutrell@2739
    32
lestat@3165
    33
#if defined(__QNXNTO__)
lestat@3165
    34
/* Include QNX system header to check QNX version later */
lestat@3165
    35
#include <sys/neutrino.h>
lestat@3165
    36
#endif /* __QNXNTO__ */
slouken@3099
    37
lestat@3165
    38
#if defined(SDL_VIDEO_DRIVER_QNXGF)  ||  \
lestat@3165
    39
    defined(SDL_VIDEO_DRIVER_PHOTON) ||  \
lestat@3165
    40
    defined(SDL_VIDEO_DRIVER_PANDORA)
lestat@3165
    41
lestat@3165
    42
/* Empty function stub to get OpenGL ES 1.x support without  */
lestat@3165
    43
/* OpenGL ES extension GL_OES_draw_texture supported         */
slouken@3139
    44
GL_API void GL_APIENTRY
slouken@3139
    45
glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height)
slouken@3099
    46
{
slouken@3139
    47
    return;
slouken@3099
    48
}
slouken@3099
    49
lestat@3165
    50
#endif /* QNXGF || PHOTON || PANDORA */
slouken@3161
    51
hfutrell@2739
    52
/* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */
hfutrell@2739
    53
hfutrell@2739
    54
static const float inv255f = 1.0f / 255.0f;
hfutrell@2739
    55
hfutrell@2739
    56
static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags);
hfutrell@2739
    57
static int GLES_ActivateRenderer(SDL_Renderer * renderer);
hfutrell@2739
    58
static int GLES_DisplayModeChanged(SDL_Renderer * renderer);
hfutrell@2739
    59
static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
hfutrell@2739
    60
static int GLES_QueryTexturePixels(SDL_Renderer * renderer,
slouken@2753
    61
                                   SDL_Texture * texture, void **pixels,
slouken@2753
    62
                                   int *pitch);
hfutrell@2739
    63
static int GLES_SetTexturePalette(SDL_Renderer * renderer,
slouken@2753
    64
                                  SDL_Texture * texture,
slouken@2753
    65
                                  const SDL_Color * colors, int firstcolor,
slouken@2753
    66
                                  int ncolors);
hfutrell@2739
    67
static int GLES_GetTexturePalette(SDL_Renderer * renderer,
slouken@2753
    68
                                  SDL_Texture * texture, SDL_Color * colors,
slouken@2753
    69
                                  int firstcolor, int ncolors);
hfutrell@2739
    70
static int GLES_SetTextureColorMod(SDL_Renderer * renderer,
slouken@2753
    71
                                   SDL_Texture * texture);
hfutrell@2739
    72
static int GLES_SetTextureAlphaMod(SDL_Renderer * renderer,
slouken@2753
    73
                                   SDL_Texture * texture);
hfutrell@2739
    74
static int GLES_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@2753
    75
                                    SDL_Texture * texture);
hfutrell@2739
    76
static int GLES_SetTextureScaleMode(SDL_Renderer * renderer,
slouken@2753
    77
                                    SDL_Texture * texture);
hfutrell@2739
    78
static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
    79
                              const SDL_Rect * rect, const void *pixels,
slouken@2753
    80
                              int pitch);
hfutrell@2739
    81
static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
    82
                            const SDL_Rect * rect, int markDirty,
slouken@2753
    83
                            void **pixels, int *pitch);
slouken@2753
    84
static void GLES_UnlockTexture(SDL_Renderer * renderer,
slouken@2753
    85
                               SDL_Texture * texture);
hfutrell@2739
    86
static void GLES_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
    87
                              int numrects, const SDL_Rect * rects);
slouken@3641
    88
static int GLES_RenderDrawPoints(SDL_Renderer * renderer,
slouken@3641
    89
                                 const SDL_Point * points, int count);
slouken@3641
    90
static int GLES_RenderDrawLines(SDL_Renderer * renderer,
slouken@3641
    91
                                const SDL_Point * points, int count);
slouken@3641
    92
static int GLES_RenderDrawRects(SDL_Renderer * renderer,
slouken@3641
    93
                                const SDL_Rect ** rects, int count);
slouken@3641
    94
static int GLES_RenderFillRects(SDL_Renderer * renderer,
slouken@3641
    95
                                const SDL_Rect ** rects, int count);
hfutrell@2739
    96
static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
    97
                           const SDL_Rect * srcrect,
slouken@2753
    98
                           const SDL_Rect * dstrect);
hfutrell@2739
    99
static void GLES_RenderPresent(SDL_Renderer * renderer);
slouken@2753
   100
static void GLES_DestroyTexture(SDL_Renderer * renderer,
slouken@2753
   101
                                SDL_Texture * texture);
hfutrell@2739
   102
static void GLES_DestroyRenderer(SDL_Renderer * renderer);
hfutrell@2739
   103
hfutrell@2739
   104
hfutrell@2739
   105
SDL_RenderDriver GL_ES_RenderDriver = {
hfutrell@2739
   106
    GLES_CreateRenderer,
hfutrell@2739
   107
    {
hfutrell@2739
   108
     "opengl_es",
hfutrell@2739
   109
     (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD |
hfutrell@2739
   110
      SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
hfutrell@2739
   111
     (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
hfutrell@2739
   112
      SDL_TEXTUREMODULATE_ALPHA),
slouken@2884
   113
     (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
slouken@2884
   114
      SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
slouken@4986
   115
     (SDL_SCALEMODE_NONE | SDL_SCALEMODE_FAST | SDL_SCALEMODE_SLOW), 6,
slouken@2753
   116
     {
lestat@3122
   117
      /* OpenGL ES 1.x supported formats list */
slouken@4985
   118
      SDL_PIXELFORMAT_RGBA4444,
slouken@4985
   119
      SDL_PIXELFORMAT_RGBA5551,
slouken@4985
   120
      SDL_PIXELFORMAT_RGB565,
slouken@4963
   121
      SDL_PIXELFORMAT_RGB24,
slouken@4963
   122
      SDL_PIXELFORMAT_BGR888,
slouken@3139
   123
      SDL_PIXELFORMAT_ABGR8888},
slouken@2753
   124
     0,
hfutrell@2739
   125
     0}
hfutrell@2739
   126
};
hfutrell@2739
   127
hfutrell@2739
   128
typedef struct
hfutrell@2739
   129
{
hfutrell@2739
   130
    SDL_GLContext context;
hfutrell@2739
   131
    SDL_bool updateSize;
hfutrell@2739
   132
    int blendMode;
slouken@2753
   133
hfutrell@2739
   134
#ifndef APIENTRY
hfutrell@2739
   135
#define APIENTRY
hfutrell@2739
   136
#endif
slouken@2753
   137
slouken@2753
   138
    SDL_bool useDrawTexture;
slouken@2753
   139
    SDL_bool GL_OES_draw_texture_supported;
slouken@2753
   140
slouken@2753
   141
    /* OpenGL ES functions */
slouken@2753
   142
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
slouken@2753
   143
#include "SDL_glesfuncs.h"
slouken@2753
   144
#undef SDL_PROC
hfutrell@2739
   145
hfutrell@2739
   146
} GLES_RenderData;
hfutrell@2739
   147
hfutrell@2739
   148
typedef struct
hfutrell@2739
   149
{
hfutrell@2739
   150
    GLuint texture;
hfutrell@2739
   151
    GLenum type;
hfutrell@2739
   152
    GLfloat texw;
hfutrell@2739
   153
    GLfloat texh;
hfutrell@2739
   154
    GLenum format;
hfutrell@2739
   155
    GLenum formattype;
hfutrell@2739
   156
    void *pixels;
hfutrell@2739
   157
    int pitch;
hfutrell@2739
   158
    SDL_DirtyRectList dirty;
hfutrell@2739
   159
} GLES_TextureData;
hfutrell@2739
   160
hfutrell@2739
   161
static void
hfutrell@2739
   162
GLES_SetError(const char *prefix, GLenum result)
hfutrell@2739
   163
{
hfutrell@2739
   164
    const char *error;
hfutrell@2739
   165
hfutrell@2739
   166
    switch (result) {
hfutrell@2739
   167
    case GL_NO_ERROR:
hfutrell@2739
   168
        error = "GL_NO_ERROR";
hfutrell@2739
   169
        break;
hfutrell@2739
   170
    case GL_INVALID_ENUM:
hfutrell@2739
   171
        error = "GL_INVALID_ENUM";
hfutrell@2739
   172
        break;
hfutrell@2739
   173
    case GL_INVALID_VALUE:
hfutrell@2739
   174
        error = "GL_INVALID_VALUE";
hfutrell@2739
   175
        break;
hfutrell@2739
   176
    case GL_INVALID_OPERATION:
hfutrell@2739
   177
        error = "GL_INVALID_OPERATION";
hfutrell@2739
   178
        break;
hfutrell@2739
   179
    case GL_STACK_OVERFLOW:
hfutrell@2739
   180
        error = "GL_STACK_OVERFLOW";
hfutrell@2739
   181
        break;
hfutrell@2739
   182
    case GL_STACK_UNDERFLOW:
hfutrell@2739
   183
        error = "GL_STACK_UNDERFLOW";
hfutrell@2739
   184
        break;
hfutrell@2739
   185
    case GL_OUT_OF_MEMORY:
hfutrell@2739
   186
        error = "GL_OUT_OF_MEMORY";
hfutrell@2739
   187
        break;
hfutrell@2739
   188
    default:
hfutrell@2739
   189
        error = "UNKNOWN";
hfutrell@2739
   190
        break;
hfutrell@2739
   191
    }
hfutrell@2739
   192
    SDL_SetError("%s: %s", prefix, error);
hfutrell@2739
   193
}
hfutrell@2739
   194
hfutrell@2739
   195
static int
hfutrell@2739
   196
GLES_LoadFunctions(GLES_RenderData * data)
hfutrell@2739
   197
{
slouken@2753
   198
slouken@2753
   199
#define SDL_PROC(ret,func,params) \
lestat@3122
   200
    data->func = func;
slouken@2753
   201
#include "SDL_glesfuncs.h"
slouken@2753
   202
#undef SDL_PROC
slouken@2753
   203
hfutrell@2739
   204
    return 0;
hfutrell@2739
   205
}
hfutrell@2739
   206
hfutrell@2739
   207
SDL_Renderer *
hfutrell@2739
   208
GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
hfutrell@2739
   209
{
slouken@2753
   210
hfutrell@2739
   211
    SDL_Renderer *renderer;
hfutrell@2739
   212
    GLES_RenderData *data;
hfutrell@2739
   213
    GLint value;
hfutrell@2739
   214
    int doublebuffer;
hfutrell@2739
   215
hfutrell@2739
   216
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
hfutrell@2739
   217
        if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) {
hfutrell@2739
   218
            return NULL;
hfutrell@2739
   219
        }
hfutrell@2739
   220
    }
hfutrell@2739
   221
hfutrell@2739
   222
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
hfutrell@2739
   223
    if (!renderer) {
hfutrell@2739
   224
        SDL_OutOfMemory();
hfutrell@2739
   225
        return NULL;
hfutrell@2739
   226
    }
hfutrell@2739
   227
hfutrell@2739
   228
    data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data));
hfutrell@2739
   229
    if (!data) {
hfutrell@2739
   230
        GLES_DestroyRenderer(renderer);
hfutrell@2739
   231
        SDL_OutOfMemory();
hfutrell@2739
   232
        return NULL;
hfutrell@2739
   233
    }
hfutrell@2739
   234
hfutrell@2739
   235
    renderer->ActivateRenderer = GLES_ActivateRenderer;
hfutrell@2739
   236
    renderer->DisplayModeChanged = GLES_DisplayModeChanged;
hfutrell@2739
   237
    renderer->CreateTexture = GLES_CreateTexture;
hfutrell@2739
   238
    renderer->QueryTexturePixels = GLES_QueryTexturePixels;
hfutrell@2739
   239
    renderer->SetTexturePalette = GLES_SetTexturePalette;
hfutrell@2739
   240
    renderer->GetTexturePalette = GLES_GetTexturePalette;
hfutrell@2739
   241
    renderer->SetTextureColorMod = GLES_SetTextureColorMod;
hfutrell@2739
   242
    renderer->SetTextureAlphaMod = GLES_SetTextureAlphaMod;
hfutrell@2739
   243
    renderer->SetTextureBlendMode = GLES_SetTextureBlendMode;
hfutrell@2739
   244
    renderer->SetTextureScaleMode = GLES_SetTextureScaleMode;
hfutrell@2739
   245
    renderer->UpdateTexture = GLES_UpdateTexture;
hfutrell@2739
   246
    renderer->LockTexture = GLES_LockTexture;
hfutrell@2739
   247
    renderer->UnlockTexture = GLES_UnlockTexture;
hfutrell@2739
   248
    renderer->DirtyTexture = GLES_DirtyTexture;
slouken@3641
   249
    renderer->RenderDrawPoints = GLES_RenderDrawPoints;
slouken@3641
   250
    renderer->RenderDrawLines = GLES_RenderDrawLines;
slouken@3641
   251
    renderer->RenderDrawRects = GLES_RenderDrawRects;
slouken@3641
   252
    renderer->RenderFillRects = GLES_RenderFillRects;
hfutrell@2739
   253
    renderer->RenderCopy = GLES_RenderCopy;
hfutrell@2739
   254
    renderer->RenderPresent = GLES_RenderPresent;
hfutrell@2739
   255
    renderer->DestroyTexture = GLES_DestroyTexture;
hfutrell@2739
   256
    renderer->DestroyRenderer = GLES_DestroyRenderer;
hfutrell@2739
   257
    renderer->info = GL_ES_RenderDriver.info;
slouken@3688
   258
    renderer->window = window;
hfutrell@2739
   259
    renderer->driverdata = data;
slouken@2753
   260
slouken@2753
   261
    renderer->info.flags =
slouken@2753
   262
        (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED);
hfutrell@2739
   263
lestat@3165
   264
#if defined(__QNXNTO__)
lestat@3165
   265
#if _NTO_VERSION<=641
lestat@3165
   266
    /* QNX's OpenGL ES implementation is broken regarding             */
lestat@3165
   267
    /* packed textures support, affected versions 6.3.2, 6.4.0, 6.4.1 */
slouken@3169
   268
    renderer->info.num_texture_formats = 2;
slouken@3169
   269
    renderer->info.texture_formats[0] = SDL_PIXELFORMAT_ABGR8888;
slouken@3169
   270
    renderer->info.texture_formats[1] = SDL_PIXELFORMAT_BGR24;
lestat@3165
   271
#endif /* _NTO_VERSION */
lestat@3165
   272
#endif /* __QNXNTO__ */
lestat@3165
   273
hfutrell@2739
   274
    if (GLES_LoadFunctions(data) < 0) {
hfutrell@2739
   275
        GLES_DestroyRenderer(renderer);
hfutrell@2739
   276
        return NULL;
hfutrell@2739
   277
    }
hfutrell@2739
   278
slouken@3688
   279
    data->context = SDL_GL_CreateContext(window);
hfutrell@2739
   280
    if (!data->context) {
hfutrell@2739
   281
        GLES_DestroyRenderer(renderer);
hfutrell@2739
   282
        return NULL;
hfutrell@2739
   283
    }
slouken@3688
   284
    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
hfutrell@2739
   285
        GLES_DestroyRenderer(renderer);
hfutrell@2739
   286
        return NULL;
hfutrell@2739
   287
    }
hfutrell@2739
   288
hfutrell@2739
   289
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
hfutrell@2739
   290
        SDL_GL_SetSwapInterval(1);
hfutrell@2739
   291
    } else {
hfutrell@2739
   292
        SDL_GL_SetSwapInterval(0);
hfutrell@2739
   293
    }
hfutrell@2739
   294
    if (SDL_GL_GetSwapInterval() > 0) {
hfutrell@2739
   295
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
hfutrell@2739
   296
    }
hfutrell@2739
   297
hfutrell@2739
   298
    if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) {
hfutrell@2739
   299
        if (!doublebuffer) {
hfutrell@2739
   300
            renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
hfutrell@2739
   301
        }
hfutrell@2739
   302
    }
slouken@3161
   303
#if SDL_VIDEO_DRIVER_PANDORA
slouken@3161
   304
    data->GL_OES_draw_texture_supported = SDL_FALSE;
slouken@3161
   305
    data->useDrawTexture = SDL_FALSE;
slouken@3161
   306
#else
slouken@2753
   307
    if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) {
slouken@2753
   308
        data->GL_OES_draw_texture_supported = SDL_TRUE;
slouken@2753
   309
        data->useDrawTexture = SDL_TRUE;
slouken@2753
   310
    } else {
slouken@2753
   311
        data->GL_OES_draw_texture_supported = SDL_FALSE;
slouken@2753
   312
        data->useDrawTexture = SDL_FALSE;
slouken@2753
   313
    }
slouken@3161
   314
#endif
hfutrell@2739
   315
hfutrell@2739
   316
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
hfutrell@2739
   317
    renderer->info.max_texture_width = value;
hfutrell@2739
   318
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
hfutrell@2739
   319
    renderer->info.max_texture_height = value;
hfutrell@2739
   320
hfutrell@2739
   321
    /* Set up parameters for rendering */
hfutrell@2739
   322
    data->blendMode = -1;
hfutrell@2739
   323
    data->glDisable(GL_DEPTH_TEST);
hfutrell@2739
   324
    data->glDisable(GL_CULL_FACE);
hfutrell@2739
   325
    data->updateSize = SDL_TRUE;
hfutrell@2739
   326
slouken@5053
   327
    data->glEnableClientState(GL_VERTEX_ARRAY);
slouken@5053
   328
    data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
slouken@5053
   329
    
hfutrell@2739
   330
    return renderer;
hfutrell@2739
   331
}
hfutrell@2739
   332
slouken@2753
   333
static int
slouken@2753
   334
GLES_ActivateRenderer(SDL_Renderer * renderer)
hfutrell@2739
   335
{
slouken@2753
   336
slouken@2753
   337
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@3685
   338
    SDL_Window *window = renderer->window;
slouken@2753
   339
slouken@3688
   340
    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
hfutrell@2739
   341
        return -1;
hfutrell@2739
   342
    }
hfutrell@2739
   343
    if (data->updateSize) {
hfutrell@2739
   344
        data->glMatrixMode(GL_PROJECTION);
hfutrell@2739
   345
        data->glLoadIdentity();
hfutrell@2739
   346
        data->glMatrixMode(GL_MODELVIEW);
hfutrell@2739
   347
        data->glLoadIdentity();
hfutrell@2739
   348
        data->glViewport(0, 0, window->w, window->h);
slouken@2753
   349
        data->glOrthof(0.0, (GLfloat) window->w, (GLfloat) window->h, 0.0,
slouken@2753
   350
                       0.0, 1.0);
hfutrell@2739
   351
        data->updateSize = SDL_FALSE;
hfutrell@2739
   352
    }
hfutrell@2739
   353
    return 0;
hfutrell@2739
   354
}
hfutrell@2739
   355
hfutrell@2739
   356
static int
hfutrell@2739
   357
GLES_DisplayModeChanged(SDL_Renderer * renderer)
hfutrell@2739
   358
{
hfutrell@2739
   359
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   360
hfutrell@2739
   361
    data->updateSize = SDL_TRUE;
hfutrell@2739
   362
    return 0;
hfutrell@2739
   363
}
hfutrell@2739
   364
hfutrell@2739
   365
static __inline__ int
hfutrell@2739
   366
power_of_2(int input)
hfutrell@2739
   367
{
hfutrell@2739
   368
    int value = 1;
hfutrell@2739
   369
hfutrell@2739
   370
    while (value < input) {
hfutrell@2739
   371
        value <<= 1;
hfutrell@2739
   372
    }
hfutrell@2739
   373
    return value;
hfutrell@2739
   374
}
hfutrell@2739
   375
hfutrell@2739
   376
static int
slouken@3139
   377
GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   378
{
hfutrell@2739
   379
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   380
    GLES_TextureData *data;
hfutrell@2739
   381
    GLint internalFormat;
hfutrell@2739
   382
    GLenum format, type;
hfutrell@2739
   383
    int texture_w, texture_h;
hfutrell@2739
   384
    GLenum result;
slouken@3099
   385
slouken@2753
   386
    switch (texture->format) {
slouken@4963
   387
    case SDL_PIXELFORMAT_RGB24:
slouken@3139
   388
        internalFormat = GL_RGB;
slouken@3139
   389
        format = GL_RGB;
slouken@3139
   390
        type = GL_UNSIGNED_BYTE;
slouken@3139
   391
        break;
slouken@4963
   392
    case SDL_PIXELFORMAT_BGR888:
slouken@2753
   393
    case SDL_PIXELFORMAT_ABGR8888:
slouken@3139
   394
        internalFormat = GL_RGBA;
slouken@3139
   395
        format = GL_RGBA;
slouken@3139
   396
        type = GL_UNSIGNED_BYTE;
slouken@3139
   397
        break;
slouken@4985
   398
    case SDL_PIXELFORMAT_RGB565:
lestat@3163
   399
        internalFormat = GL_RGB;
lestat@3163
   400
        format = GL_RGB;
lestat@3163
   401
        type = GL_UNSIGNED_SHORT_5_6_5;
lestat@3163
   402
        break;
slouken@4985
   403
    case SDL_PIXELFORMAT_RGBA5551:
lestat@3163
   404
        internalFormat = GL_RGBA;
lestat@3163
   405
        format = GL_RGBA;
lestat@3163
   406
        type = GL_UNSIGNED_SHORT_5_5_5_1;
lestat@3163
   407
        break;
slouken@4985
   408
    case SDL_PIXELFORMAT_RGBA4444:
lestat@3163
   409
        internalFormat = GL_RGBA;
lestat@3163
   410
        format = GL_RGBA;
lestat@3163
   411
        type = GL_UNSIGNED_SHORT_4_4_4_4;
lestat@3163
   412
        break;
slouken@2753
   413
    default:
slouken@4990
   414
        SDL_SetError("Texture format %s not supported by OpenGL ES",
slouken@4990
   415
                     SDL_GetPixelFormatName(texture->format));
slouken@2753
   416
        return -1;
hfutrell@2739
   417
    }
slouken@2753
   418
slouken@2753
   419
    data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data));
hfutrell@2739
   420
    if (!data) {
hfutrell@2739
   421
        SDL_OutOfMemory();
hfutrell@2739
   422
        return -1;
hfutrell@2739
   423
    }
hfutrell@2739
   424
hfutrell@2739
   425
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
hfutrell@2739
   426
        data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
hfutrell@2739
   427
        data->pixels = SDL_malloc(texture->h * data->pitch);
hfutrell@2739
   428
        if (!data->pixels) {
hfutrell@2739
   429
            SDL_OutOfMemory();
hfutrell@2739
   430
            SDL_free(data);
hfutrell@2739
   431
            return -1;
hfutrell@2739
   432
        }
hfutrell@2739
   433
    }
hfutrell@2739
   434
hfutrell@2739
   435
    texture->driverdata = data;
hfutrell@2739
   436
hfutrell@2739
   437
    renderdata->glGetError();
lestat@3122
   438
    renderdata->glEnable(GL_TEXTURE_2D);
hfutrell@2739
   439
    renderdata->glGenTextures(1, &data->texture);
slouken@2753
   440
slouken@2753
   441
    data->type = GL_TEXTURE_2D;
slouken@2753
   442
    /* no NPOV textures allowed in OpenGL ES (yet) */
slouken@2753
   443
    texture_w = power_of_2(texture->w);
slouken@2753
   444
    texture_h = power_of_2(texture->h);
slouken@2753
   445
    data->texw = (GLfloat) texture->w / texture_w;
slouken@2753
   446
    data->texh = (GLfloat) texture->h / texture_h;
slouken@2753
   447
hfutrell@2739
   448
    data->format = format;
hfutrell@2739
   449
    data->formattype = type;
hfutrell@2739
   450
    renderdata->glBindTexture(data->type, data->texture);
hfutrell@2739
   451
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
hfutrell@2739
   452
                                GL_NEAREST);
hfutrell@2739
   453
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
hfutrell@2739
   454
                                GL_NEAREST);
hfutrell@2739
   455
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
hfutrell@2739
   456
                                GL_CLAMP_TO_EDGE);
hfutrell@2739
   457
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
hfutrell@2739
   458
                                GL_CLAMP_TO_EDGE);
slouken@2753
   459
slouken@2753
   460
    renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
slouken@2753
   461
                             texture_h, 0, format, type, NULL);
lestat@3122
   462
    renderdata->glDisable(GL_TEXTURE_2D);
hfutrell@2739
   463
hfutrell@2739
   464
    result = renderdata->glGetError();
hfutrell@2739
   465
    if (result != GL_NO_ERROR) {
hfutrell@2739
   466
        GLES_SetError("glTexImage2D()", result);
hfutrell@2739
   467
        return -1;
hfutrell@2739
   468
    }
hfutrell@2739
   469
    return 0;
hfutrell@2739
   470
}
hfutrell@2739
   471
hfutrell@2739
   472
static int
hfutrell@2739
   473
GLES_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
   474
                        void **pixels, int *pitch)
hfutrell@2739
   475
{
hfutrell@2739
   476
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   477
hfutrell@2739
   478
    *pixels = data->pixels;
hfutrell@2739
   479
    *pitch = data->pitch;
hfutrell@2739
   480
    return 0;
hfutrell@2739
   481
}
hfutrell@2739
   482
hfutrell@2739
   483
static int
hfutrell@2739
   484
GLES_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
   485
                       const SDL_Color * colors, int firstcolor, int ncolors)
hfutrell@2739
   486
{
slouken@2753
   487
    SDL_SetError("OpenGL ES does not support paletted textures");
hfutrell@2739
   488
    return -1;
hfutrell@2739
   489
}
hfutrell@2739
   490
hfutrell@2739
   491
static int
hfutrell@2739
   492
GLES_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
   493
                       SDL_Color * colors, int firstcolor, int ncolors)
hfutrell@2739
   494
{
slouken@2753
   495
    SDL_SetError("OpenGL ES does not support paletted textures");
hfutrell@2739
   496
    return -1;
hfutrell@2739
   497
}
hfutrell@2739
   498
hfutrell@2739
   499
static void
hfutrell@2739
   500
SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture,
hfutrell@2739
   501
                   int pitch)
hfutrell@2739
   502
{
slouken@2753
   503
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
slouken@2753
   504
    renderdata->glBindTexture(data->type, data->texture);
hfutrell@2739
   505
    renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
hfutrell@2739
   506
}
hfutrell@2739
   507
hfutrell@2739
   508
static int
hfutrell@2739
   509
GLES_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   510
{
hfutrell@2739
   511
    return 0;
hfutrell@2739
   512
}
hfutrell@2739
   513
hfutrell@2739
   514
static int
hfutrell@2739
   515
GLES_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   516
{
hfutrell@2739
   517
    return 0;
hfutrell@2739
   518
}
hfutrell@2739
   519
hfutrell@2739
   520
static int
hfutrell@2739
   521
GLES_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   522
{
hfutrell@2739
   523
    switch (texture->blendMode) {
slouken@2884
   524
    case SDL_BLENDMODE_NONE:
slouken@2884
   525
    case SDL_BLENDMODE_MASK:
slouken@2884
   526
    case SDL_BLENDMODE_BLEND:
slouken@2884
   527
    case SDL_BLENDMODE_ADD:
slouken@2884
   528
    case SDL_BLENDMODE_MOD:
hfutrell@2739
   529
        return 0;
hfutrell@2739
   530
    default:
hfutrell@2739
   531
        SDL_Unsupported();
slouken@2884
   532
        texture->blendMode = SDL_BLENDMODE_NONE;
hfutrell@2739
   533
        return -1;
hfutrell@2739
   534
    }
hfutrell@2739
   535
}
hfutrell@2739
   536
hfutrell@2739
   537
static int
hfutrell@2739
   538
GLES_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   539
{
hfutrell@2739
   540
    switch (texture->scaleMode) {
slouken@4929
   541
    case SDL_SCALEMODE_NONE:
slouken@4929
   542
    case SDL_SCALEMODE_FAST:
slouken@4929
   543
    case SDL_SCALEMODE_SLOW:
hfutrell@2739
   544
        return 0;
slouken@4929
   545
    case SDL_SCALEMODE_BEST:
hfutrell@2739
   546
        SDL_Unsupported();
slouken@4929
   547
        texture->scaleMode = SDL_SCALEMODE_SLOW;
hfutrell@2739
   548
        return -1;
hfutrell@2739
   549
    default:
hfutrell@2739
   550
        SDL_Unsupported();
slouken@4929
   551
        texture->scaleMode = SDL_SCALEMODE_NONE;
hfutrell@2739
   552
        return -1;
hfutrell@2739
   553
    }
hfutrell@2739
   554
}
hfutrell@2739
   555
hfutrell@2739
   556
static int
slouken@3139
   557
GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@3139
   558
                   const SDL_Rect * rect, const void *pixels, int pitch)
hfutrell@2739
   559
{
hfutrell@2739
   560
    GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   561
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   562
    GLenum result;
slouken@5052
   563
    int bpp = SDL_BYTESPERPIXEL(texture->format);
slouken@5052
   564
    void * temp_buffer;
slouken@5052
   565
    void * temp_ptr;
slouken@5052
   566
    int i;
hfutrell@2739
   567
lestat@3122
   568
    renderdata->glGetError();
lestat@3122
   569
    renderdata->glEnable(data->type);
hfutrell@2739
   570
    SetupTextureUpdate(renderdata, texture, pitch);
slouken@5052
   571
slouken@5052
   572
    if( rect->w * bpp == pitch ) {
slouken@5052
   573
         temp_buffer = (void *)pixels; /* No need to reformat */
slouken@5052
   574
    } else {
slouken@5052
   575
         /* Reformatting of mem area required */
slouken@5052
   576
         temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
slouken@5052
   577
         temp_ptr = temp_buffer;
slouken@5052
   578
         for (i = 0; i < rect->h; i++) {
slouken@5052
   579
             SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
slouken@5052
   580
             temp_ptr += rect->w * bpp;
slouken@5052
   581
             pixels += pitch;
slouken@5052
   582
         }
slouken@5052
   583
    }
slouken@5052
   584
slouken@2753
   585
    renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
hfutrell@2739
   586
                                rect->h, data->format, data->formattype,
slouken@5052
   587
                                temp_buffer);
slouken@5052
   588
slouken@5052
   589
    if( temp_buffer != pixels ) {
slouken@5052
   590
        SDL_free(temp_buffer);
slouken@5052
   591
    }
slouken@5052
   592
lestat@3122
   593
    renderdata->glDisable(data->type);
hfutrell@2739
   594
    result = renderdata->glGetError();
hfutrell@2739
   595
    if (result != GL_NO_ERROR) {
hfutrell@2739
   596
        GLES_SetError("glTexSubImage2D()", result);
hfutrell@2739
   597
        return -1;
hfutrell@2739
   598
    }
hfutrell@2739
   599
    return 0;
hfutrell@2739
   600
}
hfutrell@2739
   601
hfutrell@2739
   602
static int
hfutrell@2739
   603
GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
   604
                 const SDL_Rect * rect, int markDirty, void **pixels,
slouken@2753
   605
                 int *pitch)
hfutrell@2739
   606
{
hfutrell@2739
   607
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   608
hfutrell@2739
   609
    if (markDirty) {
hfutrell@2739
   610
        SDL_AddDirtyRect(&data->dirty, rect);
hfutrell@2739
   611
    }
hfutrell@2739
   612
hfutrell@2739
   613
    *pixels =
hfutrell@2739
   614
        (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
hfutrell@2739
   615
                  rect->x * SDL_BYTESPERPIXEL(texture->format));
hfutrell@2739
   616
    *pitch = data->pitch;
hfutrell@2739
   617
    return 0;
hfutrell@2739
   618
}
hfutrell@2739
   619
hfutrell@2739
   620
static void
hfutrell@2739
   621
GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   622
{
hfutrell@2739
   623
}
hfutrell@2739
   624
hfutrell@2739
   625
static void
slouken@2753
   626
GLES_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
   627
                  int numrects, const SDL_Rect * rects)
hfutrell@2739
   628
{
hfutrell@2739
   629
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   630
    int i;
hfutrell@2739
   631
hfutrell@2739
   632
    for (i = 0; i < numrects; ++i) {
hfutrell@2739
   633
        SDL_AddDirtyRect(&data->dirty, &rects[i]);
hfutrell@2739
   634
    }
hfutrell@2739
   635
}
hfutrell@2739
   636
slouken@2936
   637
static void
lestat@3393
   638
GLES_SetBlendMode(GLES_RenderData * data, int blendMode, int isprimitive)
slouken@2936
   639
{
slouken@2936
   640
    if (blendMode != data->blendMode) {
slouken@2936
   641
        switch (blendMode) {
slouken@2936
   642
        case SDL_BLENDMODE_NONE:
slouken@2936
   643
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
slouken@2936
   644
            data->glDisable(GL_BLEND);
slouken@2936
   645
            break;
slouken@2936
   646
        case SDL_BLENDMODE_MASK:
lestat@3393
   647
            if (isprimitive) {
lestat@3393
   648
                data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
lestat@3393
   649
                data->glDisable(GL_BLEND);
lestat@3393
   650
                /* The same as SDL_BLENDMODE_NONE */
lestat@3393
   651
                blendMode = SDL_BLENDMODE_NONE;
lestat@3393
   652
                break;
lestat@3393
   653
            }
lestat@3393
   654
            /* fall through */
slouken@2936
   655
        case SDL_BLENDMODE_BLEND:
slouken@2936
   656
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2936
   657
            data->glEnable(GL_BLEND);
slouken@2936
   658
            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
slouken@2936
   659
            break;
slouken@2936
   660
        case SDL_BLENDMODE_ADD:
slouken@2936
   661
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2936
   662
            data->glEnable(GL_BLEND);
slouken@2936
   663
            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
slouken@2936
   664
            break;
slouken@2936
   665
        case SDL_BLENDMODE_MOD:
slouken@2936
   666
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2936
   667
            data->glEnable(GL_BLEND);
slouken@2936
   668
            data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
slouken@2936
   669
            break;
slouken@2936
   670
        }
slouken@2936
   671
        data->blendMode = blendMode;
slouken@2936
   672
    }
slouken@2936
   673
}
slouken@2936
   674
hfutrell@2739
   675
static int
slouken@3641
   676
GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3641
   677
                      int count)
hfutrell@2739
   678
{
slouken@2936
   679
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@3547
   680
    int i;
slouken@3547
   681
    GLshort *vertices;
slouken@2753
   682
lestat@3393
   683
    GLES_SetBlendMode(data, renderer->blendMode, 1);
slouken@2936
   684
slouken@2936
   685
    data->glColor4f((GLfloat) renderer->r * inv255f,
slouken@2936
   686
                    (GLfloat) renderer->g * inv255f,
slouken@2936
   687
                    (GLfloat) renderer->b * inv255f,
slouken@2936
   688
                    (GLfloat) renderer->a * inv255f);
slouken@2936
   689
slouken@3547
   690
    vertices = SDL_stack_alloc(GLshort, count*2);
slouken@3547
   691
    for (i = 0; i < count; ++i) {
slouken@3547
   692
        vertices[2*i+0] = (GLshort)points[i].x;
slouken@3547
   693
        vertices[2*i+1] = (GLshort)points[i].y;
slouken@3547
   694
    }
slouken@3547
   695
    data->glVertexPointer(2, GL_SHORT, 0, vertices);
slouken@3536
   696
    data->glDrawArrays(GL_POINTS, 0, count);
slouken@3547
   697
    SDL_stack_free(vertices);
slouken@2964
   698
slouken@2936
   699
    return 0;
slouken@2936
   700
}
slouken@2936
   701
slouken@2936
   702
static int
slouken@3641
   703
GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3641
   704
                     int count)
slouken@2936
   705
{
slouken@2936
   706
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@3547
   707
    int i;
slouken@3547
   708
    GLshort *vertices;
slouken@2936
   709
lestat@3393
   710
    GLES_SetBlendMode(data, renderer->blendMode, 1);
slouken@2936
   711
slouken@2936
   712
    data->glColor4f((GLfloat) renderer->r * inv255f,
slouken@2936
   713
                    (GLfloat) renderer->g * inv255f,
slouken@2936
   714
                    (GLfloat) renderer->b * inv255f,
slouken@2936
   715
                    (GLfloat) renderer->a * inv255f);
slouken@2936
   716
slouken@3547
   717
    vertices = SDL_stack_alloc(GLshort, count*2);
slouken@3547
   718
    for (i = 0; i < count; ++i) {
slouken@3547
   719
        vertices[2*i+0] = (GLshort)points[i].x;
slouken@3547
   720
        vertices[2*i+1] = (GLshort)points[i].y;
slouken@3547
   721
    }
slouken@3547
   722
    data->glVertexPointer(2, GL_SHORT, 0, vertices);
slouken@3536
   723
    if (count > 2 && 
slouken@3536
   724
        points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
slouken@3536
   725
        /* GL_LINE_LOOP takes care of the final segment */
slouken@3536
   726
        --count;
slouken@3536
   727
        data->glDrawArrays(GL_LINE_LOOP, 0, count);
slouken@3536
   728
    } else {
slouken@3536
   729
        data->glDrawArrays(GL_LINE_STRIP, 0, count);
slouken@3536
   730
    }
slouken@3547
   731
    SDL_stack_free(vertices);
hfutrell@2949
   732
slouken@2936
   733
    return 0;
slouken@2936
   734
}
slouken@2936
   735
slouken@2936
   736
static int
slouken@3641
   737
GLES_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3641
   738
                     int count)
slouken@3641
   739
{
slouken@3641
   740
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@3641
   741
    int i;
slouken@3641
   742
slouken@3641
   743
    GLES_SetBlendMode(data, renderer->blendMode, 1);
slouken@3641
   744
slouken@3641
   745
    data->glColor4f((GLfloat) renderer->r * inv255f,
slouken@3641
   746
                    (GLfloat) renderer->g * inv255f,
slouken@3641
   747
                    (GLfloat) renderer->b * inv255f,
slouken@3641
   748
                    (GLfloat) renderer->a * inv255f);
slouken@3641
   749
slouken@3641
   750
    for (i = 0; i < count; ++i) {
slouken@3641
   751
        const SDL_Rect *rect = rects[i];
slouken@3641
   752
        GLshort minx = rect->x;
slouken@3641
   753
        GLshort maxx = rect->x + rect->w;
slouken@3641
   754
        GLshort miny = rect->y;
slouken@3641
   755
        GLshort maxy = rect->y + rect->h;
slouken@3641
   756
        GLshort vertices[8];
slouken@3641
   757
        vertices[0] = minx;
slouken@3641
   758
        vertices[1] = miny;
slouken@3641
   759
        vertices[2] = maxx;
slouken@3641
   760
        vertices[3] = miny;
slouken@3641
   761
        vertices[4] = minx;
slouken@3641
   762
        vertices[5] = maxy;
slouken@3641
   763
        vertices[6] = maxx;
slouken@3641
   764
        vertices[7] = maxy;
slouken@3641
   765
slouken@3641
   766
        data->glVertexPointer(2, GL_SHORT, 0, vertices);
slouken@3641
   767
        data->glDrawArrays(GL_LINE_LOOP, 0, 4);
slouken@3641
   768
    }
slouken@3641
   769
slouken@3641
   770
    return 0;
slouken@3641
   771
}
slouken@3641
   772
slouken@3641
   773
static int
slouken@3641
   774
GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3641
   775
                     int count)
slouken@2936
   776
{
slouken@2753
   777
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
slouken@3536
   778
    int i;
slouken@2753
   779
lestat@3393
   780
    GLES_SetBlendMode(data, renderer->blendMode, 1);
slouken@2753
   781
slouken@2936
   782
    data->glColor4f((GLfloat) renderer->r * inv255f,
slouken@2936
   783
                    (GLfloat) renderer->g * inv255f,
slouken@2936
   784
                    (GLfloat) renderer->b * inv255f,
slouken@2936
   785
                    (GLfloat) renderer->a * inv255f);
slouken@2753
   786
slouken@3536
   787
    for (i = 0; i < count; ++i) {
slouken@3536
   788
        const SDL_Rect *rect = rects[i];
slouken@3536
   789
        GLshort minx = rect->x;
slouken@3536
   790
        GLshort maxx = rect->x + rect->w;
slouken@3536
   791
        GLshort miny = rect->y;
slouken@3536
   792
        GLshort maxy = rect->y + rect->h;
slouken@3536
   793
        GLshort vertices[8];
slouken@3536
   794
        vertices[0] = minx;
slouken@3536
   795
        vertices[1] = miny;
slouken@3536
   796
        vertices[2] = maxx;
slouken@3536
   797
        vertices[3] = miny;
slouken@3536
   798
        vertices[4] = minx;
slouken@3536
   799
        vertices[5] = maxy;
slouken@3536
   800
        vertices[6] = maxx;
slouken@3536
   801
        vertices[7] = maxy;
slouken@2964
   802
slouken@3536
   803
        data->glVertexPointer(2, GL_SHORT, 0, vertices);
slouken@3536
   804
        data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
slouken@3536
   805
    }
hfutrell@2949
   806
slouken@2753
   807
    return 0;
hfutrell@2739
   808
}
hfutrell@2739
   809
hfutrell@2739
   810
static int
hfutrell@2739
   811
GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2753
   812
                const SDL_Rect * srcrect, const SDL_Rect * dstrect)
hfutrell@2739
   813
{
slouken@2753
   814
hfutrell@2739
   815
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   816
    GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   817
    int minx, miny, maxx, maxy;
hfutrell@2739
   818
    GLfloat minu, maxu, minv, maxv;
slouken@2753
   819
    int i;
slouken@2753
   820
    void *temp_buffer;          /* used for reformatting dirty rect pixels */
slouken@2753
   821
    void *temp_ptr;
slouken@2753
   822
lestat@3122
   823
    data->glEnable(GL_TEXTURE_2D);
lestat@3122
   824
hfutrell@2739
   825
    if (texturedata->dirty.list) {
hfutrell@2739
   826
        SDL_DirtyRect *dirty;
hfutrell@2739
   827
        void *pixels;
hfutrell@2739
   828
        int bpp = SDL_BYTESPERPIXEL(texture->format);
hfutrell@2739
   829
        int pitch = texturedata->pitch;
hfutrell@2739
   830
hfutrell@2739
   831
        SetupTextureUpdate(data, texture, pitch);
slouken@2753
   832
hfutrell@2739
   833
        data->glBindTexture(texturedata->type, texturedata->texture);
hfutrell@2739
   834
        for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
hfutrell@2739
   835
            SDL_Rect *rect = &dirty->rect;
slouken@2753
   836
            pixels =
slouken@2753
   837
                (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
slouken@2753
   838
                          rect->x * bpp);
slouken@2753
   839
            /*      There is no GL_UNPACK_ROW_LENGTH in OpenGLES 
slouken@2753
   840
               we must do this reformatting ourselves(!)
slouken@2753
   841
slouken@2753
   842
               maybe it'd be a good idea to keep a temp buffer around
slouken@2753
   843
               for this purpose rather than allocating it each time
slouken@2753
   844
             */
slouken@4525
   845
            if( rect->x == 0 && rect->w * bpp == pitch ) {
slouken@4525
   846
                temp_buffer = pixels; /* Updating whole texture, no need to reformat */
slouken@4525
   847
            } else {
slouken@4525
   848
                temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
slouken@4525
   849
                temp_ptr = temp_buffer;
slouken@4525
   850
                for (i = 0; i < rect->h; i++) {
slouken@4525
   851
                    SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
slouken@4525
   852
                    temp_ptr += rect->w * bpp;
slouken@4525
   853
                    pixels += pitch;
slouken@4525
   854
                }
slouken@2753
   855
            }
slouken@2753
   856
hfutrell@2739
   857
            data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
hfutrell@2739
   858
                                  rect->w, rect->h, texturedata->format,
hfutrell@2739
   859
                                  texturedata->formattype, temp_buffer);
slouken@2753
   860
slouken@4525
   861
            if( temp_buffer != pixels ) {
slouken@4525
   862
                SDL_free(temp_buffer);
slouken@4525
   863
            }
hfutrell@2739
   864
        }
hfutrell@2739
   865
        SDL_ClearDirtyRects(&texturedata->dirty);
hfutrell@2739
   866
    }
slouken@2753
   867
hfutrell@2739
   868
    data->glBindTexture(texturedata->type, texturedata->texture);
slouken@2753
   869
hfutrell@2739
   870
    if (texture->modMode) {
hfutrell@2739
   871
        data->glColor4f((GLfloat) texture->r * inv255f,
hfutrell@2739
   872
                        (GLfloat) texture->g * inv255f,
hfutrell@2739
   873
                        (GLfloat) texture->b * inv255f,
hfutrell@2739
   874
                        (GLfloat) texture->a * inv255f);
hfutrell@2739
   875
    } else {
hfutrell@2739
   876
        data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
hfutrell@2739
   877
    }
hfutrell@2739
   878
lestat@3393
   879
    GLES_SetBlendMode(data, texture->blendMode, 0);
hfutrell@2739
   880
slouken@2753
   881
    switch (texture->scaleMode) {
slouken@4929
   882
    case SDL_SCALEMODE_NONE:
slouken@4929
   883
    case SDL_SCALEMODE_FAST:
slouken@2753
   884
        data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
slouken@2753
   885
                              GL_NEAREST);
slouken@2753
   886
        data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
slouken@2753
   887
                              GL_NEAREST);
slouken@2753
   888
        break;
slouken@4929
   889
    case SDL_SCALEMODE_SLOW:
slouken@4929
   890
    case SDL_SCALEMODE_BEST:
slouken@2753
   891
        data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
slouken@2753
   892
                              GL_LINEAR);
slouken@2753
   893
        data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
slouken@2753
   894
                              GL_LINEAR);
slouken@2753
   895
        break;
slouken@2753
   896
    }
hfutrell@2739
   897
slouken@2753
   898
    if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
slouken@2753
   899
        /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
slouken@3685
   900
        SDL_Window *window = renderer->window;
slouken@2753
   901
        GLint cropRect[4];
slouken@2753
   902
        cropRect[0] = srcrect->x;
slouken@2753
   903
        cropRect[1] = srcrect->y + srcrect->h;
slouken@2753
   904
        cropRect[2] = srcrect->w;
slouken@2753
   905
        cropRect[3] = -srcrect->h;
slouken@2753
   906
        data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
slouken@2753
   907
                               cropRect);
slouken@2753
   908
        data->glDrawTexiOES(dstrect->x, window->h - dstrect->y - dstrect->h,
slouken@2753
   909
                            0, dstrect->w, dstrect->h);
slouken@2753
   910
    } else {
slouken@2753
   911
slouken@2753
   912
        minx = dstrect->x;
slouken@2753
   913
        miny = dstrect->y;
slouken@2753
   914
        maxx = dstrect->x + dstrect->w;
slouken@2753
   915
        maxy = dstrect->y + dstrect->h;
slouken@2753
   916
slouken@2753
   917
        minu = (GLfloat) srcrect->x / texture->w;
slouken@2753
   918
        minu *= texturedata->texw;
slouken@2753
   919
        maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
slouken@2753
   920
        maxu *= texturedata->texw;
slouken@2753
   921
        minv = (GLfloat) srcrect->y / texture->h;
slouken@2753
   922
        minv *= texturedata->texh;
slouken@2753
   923
        maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
slouken@2753
   924
        maxv *= texturedata->texh;
slouken@2753
   925
slouken@2753
   926
        GLshort vertices[8];
slouken@2753
   927
        GLfloat texCoords[8];
slouken@2753
   928
slouken@2753
   929
        vertices[0] = minx;
slouken@2753
   930
        vertices[1] = miny;
slouken@2753
   931
        vertices[2] = maxx;
slouken@2753
   932
        vertices[3] = miny;
slouken@2753
   933
        vertices[4] = minx;
slouken@2753
   934
        vertices[5] = maxy;
slouken@2753
   935
        vertices[6] = maxx;
slouken@2753
   936
        vertices[7] = maxy;
slouken@2753
   937
slouken@2753
   938
        texCoords[0] = minu;
slouken@2753
   939
        texCoords[1] = minv;
slouken@2753
   940
        texCoords[2] = maxu;
slouken@2753
   941
        texCoords[3] = minv;
slouken@2753
   942
        texCoords[4] = minu;
slouken@2753
   943
        texCoords[5] = maxv;
slouken@2753
   944
        texCoords[6] = maxu;
slouken@2753
   945
        texCoords[7] = maxv;
slouken@2753
   946
slouken@2753
   947
        data->glVertexPointer(2, GL_SHORT, 0, vertices);
slouken@2753
   948
        data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
slouken@2753
   949
        data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
lestat@3122
   950
    }
slouken@2753
   951
lestat@3122
   952
    data->glDisable(GL_TEXTURE_2D);
slouken@2753
   953
hfutrell@2739
   954
    return 0;
hfutrell@2739
   955
}
hfutrell@2739
   956
hfutrell@2739
   957
static void
slouken@3139
   958
GLES_RenderPresent(SDL_Renderer * renderer)
hfutrell@2739
   959
{
hfutrell@2739
   960
    SDL_GL_SwapWindow(renderer->window);
hfutrell@2739
   961
}
hfutrell@2739
   962
hfutrell@2739
   963
static void
hfutrell@2739
   964
GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
hfutrell@2739
   965
{
hfutrell@2739
   966
    GLES_TextureData *data = (GLES_TextureData *) texture->driverdata;
hfutrell@2739
   967
hfutrell@2739
   968
    if (!data) {
hfutrell@2739
   969
        return;
hfutrell@2739
   970
    }
hfutrell@2739
   971
    if (data->texture) {
slouken@2753
   972
        glDeleteTextures(1, &data->texture);
hfutrell@2739
   973
    }
hfutrell@2739
   974
    if (data->pixels) {
hfutrell@2739
   975
        SDL_free(data->pixels);
hfutrell@2739
   976
    }
hfutrell@2739
   977
    SDL_FreeDirtyRects(&data->dirty);
hfutrell@2739
   978
    SDL_free(data);
hfutrell@2739
   979
    texture->driverdata = NULL;
hfutrell@2739
   980
}
hfutrell@2739
   981
hfutrell@2739
   982
static void
hfutrell@2739
   983
GLES_DestroyRenderer(SDL_Renderer * renderer)
hfutrell@2739
   984
{
hfutrell@2739
   985
    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
hfutrell@2739
   986
hfutrell@2739
   987
    if (data) {
hfutrell@2739
   988
        if (data->context) {
hfutrell@2739
   989
            SDL_GL_DeleteContext(data->context);
hfutrell@2739
   990
        }
hfutrell@2739
   991
        SDL_free(data);
hfutrell@2739
   992
    }
hfutrell@2739
   993
    SDL_free(renderer);
hfutrell@2739
   994
}
hfutrell@2739
   995
slouken@3099
   996
#endif /* SDL_VIDEO_RENDER_OGL_ES */
hfutrell@2739
   997
hfutrell@2739
   998
/* vi: set ts=4 sw=4 expandtab: */