src/render/opengl/SDL_render_gl.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 10 Jan 2012 21:00:47 -0500
changeset 6207 15ff38383cb7
parent 6182 eb6796f3e598
child 6232 37e8d0736366
permissions -rwxr-xr-x
Fixed bug 1331 - SDL_CreateTextureFromSurface fails for OpenGL + Win XP 64 NVidia 285.58 with GL_INVALID_ENUM

I think this fixes the bug. I'm not sure why it would fail, and it may have something to do with the version of OpenGL that we initialize and use by default. Regardless, this should take care of the problem.
slouken@1918
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6138
     3
  Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
slouken@1918
     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.
slouken@1918
     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:
slouken@1918
    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.
slouken@1918
    20
*/
slouken@1918
    21
#include "SDL_config.h"
slouken@1918
    22
slouken@5226
    23
#if SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED
slouken@1920
    24
slouken@5233
    25
#include "SDL_hints.h"
slouken@5233
    26
#include "SDL_log.h"
slouken@1920
    27
#include "SDL_opengl.h"
slouken@5154
    28
#include "../SDL_sysrender.h"
slouken@5228
    29
#include "SDL_shaders_gl.h"
slouken@1918
    30
slouken@2246
    31
#ifdef __MACOSX__
slouken@2246
    32
#include <OpenGL/OpenGL.h>
slouken@2246
    33
#endif
slouken@2246
    34
slouken@2778
    35
slouken@1918
    36
/* OpenGL renderer implementation */
slouken@1918
    37
slouken@2230
    38
/* Details on optimizing the texture path on Mac OS X:
slouken@5203
    39
   http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html
slouken@2230
    40
*/
slouken@2230
    41
slouken@5154
    42
/* Used to re-create the window with OpenGL capability */
slouken@5154
    43
extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
icculus@2835
    44
slouken@1985
    45
static const float inv255f = 1.0f / 255.0f;
slouken@1985
    46
slouken@1918
    47
static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@5147
    48
static void GL_WindowEvent(SDL_Renderer * renderer,
slouken@5147
    49
                           const SDL_WindowEvent *event);
slouken@1918
    50
static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1918
    51
static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
    52
                            const SDL_Rect * rect, const void *pixels,
slouken@1918
    53
                            int pitch);
slouken@1918
    54
static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
    55
                          const SDL_Rect * rect, void **pixels, int *pitch);
slouken@1918
    56
static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@5297
    57
static int GL_UpdateViewport(SDL_Renderer * renderer);
slouken@3596
    58
static int GL_RenderClear(SDL_Renderer * renderer);
slouken@3596
    59
static int GL_RenderDrawPoints(SDL_Renderer * renderer,
slouken@3596
    60
                               const SDL_Point * points, int count);
slouken@3596
    61
static int GL_RenderDrawLines(SDL_Renderer * renderer,
slouken@3596
    62
                              const SDL_Point * points, int count);
slouken@3596
    63
static int GL_RenderFillRects(SDL_Renderer * renderer,
slouken@5297
    64
                              const SDL_Rect * rects, int count);
slouken@1918
    65
static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    66
                         const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@3431
    67
static int GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
    68
                               Uint32 pixel_format, void * pixels, int pitch);
slouken@1918
    69
static void GL_RenderPresent(SDL_Renderer * renderer);
slouken@1918
    70
static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1918
    71
static void GL_DestroyRenderer(SDL_Renderer * renderer);
slouken@1918
    72
slouken@1918
    73
slouken@1918
    74
SDL_RenderDriver GL_RenderDriver = {
slouken@1918
    75
    GL_CreateRenderer,
slouken@1918
    76
    {
slouken@1918
    77
     "opengl",
slouken@5203
    78
     (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
slouken@5156
    79
     1,
slouken@5156
    80
     {SDL_PIXELFORMAT_ARGB8888},
slouken@1918
    81
     0,
slouken@1918
    82
     0}
slouken@1918
    83
};
slouken@1918
    84
slouken@1918
    85
typedef struct
slouken@1918
    86
{
slouken@1918
    87
    SDL_GLContext context;
slouken@2233
    88
    SDL_bool GL_ARB_texture_rectangle_supported;
slouken@5355
    89
    struct {
slouken@5355
    90
        GL_Shader shader;
slouken@5355
    91
        Uint32 color;
slouken@5355
    92
        int blendMode;
slouken@5355
    93
    } current;
slouken@1927
    94
slouken@1927
    95
    /* OpenGL functions */
slouken@1927
    96
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
slouken@5204
    97
#include "SDL_glfuncs.h"
slouken@1927
    98
#undef SDL_PROC
slouken@1974
    99
slouken@5228
   100
    /* Multitexture support */
slouken@5228
   101
    SDL_bool GL_ARB_multitexture_supported;
slouken@5228
   102
    PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
slouken@5351
   103
    GLint num_texture_units;
slouken@5228
   104
slouken@5228
   105
    /* Shader support */
slouken@5228
   106
    GL_ShaderContext *shaders;
slouken@5228
   107
slouken@1918
   108
} GL_RenderData;
slouken@1918
   109
slouken@1918
   110
typedef struct
slouken@1918
   111
{
slouken@1918
   112
    GLuint texture;
slouken@1920
   113
    GLenum type;
slouken@1918
   114
    GLfloat texw;
slouken@1918
   115
    GLfloat texh;
slouken@1920
   116
    GLenum format;
slouken@1920
   117
    GLenum formattype;
slouken@1918
   118
    void *pixels;
slouken@1918
   119
    int pitch;
slouken@5227
   120
    SDL_Rect locked_rect;
slouken@5264
   121
slouken@5264
   122
    /* YV12 texture support */
slouken@5264
   123
    SDL_bool yuv;
slouken@5264
   124
    GLuint utexture;
slouken@5264
   125
    GLuint vtexture;
slouken@1918
   126
} GL_TextureData;
slouken@1918
   127
slouken@1918
   128
slouken@1924
   129
static void
slouken@1924
   130
GL_SetError(const char *prefix, GLenum result)
slouken@1924
   131
{
slouken@1924
   132
    const char *error;
slouken@1924
   133
slouken@1924
   134
    switch (result) {
slouken@1924
   135
    case GL_NO_ERROR:
slouken@1924
   136
        error = "GL_NO_ERROR";
slouken@1924
   137
        break;
slouken@1924
   138
    case GL_INVALID_ENUM:
slouken@1924
   139
        error = "GL_INVALID_ENUM";
slouken@1924
   140
        break;
slouken@1924
   141
    case GL_INVALID_VALUE:
slouken@1924
   142
        error = "GL_INVALID_VALUE";
slouken@1924
   143
        break;
slouken@1924
   144
    case GL_INVALID_OPERATION:
slouken@1924
   145
        error = "GL_INVALID_OPERATION";
slouken@1924
   146
        break;
slouken@1924
   147
    case GL_STACK_OVERFLOW:
slouken@1924
   148
        error = "GL_STACK_OVERFLOW";
slouken@1924
   149
        break;
slouken@1924
   150
    case GL_STACK_UNDERFLOW:
slouken@1924
   151
        error = "GL_STACK_UNDERFLOW";
slouken@1924
   152
        break;
slouken@1924
   153
    case GL_OUT_OF_MEMORY:
slouken@1924
   154
        error = "GL_OUT_OF_MEMORY";
slouken@1924
   155
        break;
slouken@1924
   156
    case GL_TABLE_TOO_LARGE:
slouken@1924
   157
        error = "GL_TABLE_TOO_LARGE";
slouken@1924
   158
        break;
slouken@1924
   159
    default:
slouken@1924
   160
        error = "UNKNOWN";
slouken@1924
   161
        break;
slouken@1924
   162
    }
slouken@1924
   163
    SDL_SetError("%s: %s", prefix, error);
slouken@1924
   164
}
slouken@1924
   165
slouken@1927
   166
static int
slouken@1927
   167
GL_LoadFunctions(GL_RenderData * data)
slouken@1927
   168
{
slouken@1927
   169
#ifdef __SDL_NOGETPROCADDR__
slouken@1927
   170
#define SDL_PROC(ret,func,params) data->func=func;
slouken@1927
   171
#else
slouken@1927
   172
#define SDL_PROC(ret,func,params) \
slouken@1927
   173
    do { \
slouken@1927
   174
        data->func = SDL_GL_GetProcAddress(#func); \
slouken@1927
   175
        if ( ! data->func ) { \
slouken@1927
   176
            SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
slouken@1927
   177
            return -1; \
slouken@1927
   178
        } \
slouken@1927
   179
    } while ( 0 );
slouken@1927
   180
#endif /* __SDL_NOGETPROCADDR__ */
slouken@1927
   181
slouken@5204
   182
#include "SDL_glfuncs.h"
slouken@1927
   183
#undef SDL_PROC
slouken@1927
   184
    return 0;
slouken@1927
   185
}
slouken@1927
   186
slouken@5297
   187
static SDL_GLContext SDL_CurrentContext = NULL;
slouken@5297
   188
slouken@5297
   189
static int
slouken@5297
   190
GL_ActivateRenderer(SDL_Renderer * renderer)
slouken@5297
   191
{
slouken@5297
   192
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@5297
   193
slouken@5297
   194
    if (SDL_CurrentContext != data->context) {
slouken@5297
   195
        if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
slouken@5297
   196
            return -1;
slouken@5297
   197
        }
slouken@5297
   198
        SDL_CurrentContext = data->context;
slouken@5297
   199
slouken@5297
   200
        GL_UpdateViewport(renderer);
slouken@5297
   201
    }
slouken@5297
   202
    return 0;
slouken@5297
   203
}
slouken@5297
   204
slouken@5355
   205
/* This is called if we need to invalidate all of the SDL OpenGL state */
slouken@5355
   206
static void
slouken@5355
   207
GL_ResetState(SDL_Renderer *renderer)
slouken@5355
   208
{
slouken@5355
   209
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@5355
   210
slouken@5355
   211
    if (SDL_CurrentContext == data->context) {
slouken@5355
   212
        GL_UpdateViewport(renderer);
slouken@5355
   213
    } else {
slouken@5355
   214
        GL_ActivateRenderer(renderer);
slouken@5355
   215
    }
slouken@5355
   216
slouken@5355
   217
    data->current.shader = SHADER_NONE;
slouken@5355
   218
    data->current.color = 0;
slouken@5355
   219
    data->current.blendMode = -1;
slouken@5355
   220
slouken@5355
   221
    data->glDisable(GL_DEPTH_TEST);
slouken@5355
   222
    data->glDisable(GL_CULL_FACE);
slouken@5355
   223
    /* This ended up causing video discrepancies between OpenGL and Direct3D */
slouken@5355
   224
    /*data->glEnable(GL_LINE_SMOOTH);*/
slouken@5355
   225
slouken@5355
   226
    data->glMatrixMode(GL_MODELVIEW);
slouken@5355
   227
    data->glLoadIdentity();
slouken@5355
   228
}
slouken@5355
   229
slouken@1918
   230
SDL_Renderer *
slouken@1918
   231
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1918
   232
{
slouken@1918
   233
    SDL_Renderer *renderer;
slouken@1918
   234
    GL_RenderData *data;
slouken@5233
   235
    const char *hint;
slouken@1952
   236
    GLint value;
slouken@5154
   237
    Uint32 window_flags;
slouken@1918
   238
slouken@5154
   239
    window_flags = SDL_GetWindowFlags(window);
slouken@5154
   240
    if (!(window_flags & SDL_WINDOW_OPENGL)) {
slouken@5154
   241
        if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
slouken@6182
   242
            /* Uh oh, better try to put it back... */
slouken@6182
   243
            SDL_RecreateWindow(window, window_flags);
slouken@1924
   244
            return NULL;
slouken@1924
   245
        }
slouken@1918
   246
    }
slouken@1918
   247
slouken@1920
   248
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1918
   249
    if (!renderer) {
slouken@1918
   250
        SDL_OutOfMemory();
slouken@1918
   251
        return NULL;
slouken@1918
   252
    }
slouken@1918
   253
slouken@1920
   254
    data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1918
   255
    if (!data) {
slouken@1918
   256
        GL_DestroyRenderer(renderer);
slouken@1918
   257
        SDL_OutOfMemory();
slouken@1918
   258
        return NULL;
slouken@1918
   259
    }
slouken@1918
   260
slouken@5147
   261
    renderer->WindowEvent = GL_WindowEvent;
slouken@1918
   262
    renderer->CreateTexture = GL_CreateTexture;
slouken@1918
   263
    renderer->UpdateTexture = GL_UpdateTexture;
slouken@1918
   264
    renderer->LockTexture = GL_LockTexture;
slouken@1918
   265
    renderer->UnlockTexture = GL_UnlockTexture;
slouken@5297
   266
    renderer->UpdateViewport = GL_UpdateViewport;
slouken@3596
   267
    renderer->RenderClear = GL_RenderClear;
slouken@3596
   268
    renderer->RenderDrawPoints = GL_RenderDrawPoints;
slouken@3596
   269
    renderer->RenderDrawLines = GL_RenderDrawLines;
slouken@3596
   270
    renderer->RenderFillRects = GL_RenderFillRects;
slouken@1918
   271
    renderer->RenderCopy = GL_RenderCopy;
slouken@3431
   272
    renderer->RenderReadPixels = GL_RenderReadPixels;
slouken@1918
   273
    renderer->RenderPresent = GL_RenderPresent;
slouken@1918
   274
    renderer->DestroyTexture = GL_DestroyTexture;
slouken@1918
   275
    renderer->DestroyRenderer = GL_DestroyRenderer;
slouken@1918
   276
    renderer->info = GL_RenderDriver.info;
slouken@5297
   277
    renderer->info.flags = SDL_RENDERER_ACCELERATED;
slouken@1918
   278
    renderer->driverdata = data;
slouken@6171
   279
    renderer->window = window;
slouken@1918
   280
slouken@3685
   281
    data->context = SDL_GL_CreateContext(window);
slouken@1918
   282
    if (!data->context) {
slouken@1918
   283
        GL_DestroyRenderer(renderer);
slouken@1918
   284
        return NULL;
slouken@1918
   285
    }
slouken@3685
   286
    if (SDL_GL_MakeCurrent(window, data->context) < 0) {
slouken@1918
   287
        GL_DestroyRenderer(renderer);
slouken@1918
   288
        return NULL;
slouken@1918
   289
    }
slouken@5204
   290
slouken@5204
   291
    if (GL_LoadFunctions(data) < 0) {
slouken@5204
   292
        GL_DestroyRenderer(renderer);
slouken@5204
   293
        return NULL;
slouken@5204
   294
    }
slouken@5204
   295
slouken@2246
   296
#ifdef __MACOSX__
slouken@2246
   297
    /* Enable multi-threaded rendering */
slouken@2246
   298
    /* Disabled until Ryan finishes his VBO/PBO code...
bob@2295
   299
       CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
bob@2295
   300
     */
slouken@2246
   301
#endif
slouken@2246
   302
slouken@1965
   303
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1918
   304
        SDL_GL_SetSwapInterval(1);
slouken@1918
   305
    } else {
slouken@1918
   306
        SDL_GL_SetSwapInterval(0);
slouken@1918
   307
    }
slouken@1918
   308
    if (SDL_GL_GetSwapInterval() > 0) {
slouken@1965
   309
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1918
   310
    }
slouken@1918
   311
slouken@1952
   312
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
slouken@1952
   313
    renderer->info.max_texture_width = value;
slouken@1952
   314
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
slouken@1952
   315
    renderer->info.max_texture_height = value;
slouken@1920
   316
slouken@1926
   317
    if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
slouken@1926
   318
        || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
slouken@1926
   319
        data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
slouken@1926
   320
    }
slouken@1920
   321
slouken@5228
   322
    /* Check for multitexture support */
slouken@5228
   323
    if (SDL_GL_ExtensionSupported("GL_ARB_multitexture")) {
slouken@5228
   324
        data->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
slouken@5228
   325
        if (data->glActiveTextureARB) {
slouken@5228
   326
            data->GL_ARB_multitexture_supported = SDL_TRUE;
slouken@5228
   327
            data->glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &data->num_texture_units);
slouken@5228
   328
        }
slouken@5228
   329
    }
slouken@5228
   330
slouken@5228
   331
    /* Check for shader support */
slouken@5233
   332
    hint = SDL_GetHint(SDL_HINT_RENDER_OPENGL_SHADERS);
slouken@5233
   333
    if (!hint || *hint != '0') {
slouken@5233
   334
        data->shaders = GL_CreateShaderContext();
slouken@5233
   335
    }
slouken@5233
   336
    SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
slouken@5233
   337
                data->shaders ? "ENABLED" : "DISABLED");
slouken@5228
   338
slouken@5228
   339
    /* We support YV12 textures using 3 textures and a shader */
slouken@5228
   340
    if (data->shaders && data->num_texture_units >= 3) {
slouken@5228
   341
        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
slouken@5264
   342
        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
slouken@5228
   343
    }
slouken@5228
   344
slouken@1918
   345
    /* Set up parameters for rendering */
slouken@5355
   346
    GL_ResetState(renderer);
slouken@1918
   347
slouken@1918
   348
    return renderer;
slouken@1918
   349
}
slouken@1918
   350
slouken@5147
   351
static void
slouken@5147
   352
GL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
slouken@1970
   353
{
slouken@5276
   354
    if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
slouken@5147
   355
        /* Rebind the context to the window area and update matrices */
slouken@5147
   356
        SDL_CurrentContext = NULL;
slouken@5147
   357
    }
slouken@1923
   358
}
slouken@1923
   359
slouken@1922
   360
static __inline__ int
slouken@1922
   361
power_of_2(int input)
slouken@1922
   362
{
slouken@1922
   363
    int value = 1;
slouken@1922
   364
slouken@1922
   365
    while (value < input) {
slouken@1922
   366
        value <<= 1;
slouken@1922
   367
    }
slouken@1922
   368
    return value;
slouken@1922
   369
}
slouken@1922
   370
slouken@3433
   371
static __inline__ SDL_bool
slouken@3433
   372
convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
slouken@3433
   373
               GLint* internalFormat, GLenum* format, GLenum* type)
slouken@3433
   374
{
slouken@3433
   375
    switch (pixel_format) {
slouken@3433
   376
    case SDL_PIXELFORMAT_ARGB8888:
slouken@5156
   377
        *internalFormat = GL_RGBA8;
slouken@3433
   378
        *format = GL_BGRA;
slouken@3433
   379
        *type = GL_UNSIGNED_INT_8_8_8_8_REV;
slouken@3433
   380
        break;
slouken@5264
   381
    case SDL_PIXELFORMAT_YV12:
slouken@5264
   382
    case SDL_PIXELFORMAT_IYUV:
slouken@5264
   383
        *internalFormat = GL_LUMINANCE;
slouken@5264
   384
        *format = GL_LUMINANCE;
slouken@5264
   385
        *type = GL_UNSIGNED_BYTE;
slouken@5264
   386
        break;
slouken@3433
   387
    default:
slouken@3433
   388
        return SDL_FALSE;
slouken@3433
   389
    }
slouken@3433
   390
    return SDL_TRUE;
slouken@3433
   391
}
icculus@2835
   392
slouken@5484
   393
static GLenum
slouken@5484
   394
GetScaleQuality(void)
slouken@5484
   395
{
slouken@5484
   396
    const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
slouken@5484
   397
slouken@5484
   398
    if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
slouken@5484
   399
        return GL_NEAREST;
slouken@5484
   400
    } else {
slouken@5484
   401
        return GL_LINEAR;
slouken@5484
   402
    }
slouken@5484
   403
}
slouken@5484
   404
slouken@1918
   405
static int
slouken@1918
   406
GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1918
   407
{
slouken@1918
   408
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
   409
    GL_TextureData *data;
slouken@1920
   410
    GLint internalFormat;
slouken@1920
   411
    GLenum format, type;
slouken@1922
   412
    int texture_w, texture_h;
slouken@5503
   413
    GLenum scaleMode;
slouken@1924
   414
    GLenum result;
slouken@1918
   415
slouken@5147
   416
    GL_ActivateRenderer(renderer);
slouken@5147
   417
slouken@3433
   418
    if (!convert_format(renderdata, texture->format, &internalFormat,
slouken@3433
   419
                        &format, &type)) {
slouken@4990
   420
        SDL_SetError("Texture format %s not supported by OpenGL",
slouken@4990
   421
                     SDL_GetPixelFormatName(texture->format));
slouken@1920
   422
        return -1;
slouken@1920
   423
    }
slouken@1920
   424
slouken@1920
   425
    data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@1918
   426
    if (!data) {
slouken@1918
   427
        SDL_OutOfMemory();
slouken@1918
   428
        return -1;
slouken@1918
   429
    }
slouken@1918
   430
slouken@2222
   431
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5264
   432
        size_t size;
slouken@5156
   433
        data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
slouken@5264
   434
        size = texture->h * data->pitch;
slouken@5264
   435
        if (texture->format == SDL_PIXELFORMAT_YV12 ||
slouken@5264
   436
            texture->format == SDL_PIXELFORMAT_IYUV) {
slouken@5264
   437
            /* Need to add size for the U and V planes */
slouken@5264
   438
            size += (2 * (texture->h * data->pitch) / 4);
slouken@5264
   439
        }
slouken@5402
   440
        data->pixels = SDL_calloc(1, size);
slouken@2222
   441
        if (!data->pixels) {
slouken@2222
   442
            SDL_OutOfMemory();
slouken@2222
   443
            SDL_free(data);
slouken@2222
   444
            return -1;
slouken@2222
   445
        }
slouken@2222
   446
    }
slouken@2222
   447
slouken@1918
   448
    texture->driverdata = data;
slouken@1918
   449
slouken@1927
   450
    renderdata->glGetError();
slouken@1927
   451
    renderdata->glGenTextures(1, &data->texture);
slouken@1926
   452
    if (renderdata->GL_ARB_texture_rectangle_supported) {
slouken@1926
   453
        data->type = GL_TEXTURE_RECTANGLE_ARB;
slouken@1926
   454
        texture_w = texture->w;
slouken@1926
   455
        texture_h = texture->h;
icculus@2835
   456
        data->texw = (GLfloat) texture_w;
icculus@2835
   457
        data->texh = (GLfloat) texture_h;
slouken@1926
   458
    } else {
slouken@1926
   459
        data->type = GL_TEXTURE_2D;
slouken@1926
   460
        texture_w = power_of_2(texture->w);
slouken@1926
   461
        texture_h = power_of_2(texture->h);
icculus@2835
   462
        data->texw = (GLfloat) (texture->w) / texture_w;
slouken@1926
   463
        data->texh = (GLfloat) texture->h / texture_h;
slouken@1926
   464
    }
icculus@2835
   465
slouken@1920
   466
    data->format = format;
slouken@1920
   467
    data->formattype = type;
slouken@5503
   468
    scaleMode = GetScaleQuality();
slouken@2884
   469
    renderdata->glEnable(data->type);
slouken@1927
   470
    renderdata->glBindTexture(data->type, data->texture);
slouken@5503
   471
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode);
slouken@5503
   472
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode);
slouken@6207
   473
    /* According to the spec, CLAMP_TO_EDGE is the default for TEXTURE_RECTANGLE
slouken@6207
   474
       and setting it causes an INVALID_ENUM error in the latest NVidia drivers.
slouken@6207
   475
    */
slouken@6207
   476
    if (data->type != GL_TEXTURE_RECTANGLE_ARB) {
slouken@6207
   477
        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
slouken@6207
   478
                                    GL_CLAMP_TO_EDGE);
slouken@6207
   479
        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
slouken@6207
   480
                                    GL_CLAMP_TO_EDGE);
slouken@6207
   481
    }
slouken@2840
   482
#ifdef __MACOSX__
slouken@2230
   483
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
slouken@2230
   484
#define GL_TEXTURE_STORAGE_HINT_APPLE       0x85BC
slouken@2230
   485
#endif
slouken@2230
   486
#ifndef STORAGE_CACHED_APPLE
slouken@2230
   487
#define STORAGE_CACHED_APPLE                0x85BE
slouken@2230
   488
#endif
slouken@2230
   489
#ifndef STORAGE_SHARED_APPLE
slouken@2230
   490
#define STORAGE_SHARED_APPLE                0x85BF
slouken@2230
   491
#endif
slouken@2230
   492
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2230
   493
        renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
slouken@2230
   494
                                    GL_STORAGE_SHARED_APPLE);
slouken@2230
   495
    } else {
slouken@2230
   496
        renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
slouken@2230
   497
                                    GL_STORAGE_CACHED_APPLE);
slouken@2230
   498
    }
bob@2295
   499
    if (texture->access == SDL_TEXTUREACCESS_STREAMING
slouken@5397
   500
        && texture->format == SDL_PIXELFORMAT_ARGB8888
slouken@5397
   501
        && (texture->w % 8) == 0) {
slouken@2230
   502
        renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
slouken@5397
   503
        renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
slouken@5397
   504
        renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
slouken@5397
   505
                          (data->pitch / SDL_BYTESPERPIXEL(texture->format)));
slouken@2230
   506
        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
slouken@2230
   507
                                 texture_h, 0, format, type, data->pixels);
slouken@5397
   508
        renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
slouken@5156
   509
    }
slouken@5156
   510
    else
slouken@2809
   511
#endif
slouken@2230
   512
    {
slouken@2230
   513
        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
slouken@2230
   514
                                 texture_h, 0, format, type, NULL);
slouken@2230
   515
    }
slouken@3041
   516
    renderdata->glDisable(data->type);
slouken@1927
   517
    result = renderdata->glGetError();
slouken@1924
   518
    if (result != GL_NO_ERROR) {
slouken@1924
   519
        GL_SetError("glTexImage2D()", result);
slouken@1924
   520
        return -1;
slouken@1924
   521
    }
slouken@5264
   522
slouken@5264
   523
    if (texture->format == SDL_PIXELFORMAT_YV12 ||
slouken@5264
   524
        texture->format == SDL_PIXELFORMAT_IYUV) {
slouken@5264
   525
        data->yuv = SDL_TRUE;
slouken@5264
   526
slouken@5264
   527
        renderdata->glGenTextures(1, &data->utexture);
slouken@5264
   528
        renderdata->glGenTextures(1, &data->vtexture);
slouken@5264
   529
        renderdata->glEnable(data->type);
slouken@5264
   530
slouken@5264
   531
        renderdata->glBindTexture(data->type, data->utexture);
slouken@5503
   532
        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
slouken@5503
   533
                                    scaleMode);
slouken@5503
   534
        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
slouken@5503
   535
                                    scaleMode);
slouken@5264
   536
        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
slouken@5264
   537
                                    GL_CLAMP_TO_EDGE);
slouken@5264
   538
        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
slouken@5264
   539
                                    GL_CLAMP_TO_EDGE);
slouken@5264
   540
        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
slouken@5264
   541
                                 texture_h/2, 0, format, type, NULL);
slouken@5264
   542
slouken@5264
   543
        renderdata->glBindTexture(data->type, data->vtexture);
slouken@5503
   544
        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
slouken@5503
   545
                                    scaleMode);
slouken@5503
   546
        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
slouken@5503
   547
                                    scaleMode);
slouken@5264
   548
        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
slouken@5264
   549
                                    GL_CLAMP_TO_EDGE);
slouken@5264
   550
        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
slouken@5264
   551
                                    GL_CLAMP_TO_EDGE);
slouken@5264
   552
        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
slouken@5264
   553
                                 texture_h/2, 0, format, type, NULL);
slouken@5264
   554
slouken@5264
   555
        renderdata->glDisable(data->type);
slouken@5264
   556
    }
slouken@1918
   557
    return 0;
slouken@1918
   558
}
slouken@1918
   559
slouken@1918
   560
static int
slouken@1918
   561
GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
   562
                 const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1918
   563
{
slouken@1927
   564
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
   565
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1924
   566
    GLenum result;
slouken@1918
   567
slouken@5147
   568
    GL_ActivateRenderer(renderer);
slouken@5147
   569
slouken@1927
   570
    renderdata->glGetError();
slouken@5397
   571
    renderdata->glEnable(data->type);
slouken@5397
   572
    renderdata->glBindTexture(data->type, data->texture);
slouken@5227
   573
    renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
slouken@5227
   574
    renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
slouken@5227
   575
                              (pitch / SDL_BYTESPERPIXEL(texture->format)));
slouken@1927
   576
    renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
slouken@1927
   577
                                rect->h, data->format, data->formattype,
slouken@1927
   578
                                pixels);
slouken@5264
   579
    if (data->yuv) {
slouken@5265
   580
        renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2));
slouken@5265
   581
slouken@5264
   582
        /* Skip to the correct offset into the next texture */
slouken@6135
   583
        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
slouken@5264
   584
        if (texture->format == SDL_PIXELFORMAT_YV12) {
slouken@5264
   585
            renderdata->glBindTexture(data->type, data->vtexture);
slouken@5264
   586
        } else {
slouken@5264
   587
            renderdata->glBindTexture(data->type, data->utexture);
slouken@5264
   588
        }
slouken@5264
   589
        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
slouken@5264
   590
                                    rect->w/2, rect->h/2,
slouken@5264
   591
                                    data->format, data->formattype, pixels);
slouken@5264
   592
slouken@5264
   593
        /* Skip to the correct offset into the next texture */
slouken@6135
   594
        pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);
slouken@5264
   595
        if (texture->format == SDL_PIXELFORMAT_YV12) {
slouken@5264
   596
            renderdata->glBindTexture(data->type, data->utexture);
slouken@5264
   597
        } else {
slouken@5264
   598
            renderdata->glBindTexture(data->type, data->vtexture);
slouken@5264
   599
        }
slouken@5264
   600
        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
slouken@5264
   601
                                    rect->w/2, rect->h/2,
slouken@5264
   602
                                    data->format, data->formattype, pixels);
slouken@5264
   603
    }
slouken@3041
   604
    renderdata->glDisable(data->type);
slouken@1927
   605
    result = renderdata->glGetError();
slouken@1924
   606
    if (result != GL_NO_ERROR) {
slouken@1924
   607
        GL_SetError("glTexSubImage2D()", result);
slouken@1924
   608
        return -1;
slouken@1924
   609
    }
slouken@1918
   610
    return 0;
slouken@1918
   611
}
slouken@1918
   612
slouken@1918
   613
static int
slouken@1918
   614
GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   615
               const SDL_Rect * rect, void **pixels, int *pitch)
slouken@1918
   616
{
slouken@1918
   617
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1918
   618
slouken@5227
   619
    data->locked_rect = *rect;
slouken@5227
   620
    *pixels = 
slouken@1920
   621
        (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
slouken@5156
   622
                  rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@1920
   623
    *pitch = data->pitch;
slouken@1918
   624
    return 0;
slouken@1918
   625
}
slouken@1918
   626
slouken@1918
   627
static void
slouken@1918
   628
GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1918
   629
{
slouken@5156
   630
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@5227
   631
    const SDL_Rect *rect;
slouken@5227
   632
    void *pixels;
slouken@1918
   633
slouken@5227
   634
    rect = &data->locked_rect;
slouken@5227
   635
    pixels = 
slouken@5227
   636
        (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
slouken@5227
   637
                  rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@5227
   638
    GL_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
slouken@1918
   639
}
slouken@1918
   640
slouken@5297
   641
static int
slouken@5297
   642
GL_UpdateViewport(SDL_Renderer * renderer)
slouken@5224
   643
{
slouken@5224
   644
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@5224
   645
slouken@5297
   646
    if (SDL_CurrentContext != data->context) {
slouken@5297
   647
        /* We'll update the viewport after we rebind the context */
slouken@5297
   648
        return 0;
slouken@5297
   649
    }
slouken@5224
   650
slouken@5297
   651
    data->glViewport(renderer->viewport.x, renderer->viewport.y,
slouken@5297
   652
                     renderer->viewport.w, renderer->viewport.h);
slouken@5224
   653
slouken@5297
   654
    data->glMatrixMode(GL_PROJECTION);
slouken@5297
   655
    data->glLoadIdentity();
slouken@5297
   656
    data->glOrtho((GLdouble) 0,
slouken@5297
   657
                  (GLdouble) renderer->viewport.w,
slouken@5297
   658
                  (GLdouble) renderer->viewport.h,
slouken@5297
   659
                  (GLdouble) 0, 0.0, 1.0);
slouken@5297
   660
    return 0;
slouken@5224
   661
}
slouken@5224
   662
slouken@5224
   663
static void
slouken@5355
   664
GL_SetShader(GL_RenderData * data, GL_Shader shader)
slouken@5355
   665
{
slouken@5355
   666
    if (data->shaders && shader != data->current.shader) {
slouken@5355
   667
        GL_SelectShader(data->shaders, shader);
slouken@5355
   668
        data->current.shader = shader;
slouken@5355
   669
    }
slouken@5355
   670
}
slouken@5355
   671
slouken@5355
   672
static void
slouken@5355
   673
GL_SetColor(GL_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5355
   674
{
slouken@5355
   675
    Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
slouken@5355
   676
slouken@5355
   677
    if (color != data->current.color) {
slouken@5355
   678
        data->glColor4f((GLfloat) r * inv255f,
slouken@5355
   679
                        (GLfloat) g * inv255f,
slouken@5355
   680
                        (GLfloat) b * inv255f,
slouken@5355
   681
                        (GLfloat) a * inv255f);
slouken@5355
   682
        data->current.color = color;
slouken@5355
   683
    }
slouken@5355
   684
}
slouken@5355
   685
slouken@5355
   686
static void
slouken@5140
   687
GL_SetBlendMode(GL_RenderData * data, int blendMode)
slouken@2936
   688
{
slouken@5355
   689
    if (blendMode != data->current.blendMode) {
slouken@2936
   690
        switch (blendMode) {
slouken@2936
   691
        case SDL_BLENDMODE_NONE:
slouken@2936
   692
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
slouken@2936
   693
            data->glDisable(GL_BLEND);
slouken@2936
   694
            break;
slouken@2936
   695
        case SDL_BLENDMODE_BLEND:
slouken@2936
   696
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2936
   697
            data->glEnable(GL_BLEND);
slouken@2936
   698
            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
slouken@2936
   699
            break;
slouken@2936
   700
        case SDL_BLENDMODE_ADD:
slouken@2936
   701
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2936
   702
            data->glEnable(GL_BLEND);
slouken@2936
   703
            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
slouken@2936
   704
            break;
slouken@5184
   705
        case SDL_BLENDMODE_MOD:
slouken@5184
   706
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@5184
   707
            data->glEnable(GL_BLEND);
slouken@5184
   708
            data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
slouken@5184
   709
            break;
slouken@2936
   710
        }
slouken@5355
   711
        data->current.blendMode = blendMode;
slouken@2936
   712
    }
slouken@2936
   713
}
slouken@2936
   714
slouken@5355
   715
static void
slouken@5355
   716
GL_SetDrawingState(SDL_Renderer * renderer)
slouken@5355
   717
{
slouken@5355
   718
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@5355
   719
slouken@5355
   720
    GL_ActivateRenderer(renderer);
slouken@5355
   721
slouken@5381
   722
    GL_SetColor(data, renderer->r,
slouken@5381
   723
                      renderer->g,
slouken@5381
   724
                      renderer->b,
slouken@5381
   725
                      renderer->a);
slouken@5355
   726
slouken@5355
   727
    GL_SetBlendMode(data, renderer->blendMode);
slouken@5355
   728
slouken@5355
   729
    GL_SetShader(data, SHADER_SOLID);
slouken@5355
   730
}
slouken@5355
   731
slouken@1918
   732
static int
slouken@3596
   733
GL_RenderClear(SDL_Renderer * renderer)
slouken@3596
   734
{
slouken@3596
   735
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@3596
   736
slouken@5147
   737
    GL_ActivateRenderer(renderer);
slouken@5147
   738
slouken@3596
   739
    data->glClearColor((GLfloat) renderer->r * inv255f,
slouken@3596
   740
                       (GLfloat) renderer->g * inv255f,
slouken@3596
   741
                       (GLfloat) renderer->b * inv255f,
slouken@3596
   742
                       (GLfloat) renderer->a * inv255f);
slouken@3596
   743
slouken@3596
   744
    data->glClear(GL_COLOR_BUFFER_BIT);
slouken@3596
   745
slouken@3596
   746
    return 0;
slouken@3596
   747
}
slouken@3596
   748
slouken@3596
   749
static int
slouken@3596
   750
GL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3596
   751
                    int count)
slouken@2884
   752
{
slouken@2884
   753
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@3536
   754
    int i;
slouken@2884
   755
slouken@5355
   756
    GL_SetDrawingState(renderer);
slouken@2884
   757
slouken@2901
   758
    data->glBegin(GL_POINTS);
slouken@3536
   759
    for (i = 0; i < count; ++i) {
slouken@3536
   760
        data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
slouken@3536
   761
    }
slouken@2901
   762
    data->glEnd();
slouken@2901
   763
slouken@2901
   764
    return 0;
slouken@2901
   765
}
slouken@2901
   766
slouken@2901
   767
static int
slouken@3596
   768
GL_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3596
   769
                   int count)
slouken@2901
   770
{
slouken@2901
   771
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@3536
   772
    int i;
slouken@2901
   773
slouken@5355
   774
    GL_SetDrawingState(renderer);
slouken@2901
   775
slouken@3536
   776
    if (count > 2 && 
slouken@3536
   777
        points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
slouken@3536
   778
        data->glBegin(GL_LINE_LOOP);
slouken@3536
   779
        /* GL_LINE_LOOP takes care of the final segment */
slouken@3536
   780
        --count;
slouken@3536
   781
        for (i = 0; i < count; ++i) {
slouken@3536
   782
            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
slouken@3536
   783
        }
slouken@3536
   784
        data->glEnd();
slouken@3536
   785
    } else {
slouken@5086
   786
#if defined(__APPLE__) || defined(__WIN32__)
aschiffler@4910
   787
#else
slouken@4905
   788
        int x1, y1, x2, y2;
aschiffler@4910
   789
#endif
slouken@4905
   790
slouken@3536
   791
        data->glBegin(GL_LINE_STRIP);
slouken@3536
   792
        for (i = 0; i < count; ++i) {
slouken@3536
   793
            data->glVertex2f(0.5f + points[i].x, 0.5f + points[i].y);
slouken@3536
   794
        }
slouken@3536
   795
        data->glEnd();
slouken@3474
   796
slouken@3536
   797
        /* The line is half open, so we need one more point to complete it.
slouken@3536
   798
         * http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node47.html
slouken@3536
   799
         * If we have to, we can use vertical line and horizontal line textures
slouken@3536
   800
         * for vertical and horizontal lines, and then create custom textures
slouken@3536
   801
         * for diagonal lines and software render those.  It's terrible, but at
slouken@3536
   802
         * least it would be pixel perfect.
slouken@3536
   803
         */
slouken@3536
   804
        data->glBegin(GL_POINTS);
slouken@5086
   805
#if defined(__APPLE__) || defined(__WIN32__)
slouken@3536
   806
        /* Mac OS X and Windows seem to always leave the second point open */
slouken@3536
   807
        data->glVertex2f(0.5f + points[count-1].x, 0.5f + points[count-1].y);
slouken@3474
   808
#else
slouken@3536
   809
        /* Linux seems to leave the right-most or bottom-most point open */
slouken@4905
   810
        x1 = points[0].x;
slouken@4905
   811
        y1 = points[0].y;
slouken@4905
   812
        x2 = points[count-1].x;
slouken@4905
   813
        y2 = points[count-1].y;
slouken@3536
   814
slouken@3536
   815
        if (x1 > x2) {
slouken@3536
   816
            data->glVertex2f(0.5f + x1, 0.5f + y1);
slouken@3536
   817
        } else if (x2 > x1) {
slouken@3536
   818
            data->glVertex2f(0.5f + x2, 0.5f + y2);
slouken@3536
   819
        } else if (y1 > y2) {
slouken@3536
   820
            data->glVertex2f(0.5f + x1, 0.5f + y1);
slouken@3536
   821
        } else if (y2 > y1) {
slouken@3536
   822
            data->glVertex2f(0.5f + x2, 0.5f + y2);
slouken@3536
   823
        }
slouken@3536
   824
#endif
slouken@3536
   825
        data->glEnd();
slouken@3474
   826
    }
slouken@3455
   827
slouken@1918
   828
    return 0;
slouken@1918
   829
}
slouken@1918
   830
slouken@1918
   831
static int
slouken@5297
   832
GL_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect * rects, int count)
slouken@2925
   833
{
slouken@2925
   834
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@3536
   835
    int i;
slouken@2925
   836
slouken@5355
   837
    GL_SetDrawingState(renderer);
slouken@2936
   838
slouken@3536
   839
    for (i = 0; i < count; ++i) {
slouken@5297
   840
        const SDL_Rect *rect = &rects[i];
slouken@3536
   841
slouken@3536
   842
        data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
slouken@3536
   843
    }
slouken@2925
   844
slouken@2925
   845
    return 0;
slouken@2925
   846
}
slouken@2925
   847
slouken@2925
   848
static int
slouken@1918
   849
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
   850
              const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1918
   851
{
slouken@1918
   852
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@1918
   853
    GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
slouken@1918
   854
    int minx, miny, maxx, maxy;
slouken@1918
   855
    GLfloat minu, maxu, minv, maxv;
slouken@1918
   856
slouken@5147
   857
    GL_ActivateRenderer(renderer);
slouken@5147
   858
slouken@5355
   859
    data->glEnable(texturedata->type);
slouken@5355
   860
    if (texturedata->yuv) {
slouken@5355
   861
        data->glActiveTextureARB(GL_TEXTURE2_ARB);
slouken@5355
   862
        data->glBindTexture(texturedata->type, texturedata->vtexture);
slouken@5355
   863
slouken@5355
   864
        data->glActiveTextureARB(GL_TEXTURE1_ARB);
slouken@5355
   865
        data->glBindTexture(texturedata->type, texturedata->utexture);
slouken@5355
   866
slouken@5355
   867
        data->glActiveTextureARB(GL_TEXTURE0_ARB);
slouken@5355
   868
    }
slouken@5355
   869
    data->glBindTexture(texturedata->type, texturedata->texture);
slouken@5355
   870
slouken@5355
   871
    if (texture->modMode) {
slouken@5355
   872
        GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
slouken@5355
   873
    } else {
slouken@5355
   874
        GL_SetColor(data, 255, 255, 255, 255);
slouken@5355
   875
    }
slouken@5355
   876
slouken@5355
   877
    GL_SetBlendMode(data, texture->blendMode);
slouken@5355
   878
slouken@5355
   879
    if (texturedata->yuv) {
slouken@5355
   880
        GL_SetShader(data, SHADER_YV12);
slouken@5355
   881
    } else {
slouken@5355
   882
        GL_SetShader(data, SHADER_RGB);
slouken@5355
   883
    }
slouken@5355
   884
slouken@1918
   885
    minx = dstrect->x;
slouken@1918
   886
    miny = dstrect->y;
slouken@1918
   887
    maxx = dstrect->x + dstrect->w;
slouken@1918
   888
    maxy = dstrect->y + dstrect->h;
slouken@1918
   889
slouken@1918
   890
    minu = (GLfloat) srcrect->x / texture->w;
slouken@1920
   891
    minu *= texturedata->texw;
slouken@1918
   892
    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
slouken@1920
   893
    maxu *= texturedata->texw;
slouken@1918
   894
    minv = (GLfloat) srcrect->y / texture->h;
slouken@1920
   895
    minv *= texturedata->texh;
slouken@1918
   896
    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
slouken@1920
   897
    maxv *= texturedata->texh;
slouken@1918
   898
slouken@1927
   899
    data->glBegin(GL_TRIANGLE_STRIP);
slouken@1927
   900
    data->glTexCoord2f(minu, minv);
slouken@3472
   901
    data->glVertex2f((GLfloat) minx, (GLfloat) miny);
slouken@1927
   902
    data->glTexCoord2f(maxu, minv);
slouken@3472
   903
    data->glVertex2f((GLfloat) maxx, (GLfloat) miny);
slouken@1927
   904
    data->glTexCoord2f(minu, maxv);
slouken@3472
   905
    data->glVertex2f((GLfloat) minx, (GLfloat) maxy);
slouken@1927
   906
    data->glTexCoord2f(maxu, maxv);
slouken@3472
   907
    data->glVertex2f((GLfloat) maxx, (GLfloat) maxy);
slouken@1927
   908
    data->glEnd();
slouken@1918
   909
slouken@2884
   910
    data->glDisable(texturedata->type);
slouken@2884
   911
slouken@1918
   912
    return 0;
slouken@1918
   913
}
slouken@1918
   914
slouken@3431
   915
static int
slouken@3431
   916
GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
   917
                    Uint32 pixel_format, void * pixels, int pitch)
slouken@3431
   918
{
slouken@3433
   919
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@3685
   920
    SDL_Window *window = renderer->window;
slouken@5465
   921
    Uint32 temp_format = SDL_PIXELFORMAT_ARGB8888;
slouken@5465
   922
    void *temp_pixels;
slouken@5465
   923
    int temp_pitch;
slouken@3433
   924
    GLint internalFormat;
slouken@3433
   925
    GLenum format, type;
slouken@3435
   926
    Uint8 *src, *dst, *tmp;
slouken@5154
   927
    int w, h, length, rows;
slouken@5465
   928
    int status;
slouken@3433
   929
slouken@5147
   930
    GL_ActivateRenderer(renderer);
slouken@5147
   931
slouken@5465
   932
    temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@5465
   933
    temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@5465
   934
    if (!temp_pixels) {
slouken@5465
   935
        SDL_OutOfMemory();
slouken@3433
   936
        return -1;
slouken@3433
   937
    }
slouken@3433
   938
slouken@5465
   939
    convert_format(data, temp_format, &internalFormat, &format, &type);
slouken@5465
   940
slouken@5154
   941
    SDL_GetWindowSize(window, &w, &h);
slouken@5154
   942
slouken@3446
   943
    data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
slouken@3446
   944
    data->glPixelStorei(GL_PACK_ROW_LENGTH,
slouken@5465
   945
                        (temp_pitch / SDL_BYTESPERPIXEL(temp_format)));
slouken@3433
   946
slouken@5154
   947
    data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
slouken@5465
   948
                       format, type, temp_pixels);
slouken@3435
   949
slouken@3435
   950
    /* Flip the rows to be top-down */
slouken@5465
   951
    length = rect->w * SDL_BYTESPERPIXEL(temp_format);
slouken@5465
   952
    src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
slouken@5465
   953
    dst = (Uint8*)temp_pixels;
slouken@3435
   954
    tmp = SDL_stack_alloc(Uint8, length);
slouken@3435
   955
    rows = rect->h / 2;
slouken@3435
   956
    while (rows--) {
slouken@3435
   957
        SDL_memcpy(tmp, dst, length);
slouken@3435
   958
        SDL_memcpy(dst, src, length);
slouken@3435
   959
        SDL_memcpy(src, tmp, length);
slouken@5465
   960
        dst += temp_pitch;
slouken@5465
   961
        src -= temp_pitch;
slouken@3435
   962
    }
slouken@3435
   963
    SDL_stack_free(tmp);
slouken@3440
   964
slouken@5465
   965
    status = SDL_ConvertPixels(rect->w, rect->h,
slouken@5465
   966
                               temp_format, temp_pixels, temp_pitch,
slouken@5465
   967
                               pixel_format, pixels, pitch);
slouken@5465
   968
    SDL_free(temp_pixels);
slouken@5465
   969
slouken@5465
   970
    return status;
slouken@3431
   971
}
slouken@3431
   972
slouken@1918
   973
static void
slouken@1918
   974
GL_RenderPresent(SDL_Renderer * renderer)
slouken@1918
   975
{
slouken@5147
   976
    GL_ActivateRenderer(renderer);
slouken@5147
   977
slouken@1918
   978
    SDL_GL_SwapWindow(renderer->window);
slouken@1918
   979
}
slouken@1918
   980
slouken@1918
   981
static void
slouken@1918
   982
GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1918
   983
{
slouken@1927
   984
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
   985
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1918
   986
slouken@5147
   987
    GL_ActivateRenderer(renderer);
slouken@5147
   988
slouken@1918
   989
    if (!data) {
slouken@1918
   990
        return;
slouken@1918
   991
    }
slouken@1918
   992
    if (data->texture) {
slouken@1927
   993
        renderdata->glDeleteTextures(1, &data->texture);
slouken@1918
   994
    }
slouken@5264
   995
    if (data->yuv) {
slouken@5264
   996
        renderdata->glDeleteTextures(1, &data->utexture);
slouken@5264
   997
        renderdata->glDeleteTextures(1, &data->vtexture);
slouken@5264
   998
    }
slouken@1920
   999
    if (data->pixels) {
slouken@1920
  1000
        SDL_free(data->pixels);
slouken@1920
  1001
    }
slouken@1918
  1002
    SDL_free(data);
slouken@1918
  1003
    texture->driverdata = NULL;
slouken@1918
  1004
}
slouken@1918
  1005
slouken@1975
  1006
static void
slouken@1918
  1007
GL_DestroyRenderer(SDL_Renderer * renderer)
slouken@1918
  1008
{
slouken@1918
  1009
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@1918
  1010
slouken@1918
  1011
    if (data) {
icculus@5566
  1012
        if (data->shaders) {
icculus@5566
  1013
            GL_DestroyShaderContext(data->shaders);
icculus@5566
  1014
        }
slouken@1920
  1015
        if (data->context) {
bob@2328
  1016
            /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
slouken@1920
  1017
            SDL_GL_DeleteContext(data->context);
slouken@1918
  1018
        }
slouken@1918
  1019
        SDL_free(data);
slouken@1918
  1020
    }
slouken@1918
  1021
    SDL_free(renderer);
slouken@1918
  1022
}
slouken@1918
  1023
slouken@5226
  1024
#endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */
slouken@1918
  1025
slouken@1918
  1026
/* vi: set ts=4 sw=4 expandtab: */