src/video/SDL_renderer_gl.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 20 Dec 2008 12:00:00 +0000
changeset 2884 9dde605c7540
parent 2858 a38fcb093081
child 2893 e67f3f3bf221
permissions -rw-r--r--
Date: Fri, 19 Dec 2008 20:17:35 +0100
From: Couriersud
Subject: Re: Aw: Experience using SDL1.3 in sdlmame/Proposal for api additions

> For consistency you'd probably want:
> SDL_SetRenderDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
> SDL_SetRenderDrawBlendMode(SDL_BlendMode blendMode);
> SDL_RenderLine(int x1, int y1, int x2, int y2);
> SDL_RenderFill(SDL_Rect *rect);
>
> You probably also want to add API functions query the current state.
>

I have implemented the above api for the opengl, x11, directfb and
software renderers. I have also renamed *TEXTUREBLENDMODE* constants to
BLENDMODE*. The unix build compiles. The windows renderer still needs to
be updated, but I have no windows development machine at hand. Have a
look at the x11 renderer for a sample.

Vector games now run at 90% both on opengl and directfb in comparison to
sdlmame's own opengl renderer. The same applies to raster games.

The diff also includes

a) Changed XDrawRect to XFillRect in x11 renderer
b) A number of changes to fix blending and modulation issues in the
directfb renderer.
slouken@1918
     1
/*
slouken@1918
     2
    SDL - Simple DirectMedia Layer
slouken@2858
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@1918
     4
slouken@1918
     5
    This library is free software; you can redistribute it and/or
slouken@1918
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1918
     7
    License as published by the Free Software Foundation; either
slouken@1918
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1918
     9
slouken@1918
    10
    This library is distributed in the hope that it will be useful,
slouken@1918
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1918
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1918
    13
    Lesser General Public License for more details.
slouken@1918
    14
slouken@1918
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1918
    16
    License along with this library; if not, write to the Free Software
slouken@1918
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1918
    18
slouken@1918
    19
    Sam Lantinga
slouken@1918
    20
    slouken@libsdl.org
slouken@1918
    21
*/
slouken@1918
    22
#include "SDL_config.h"
slouken@1918
    23
slouken@1952
    24
#if SDL_VIDEO_RENDER_OGL
slouken@1920
    25
slouken@1920
    26
#include "SDL_video.h"
slouken@1920
    27
#include "SDL_opengl.h"
slouken@1920
    28
#include "SDL_sysvideo.h"
slouken@1920
    29
#include "SDL_pixels_c.h"
slouken@1920
    30
#include "SDL_rect_c.h"
slouken@1920
    31
#include "SDL_yuv_sw_c.h"
slouken@1918
    32
slouken@2246
    33
#ifdef __MACOSX__
slouken@2246
    34
#include <OpenGL/OpenGL.h>
slouken@2246
    35
#endif
slouken@2246
    36
slouken@2778
    37
slouken@1918
    38
/* OpenGL renderer implementation */
slouken@1918
    39
slouken@2230
    40
/* Details on optimizing the texture path on Mac OS X:
slouken@2230
    41
   http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html
slouken@2230
    42
*/
slouken@2230
    43
icculus@2835
    44
/* !!! FIXME: this should go in a higher level than the GL renderer. */
icculus@2835
    45
static __inline__ int
icculus@2835
    46
bytes_per_pixel(const Uint32 format)
icculus@2835
    47
{
slouken@2839
    48
    if (!SDL_ISPIXELFORMAT_FOURCC(format)) {
slouken@2839
    49
        return SDL_BYTESPERPIXEL(format);
slouken@2839
    50
    }
slouken@2839
    51
slouken@2839
    52
    /* FOURCC format */
icculus@2835
    53
    switch (format) {
slouken@2884
    54
    case SDL_PIXELFORMAT_YV12:
slouken@2884
    55
    case SDL_PIXELFORMAT_IYUV:
slouken@2884
    56
    case SDL_PIXELFORMAT_YUY2:
slouken@2884
    57
    case SDL_PIXELFORMAT_UYVY:
slouken@2884
    58
    case SDL_PIXELFORMAT_YVYU:
slouken@2884
    59
        return 2;
slouken@2884
    60
    default:
slouken@2884
    61
        return 1;               /* shouldn't ever hit this. */
icculus@2835
    62
    }
icculus@2835
    63
}
icculus@2835
    64
icculus@2835
    65
slouken@1985
    66
static const float inv255f = 1.0f / 255.0f;
slouken@1985
    67
slouken@1918
    68
static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@1923
    69
static int GL_ActivateRenderer(SDL_Renderer * renderer);
slouken@1970
    70
static int GL_DisplayModeChanged(SDL_Renderer * renderer);
slouken@1918
    71
static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@2222
    72
static int GL_QueryTexturePixels(SDL_Renderer * renderer,
slouken@2222
    73
                                 SDL_Texture * texture, void **pixels,
slouken@2222
    74
                                 int *pitch);
slouken@1918
    75
static int GL_SetTexturePalette(SDL_Renderer * renderer,
slouken@1918
    76
                                SDL_Texture * texture,
slouken@1918
    77
                                const SDL_Color * colors, int firstcolor,
slouken@1918
    78
                                int ncolors);
slouken@1918
    79
static int GL_GetTexturePalette(SDL_Renderer * renderer,
slouken@1918
    80
                                SDL_Texture * texture, SDL_Color * colors,
slouken@1918
    81
                                int firstcolor, int ncolors);
slouken@1985
    82
static int GL_SetTextureColorMod(SDL_Renderer * renderer,
slouken@1985
    83
                                 SDL_Texture * texture);
slouken@1985
    84
static int GL_SetTextureAlphaMod(SDL_Renderer * renderer,
slouken@1985
    85
                                 SDL_Texture * texture);
slouken@1985
    86
static int GL_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@1985
    87
                                  SDL_Texture * texture);
slouken@1985
    88
static int GL_SetTextureScaleMode(SDL_Renderer * renderer,
slouken@1985
    89
                                  SDL_Texture * texture);
slouken@1918
    90
static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
    91
                            const SDL_Rect * rect, const void *pixels,
slouken@1918
    92
                            int pitch);
slouken@1918
    93
static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    94
                          const SDL_Rect * rect, int markDirty, void **pixels,
slouken@1985
    95
                          int *pitch);
slouken@1918
    96
static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1918
    97
static void GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
    98
                            int numrects, const SDL_Rect * rects);
slouken@2884
    99
static int GL_SetDrawColor(SDL_Renderer * renderer);
slouken@2884
   100
static int GL_SetDrawBlendMode(SDL_Renderer * renderer);
slouken@2884
   101
static int GL_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2,
slouken@2884
   102
                         int y2);
slouken@2884
   103
static int GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect);
slouken@1918
   104
static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
   105
                         const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@2884
   106
slouken@1918
   107
static void GL_RenderPresent(SDL_Renderer * renderer);
slouken@1918
   108
static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1918
   109
static void GL_DestroyRenderer(SDL_Renderer * renderer);
slouken@1918
   110
slouken@1918
   111
slouken@1918
   112
SDL_RenderDriver GL_RenderDriver = {
slouken@1918
   113
    GL_CreateRenderer,
slouken@1918
   114
    {
slouken@1918
   115
     "opengl",
slouken@1974
   116
     (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD |
slouken@1974
   117
      SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
slouken@1985
   118
     (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
slouken@1985
   119
      SDL_TEXTUREMODULATE_ALPHA),
slouken@2884
   120
     (SDL_BLENDMODE_NONE | SDL_BLENDMODE_MASK |
slouken@2884
   121
      SDL_BLENDMODE_BLEND | SDL_BLENDMODE_ADD | SDL_BLENDMODE_MOD),
slouken@1965
   122
     (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
slouken@1965
   123
      SDL_TEXTURESCALEMODE_SLOW),
slouken@2813
   124
     15,
slouken@1918
   125
     {
slouken@1965
   126
      SDL_PIXELFORMAT_INDEX1LSB,
slouken@1965
   127
      SDL_PIXELFORMAT_INDEX1MSB,
slouken@1965
   128
      SDL_PIXELFORMAT_INDEX8,
slouken@1965
   129
      SDL_PIXELFORMAT_RGB332,
slouken@1965
   130
      SDL_PIXELFORMAT_RGB444,
slouken@1965
   131
      SDL_PIXELFORMAT_RGB555,
slouken@1965
   132
      SDL_PIXELFORMAT_ARGB4444,
slouken@1965
   133
      SDL_PIXELFORMAT_ARGB1555,
slouken@1965
   134
      SDL_PIXELFORMAT_RGB565,
slouken@1965
   135
      SDL_PIXELFORMAT_RGB24,
slouken@1965
   136
      SDL_PIXELFORMAT_BGR24,
slouken@1965
   137
      SDL_PIXELFORMAT_RGB888,
slouken@1965
   138
      SDL_PIXELFORMAT_BGR888,
slouken@1965
   139
      SDL_PIXELFORMAT_ARGB8888,
slouken@1965
   140
      SDL_PIXELFORMAT_ABGR8888,
slouken@2813
   141
      SDL_PIXELFORMAT_ARGB2101010},
slouken@1918
   142
     0,
slouken@1918
   143
     0}
slouken@1918
   144
};
slouken@1918
   145
slouken@1918
   146
typedef struct
slouken@1918
   147
{
slouken@1918
   148
    SDL_GLContext context;
slouken@2833
   149
    SDL_bool updateSize;
slouken@2233
   150
    SDL_bool GL_ARB_texture_rectangle_supported;
slouken@1974
   151
    SDL_bool GL_EXT_paletted_texture_supported;
slouken@2845
   152
    SDL_bool GL_APPLE_ycbcr_422_supported;
slouken@2845
   153
    SDL_bool GL_MESA_ycbcr_texture_supported;
icculus@2835
   154
    SDL_bool GL_ARB_fragment_program_supported;
slouken@1927
   155
    int blendMode;
slouken@1927
   156
    int scaleMode;
slouken@1927
   157
slouken@1927
   158
    /* OpenGL functions */
slouken@1927
   159
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
slouken@1927
   160
#include "SDL_glfuncs.h"
slouken@1927
   161
#undef SDL_PROC
slouken@1974
   162
slouken@1974
   163
    PFNGLCOLORTABLEEXTPROC glColorTableEXT;
slouken@2233
   164
    void (*glTextureRangeAPPLE) (GLenum target, GLsizei length,
slouken@2233
   165
                                 const GLvoid * pointer);
icculus@2835
   166
icculus@2835
   167
    PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
icculus@2835
   168
    PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
icculus@2835
   169
    PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
icculus@2835
   170
    PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
icculus@2835
   171
    PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
icculus@2835
   172
    PFNGLBINDPROGRAMARBPROC glBindProgramARB;
icculus@2835
   173
    PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
icculus@2835
   174
icculus@2835
   175
    /* (optional) fragment programs */
icculus@2835
   176
    GLuint fragment_program_UYVY;
slouken@1918
   177
} GL_RenderData;
slouken@1918
   178
slouken@1918
   179
typedef struct
slouken@1918
   180
{
slouken@1918
   181
    GLuint texture;
icculus@2835
   182
    GLuint shader;
slouken@1920
   183
    GLenum type;
slouken@1918
   184
    GLfloat texw;
slouken@1918
   185
    GLfloat texh;
slouken@1920
   186
    GLenum format;
slouken@1920
   187
    GLenum formattype;
slouken@1974
   188
    Uint8 *palette;
slouken@1918
   189
    void *pixels;
slouken@1918
   190
    int pitch;
slouken@1920
   191
    SDL_DirtyRectList dirty;
slouken@2884
   192
    int HACK_RYAN_FIXME;
slouken@1918
   193
} GL_TextureData;
slouken@1918
   194
slouken@1918
   195
slouken@1924
   196
static void
slouken@1924
   197
GL_SetError(const char *prefix, GLenum result)
slouken@1924
   198
{
slouken@1924
   199
    const char *error;
slouken@1924
   200
slouken@1924
   201
    switch (result) {
slouken@1924
   202
    case GL_NO_ERROR:
slouken@1924
   203
        error = "GL_NO_ERROR";
slouken@1924
   204
        break;
slouken@1924
   205
    case GL_INVALID_ENUM:
slouken@1924
   206
        error = "GL_INVALID_ENUM";
slouken@1924
   207
        break;
slouken@1924
   208
    case GL_INVALID_VALUE:
slouken@1924
   209
        error = "GL_INVALID_VALUE";
slouken@1924
   210
        break;
slouken@1924
   211
    case GL_INVALID_OPERATION:
slouken@1924
   212
        error = "GL_INVALID_OPERATION";
slouken@1924
   213
        break;
slouken@1924
   214
    case GL_STACK_OVERFLOW:
slouken@1924
   215
        error = "GL_STACK_OVERFLOW";
slouken@1924
   216
        break;
slouken@1924
   217
    case GL_STACK_UNDERFLOW:
slouken@1924
   218
        error = "GL_STACK_UNDERFLOW";
slouken@1924
   219
        break;
slouken@1924
   220
    case GL_OUT_OF_MEMORY:
slouken@1924
   221
        error = "GL_OUT_OF_MEMORY";
slouken@1924
   222
        break;
slouken@1924
   223
    case GL_TABLE_TOO_LARGE:
slouken@1924
   224
        error = "GL_TABLE_TOO_LARGE";
slouken@1924
   225
        break;
slouken@1924
   226
    default:
slouken@1924
   227
        error = "UNKNOWN";
slouken@1924
   228
        break;
slouken@1924
   229
    }
slouken@1924
   230
    SDL_SetError("%s: %s", prefix, error);
slouken@1924
   231
}
slouken@1924
   232
slouken@1927
   233
static int
slouken@1927
   234
GL_LoadFunctions(GL_RenderData * data)
slouken@1927
   235
{
slouken@1927
   236
#if defined(__QNXNTO__) && (_NTO_VERSION < 630)
slouken@1927
   237
#define __SDL_NOGETPROCADDR__
slouken@1927
   238
#elif defined(__MINT__)
slouken@1927
   239
#define __SDL_NOGETPROCADDR__
slouken@1927
   240
#endif
slouken@1927
   241
#ifdef __SDL_NOGETPROCADDR__
slouken@1927
   242
#define SDL_PROC(ret,func,params) data->func=func;
slouken@1927
   243
#else
slouken@1927
   244
#define SDL_PROC(ret,func,params) \
slouken@1927
   245
    do { \
slouken@1927
   246
        data->func = SDL_GL_GetProcAddress(#func); \
slouken@1927
   247
        if ( ! data->func ) { \
slouken@1927
   248
            SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
slouken@1927
   249
            return -1; \
slouken@1927
   250
        } \
slouken@1927
   251
    } while ( 0 );
slouken@1927
   252
#endif /* __SDL_NOGETPROCADDR__ */
slouken@1927
   253
slouken@1927
   254
#include "SDL_glfuncs.h"
slouken@1927
   255
#undef SDL_PROC
slouken@1927
   256
    return 0;
slouken@1927
   257
}
slouken@1927
   258
slouken@1918
   259
void
slouken@1918
   260
GL_AddRenderDriver(_THIS)
slouken@1918
   261
{
slouken@1920
   262
    if (_this->GL_CreateContext) {
slouken@1918
   263
        SDL_AddRenderDriver(0, &GL_RenderDriver);
slouken@1918
   264
    }
slouken@1918
   265
}
slouken@1918
   266
slouken@1918
   267
SDL_Renderer *
slouken@1918
   268
GL_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1918
   269
{
slouken@1918
   270
    SDL_Renderer *renderer;
slouken@1918
   271
    GL_RenderData *data;
slouken@1952
   272
    GLint value;
slouken@1974
   273
    int doublebuffer;
slouken@1918
   274
slouken@1974
   275
    /* Render directly to the window, unless we're compositing */
slouken@1974
   276
#ifndef __MACOSX__
slouken@1974
   277
    if (flags & SDL_RENDERER_SINGLEBUFFER) {
slouken@1974
   278
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
slouken@1974
   279
    }
slouken@1974
   280
#endif
slouken@1918
   281
    if (!(window->flags & SDL_WINDOW_OPENGL)) {
slouken@1928
   282
        if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) {
slouken@1924
   283
            return NULL;
slouken@1924
   284
        }
slouken@1918
   285
    }
slouken@1918
   286
slouken@1920
   287
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1918
   288
    if (!renderer) {
slouken@1918
   289
        SDL_OutOfMemory();
slouken@1918
   290
        return NULL;
slouken@1918
   291
    }
slouken@1918
   292
slouken@1920
   293
    data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1918
   294
    if (!data) {
slouken@1918
   295
        GL_DestroyRenderer(renderer);
slouken@1918
   296
        SDL_OutOfMemory();
slouken@1918
   297
        return NULL;
slouken@1918
   298
    }
slouken@1918
   299
slouken@1923
   300
    renderer->ActivateRenderer = GL_ActivateRenderer;
slouken@1970
   301
    renderer->DisplayModeChanged = GL_DisplayModeChanged;
slouken@1918
   302
    renderer->CreateTexture = GL_CreateTexture;
slouken@2222
   303
    renderer->QueryTexturePixels = GL_QueryTexturePixels;
slouken@1918
   304
    renderer->SetTexturePalette = GL_SetTexturePalette;
slouken@1918
   305
    renderer->GetTexturePalette = GL_GetTexturePalette;
slouken@1985
   306
    renderer->SetTextureColorMod = GL_SetTextureColorMod;
slouken@1985
   307
    renderer->SetTextureAlphaMod = GL_SetTextureAlphaMod;
slouken@1985
   308
    renderer->SetTextureBlendMode = GL_SetTextureBlendMode;
slouken@1985
   309
    renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
slouken@1918
   310
    renderer->UpdateTexture = GL_UpdateTexture;
slouken@1918
   311
    renderer->LockTexture = GL_LockTexture;
slouken@1918
   312
    renderer->UnlockTexture = GL_UnlockTexture;
slouken@1918
   313
    renderer->DirtyTexture = GL_DirtyTexture;
slouken@2884
   314
    renderer->SetDrawColor = GL_SetDrawColor;
slouken@2884
   315
    renderer->SetDrawBlendMode = GL_SetDrawBlendMode;
slouken@2884
   316
    renderer->RenderLine = GL_RenderLine;
slouken@1918
   317
    renderer->RenderFill = GL_RenderFill;
slouken@1918
   318
    renderer->RenderCopy = GL_RenderCopy;
slouken@1918
   319
    renderer->RenderPresent = GL_RenderPresent;
slouken@1918
   320
    renderer->DestroyTexture = GL_DestroyTexture;
slouken@1918
   321
    renderer->DestroyRenderer = GL_DestroyRenderer;
slouken@1918
   322
    renderer->info = GL_RenderDriver.info;
slouken@1918
   323
    renderer->window = window->id;
slouken@1918
   324
    renderer->driverdata = data;
slouken@1918
   325
slouken@1918
   326
    renderer->info.flags =
slouken@1965
   327
        (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED);
slouken@1918
   328
slouken@1927
   329
    if (GL_LoadFunctions(data) < 0) {
slouken@1927
   330
        GL_DestroyRenderer(renderer);
slouken@1927
   331
        return NULL;
slouken@1927
   332
    }
slouken@1927
   333
slouken@1918
   334
    data->context = SDL_GL_CreateContext(window->id);
slouken@1918
   335
    if (!data->context) {
slouken@1918
   336
        GL_DestroyRenderer(renderer);
slouken@1918
   337
        return NULL;
slouken@1918
   338
    }
slouken@1918
   339
    if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
slouken@1918
   340
        GL_DestroyRenderer(renderer);
slouken@1918
   341
        return NULL;
slouken@1918
   342
    }
slouken@2246
   343
#ifdef __MACOSX__
slouken@2246
   344
    /* Enable multi-threaded rendering */
slouken@2246
   345
    /* Disabled until Ryan finishes his VBO/PBO code...
bob@2295
   346
       CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
bob@2295
   347
     */
slouken@2246
   348
#endif
slouken@2246
   349
slouken@1965
   350
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1918
   351
        SDL_GL_SetSwapInterval(1);
slouken@1918
   352
    } else {
slouken@1918
   353
        SDL_GL_SetSwapInterval(0);
slouken@1918
   354
    }
slouken@1918
   355
    if (SDL_GL_GetSwapInterval() > 0) {
slouken@1965
   356
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1918
   357
    }
slouken@1918
   358
slouken@1974
   359
    if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) {
slouken@1974
   360
        if (!doublebuffer) {
slouken@1974
   361
            renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
slouken@1974
   362
        }
slouken@1974
   363
    }
slouken@1974
   364
slouken@1952
   365
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
slouken@1952
   366
    renderer->info.max_texture_width = value;
slouken@1952
   367
    data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
slouken@1952
   368
    renderer->info.max_texture_height = value;
slouken@1920
   369
slouken@1926
   370
    if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
slouken@1926
   371
        || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
slouken@1926
   372
        data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
slouken@1926
   373
    }
slouken@1974
   374
    if (SDL_GL_ExtensionSupported("GL_EXT_paletted_texture")) {
slouken@1974
   375
        data->GL_EXT_paletted_texture_supported = SDL_TRUE;
slouken@1974
   376
        data->glColorTableEXT =
slouken@1974
   377
            (PFNGLCOLORTABLEEXTPROC) SDL_GL_GetProcAddress("glColorTableEXT");
slouken@1974
   378
    } else {
slouken@1974
   379
        /* Don't advertise support for 8-bit indexed texture format */
slouken@1974
   380
        Uint32 i, j;
slouken@1974
   381
        SDL_RendererInfo *info = &renderer->info;
slouken@1974
   382
        for (i = 0, j = 0; i < info->num_texture_formats; ++i) {
slouken@1974
   383
            if (info->texture_formats[i] != SDL_PIXELFORMAT_INDEX8) {
slouken@1974
   384
                info->texture_formats[j++] = info->texture_formats[i];
slouken@1974
   385
            }
slouken@1974
   386
        }
slouken@1974
   387
        --info->num_texture_formats;
slouken@1974
   388
    }
slouken@2845
   389
    if (SDL_GL_ExtensionSupported("GL_APPLE_ycbcr_422")) {
slouken@2845
   390
        data->GL_APPLE_ycbcr_422_supported = SDL_TRUE;
slouken@2845
   391
    }
slouken@2845
   392
    if (SDL_GL_ExtensionSupported("GL_MESA_ycbcr_texture")) {
slouken@2845
   393
        data->GL_MESA_ycbcr_texture_supported = SDL_TRUE;
slouken@2845
   394
    }
slouken@2233
   395
    if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
slouken@2233
   396
        data->glTextureRangeAPPLE =
slouken@2233
   397
            (void (*)(GLenum, GLsizei, const GLvoid *))
slouken@2233
   398
            SDL_GL_GetProcAddress("glTextureRangeAPPLE");
slouken@2233
   399
    }
slouken@1920
   400
icculus@2835
   401
    /* we might use fragment programs for YUV data, etc. */
icculus@2835
   402
    if (SDL_GL_ExtensionSupported("GL_ARB_fragment_program")) {
icculus@2835
   403
        /* !!! FIXME: this doesn't check for errors. */
icculus@2835
   404
        /* !!! FIXME: this should really reuse the glfuncs.h stuff. */
icculus@2835
   405
        data->glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC)
icculus@2835
   406
            SDL_GL_GetProcAddress("glGetProgramivARB");
icculus@2835
   407
        data->glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC)
icculus@2835
   408
            SDL_GL_GetProcAddress("glGetProgramStringARB");
icculus@2835
   409
        data->glProgramLocalParameter4fvARB =
icculus@2835
   410
            (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)
icculus@2835
   411
            SDL_GL_GetProcAddress("glProgramLocalParameter4fvARB");
icculus@2835
   412
        data->glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)
icculus@2835
   413
            SDL_GL_GetProcAddress("glDeleteProgramsARB");
icculus@2835
   414
        data->glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)
icculus@2835
   415
            SDL_GL_GetProcAddress("glGenProgramsARB");
icculus@2835
   416
        data->glBindProgramARB = (PFNGLBINDPROGRAMARBPROC)
icculus@2835
   417
            SDL_GL_GetProcAddress("glBindProgramARB");
icculus@2835
   418
        data->glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)
icculus@2835
   419
            SDL_GL_GetProcAddress("glProgramStringARB");
icculus@2835
   420
        data->GL_ARB_fragment_program_supported = SDL_TRUE;
icculus@2835
   421
    }
icculus@2835
   422
slouken@1918
   423
    /* Set up parameters for rendering */
slouken@1927
   424
    data->blendMode = -1;
slouken@1927
   425
    data->scaleMode = -1;
slouken@1927
   426
    data->glDisable(GL_DEPTH_TEST);
slouken@1927
   427
    data->glDisable(GL_CULL_FACE);
slouken@1926
   428
    if (data->GL_ARB_texture_rectangle_supported) {
slouken@1927
   429
        data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
slouken@1926
   430
    } else {
slouken@1927
   431
        data->glEnable(GL_TEXTURE_2D);
slouken@1926
   432
    }
slouken@2833
   433
    data->updateSize = SDL_TRUE;
slouken@1918
   434
slouken@1918
   435
    return renderer;
slouken@1918
   436
}
slouken@1918
   437
slouken@2884
   438
static void
slouken@2884
   439
SetBlendMode(GL_RenderData * data, int blendMode)
slouken@2884
   440
{
slouken@2884
   441
    if (blendMode != data->blendMode) {
slouken@2884
   442
        switch (blendMode) {
slouken@2884
   443
        case SDL_BLENDMODE_NONE:
slouken@2884
   444
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
slouken@2884
   445
            data->glDisable(GL_BLEND);
slouken@2884
   446
            break;
slouken@2884
   447
        case SDL_BLENDMODE_MASK:
slouken@2884
   448
        case SDL_BLENDMODE_BLEND:
slouken@2884
   449
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2884
   450
            data->glEnable(GL_BLEND);
slouken@2884
   451
            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
slouken@2884
   452
            break;
slouken@2884
   453
        case SDL_BLENDMODE_ADD:
slouken@2884
   454
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2884
   455
            data->glEnable(GL_BLEND);
slouken@2884
   456
            data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
slouken@2884
   457
            break;
slouken@2884
   458
        case SDL_BLENDMODE_MOD:
slouken@2884
   459
            data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
slouken@2884
   460
            data->glEnable(GL_BLEND);
slouken@2884
   461
            data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
slouken@2884
   462
            break;
slouken@2884
   463
        }
slouken@2884
   464
        data->blendMode = blendMode;
slouken@2884
   465
    }
slouken@2884
   466
}
slouken@2884
   467
slouken@1923
   468
static int
slouken@1923
   469
GL_ActivateRenderer(SDL_Renderer * renderer)
slouken@1923
   470
{
slouken@1923
   471
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@1923
   472
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@1923
   473
slouken@1970
   474
    if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
slouken@1970
   475
        return -1;
slouken@1970
   476
    }
slouken@2833
   477
    if (data->updateSize) {
slouken@2836
   478
        data->glMatrixMode(GL_PROJECTION);
slouken@2836
   479
        data->glLoadIdentity();
slouken@2836
   480
        data->glMatrixMode(GL_MODELVIEW);
slouken@2836
   481
        data->glLoadIdentity();
slouken@2836
   482
        data->glViewport(0, 0, window->w, window->h);
slouken@2836
   483
        data->glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0,
slouken@2836
   484
                      0.0, 1.0);
slouken@2833
   485
        data->updateSize = SDL_FALSE;
slouken@2833
   486
    }
slouken@1970
   487
    return 0;
slouken@1970
   488
}
slouken@1970
   489
slouken@1970
   490
static int
slouken@1970
   491
GL_DisplayModeChanged(SDL_Renderer * renderer)
slouken@1970
   492
{
slouken@1970
   493
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@1970
   494
slouken@2836
   495
    /* Rebind the context to the window area and update matrices */
slouken@2836
   496
    data->updateSize = SDL_TRUE;
slouken@2836
   497
    return GL_ActivateRenderer(renderer);
slouken@1923
   498
}
slouken@1923
   499
slouken@1922
   500
static __inline__ int
slouken@1922
   501
power_of_2(int input)
slouken@1922
   502
{
slouken@1922
   503
    int value = 1;
slouken@1922
   504
slouken@1922
   505
    while (value < input) {
slouken@1922
   506
        value <<= 1;
slouken@1922
   507
    }
slouken@1922
   508
    return value;
slouken@1922
   509
}
slouken@1922
   510
icculus@2835
   511
slouken@2858
   512
//#define DEBUG_PROGRAM_COMPILE 1
icculus@2835
   513
icculus@2835
   514
static GLuint
slouken@2884
   515
compile_shader(GL_RenderData * data, GLenum shader_type, const char *_code)
icculus@2835
   516
{
icculus@2847
   517
    const int have_texture_rects = data->GL_ARB_texture_rectangle_supported;
icculus@2847
   518
    const char *replacement = have_texture_rects ? "RECT" : "2D";
icculus@2847
   519
    const size_t replacementlen = strlen(replacement);
icculus@2847
   520
    const char *token = "%TEXTURETARGET%";
icculus@2847
   521
    const size_t tokenlen = strlen(token);
icculus@2847
   522
    char *code = NULL;
icculus@2847
   523
    char *ptr = NULL;
icculus@2847
   524
    GLuint program = 0;
icculus@2847
   525
icculus@2847
   526
    /*
icculus@2847
   527
     * The TEX instruction needs a different target depending on what we use.
icculus@2847
   528
     *  To handle this, we use "%TEXTURETARGET%" and replace the string before
icculus@2847
   529
     *  compiling the shader.
icculus@2847
   530
     */
icculus@2847
   531
    code = SDL_strdup(_code);
icculus@2847
   532
    if (code == NULL)
icculus@2847
   533
        return 0;
icculus@2847
   534
slouken@2884
   535
    for (ptr = SDL_strstr(code, token); ptr; ptr = SDL_strstr(ptr + 1, token)) {
icculus@2847
   536
        memcpy(ptr, replacement, replacementlen);
slouken@2884
   537
        memmove(ptr + replacementlen, ptr + tokenlen,
slouken@2884
   538
                strlen(ptr + tokenlen) + 1);
icculus@2847
   539
    }
icculus@2847
   540
icculus@2835
   541
#if DEBUG_PROGRAM_COMPILE
icculus@2847
   542
    printf("compiling shader:\n%s\n\n", code);
icculus@2835
   543
#endif
icculus@2835
   544
slouken@2884
   545
    data->glGetError();         /* flush any existing error state. */
icculus@2835
   546
    data->glGenProgramsARB(1, &program);
icculus@2835
   547
    data->glBindProgramARB(shader_type, program);
icculus@2835
   548
    data->glProgramStringARB(shader_type, GL_PROGRAM_FORMAT_ASCII_ARB,
icculus@2847
   549
                             SDL_strlen(code), code);
icculus@2847
   550
icculus@2847
   551
    SDL_free(code);
icculus@2835
   552
slouken@2884
   553
    if (data->glGetError() == GL_INVALID_OPERATION) {
icculus@2835
   554
#if DEBUG_PROGRAM_COMPILE
icculus@2835
   555
        GLint pos = 0;
icculus@2835
   556
        const GLubyte *errstr;
icculus@2835
   557
        data->glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
icculus@2835
   558
        errstr = data->glGetString(GL_PROGRAM_ERROR_STRING_ARB);
icculus@2835
   559
        printf("program compile error at position %d: %s\n\n",
slouken@2884
   560
               (int) pos, (const char *) errstr);
icculus@2835
   561
#endif
icculus@2835
   562
        data->glBindProgramARB(shader_type, 0);
icculus@2835
   563
        data->glDeleteProgramsARB(1, &program);
icculus@2835
   564
        return 0;
icculus@2848
   565
    }
icculus@2835
   566
icculus@2835
   567
    return program;
icculus@2835
   568
}
icculus@2835
   569
icculus@2848
   570
icculus@2848
   571
/*
icculus@2848
   572
 * Fragment program that renders from UYVY textures.
icculus@2848
   573
 * The UYVY to RGB equasion is:
icculus@2848
   574
 *   R = 1.164(Y-16) + 1.596(Cr-128)
icculus@2848
   575
 *   G = 1.164(Y-16) - 0.813(Cr-128) - 0.391(Cb-128)
icculus@2848
   576
 *   B = 1.164(Y-16) + 2.018(Cb-128)
icculus@2848
   577
 * Byte layout is Cb, Y1, Cr, Y2, stored in the R, G, B, A channels.
icculus@2848
   578
 * 4 bytes == 2 pixels: Y1/Cb/Cr, Y2/Cb/Cr
icculus@2848
   579
 *
icculus@2848
   580
 * !!! FIXME: this ignores blendmodes, etc.
icculus@2848
   581
 * !!! FIXME: this could be more efficient...use a dot product for green, etc.
icculus@2848
   582
 */
slouken@2884
   583
static const char *fragment_program_UYVY_source_code = "!!ARBfp1.0\n"
icculus@2848
   584
    /* outputs... */
icculus@2835
   585
    "OUTPUT outcolor = result.color;\n"
icculus@2848
   586
    /* scratch registers... */
slouken@2884
   587
    "TEMP uyvy;\n" "TEMP luminance;\n" "TEMP work;\n"
icculus@2848
   588
    /* Halve the coordinates to grab the correct 32 bits for the fragment. */
icculus@2835
   589
    "MUL work, fragment.texcoord, { 0.5, 1.0, 1.0, 1.0 };\n"
icculus@2848
   590
    /* Sample the YUV texture. Cb, Y1, Cr, Y2, are stored in x, y, z, w. */
icculus@2847
   591
    "TEX uyvy, work, texture[0], %TEXTURETARGET%;\n"
icculus@2848
   592
    /* Do subtractions (128/255, 16/255, 128/255, 16/255) */
slouken@2846
   593
    "SUB uyvy, uyvy, { 0.501960784313726, 0.06274509803922, 0.501960784313726, 0.06274509803922 };\n"
icculus@2848
   594
    /* Choose the luminance component by texcoord. */
icculus@2848
   595
    /* !!! FIXME: laziness wins out for now... just average Y1 and Y2. */
icculus@2835
   596
    "ADD luminance, uyvy.yyyy, uyvy.wwww;\n"
icculus@2835
   597
    "MUL luminance, luminance, { 0.5, 0.5, 0.5, 0.5 };\n"
icculus@2848
   598
    /* Multiply luminance by its magic value. */
icculus@2835
   599
    "MUL luminance, luminance, { 1.164, 1.164, 1.164, 1.164 };\n"
icculus@2848
   600
    /* uyvy.xyzw becomes Cr/Cr/Cb/Cb, with multiplications. */
icculus@2835
   601
    "MUL uyvy, uyvy.zzxx, { 1.596, -0.813, 2.018, -0.391 };\n"
icculus@2848
   602
    /* Add luminance to Cr and Cb, store to RGB channels. */
icculus@2835
   603
    "ADD work.rgb, luminance, uyvy;\n"
icculus@2848
   604
    /* Do final addition for Green channel.  (!!! FIXME: this should be a DPH?) */
icculus@2835
   605
    "ADD work.g, work.g, uyvy.w;\n"
icculus@2848
   606
    /* Make sure alpha channel is fully opaque.  (!!! FIXME: blend modes!) */
icculus@2835
   607
    "MOV work.a, { 1.0 };\n"
icculus@2848
   608
    /* Store out the final fragment color... */
icculus@2835
   609
    "MOV outcolor, work;\n"
icculus@2848
   610
    /* ...and we're done! */
icculus@2835
   611
    "END\n";
icculus@2835
   612
icculus@2835
   613
slouken@1918
   614
static int
slouken@1918
   615
GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1918
   616
{
slouken@1918
   617
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
   618
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@1918
   619
    GL_TextureData *data;
slouken@1920
   620
    GLint internalFormat;
slouken@1920
   621
    GLenum format, type;
slouken@1922
   622
    int texture_w, texture_h;
icculus@2835
   623
    GLuint shader = 0;
slouken@1924
   624
    GLenum result;
slouken@1918
   625
slouken@1920
   626
    switch (texture->format) {
slouken@1965
   627
    case SDL_PIXELFORMAT_INDEX1LSB:
slouken@1965
   628
    case SDL_PIXELFORMAT_INDEX1MSB:
slouken@1920
   629
        internalFormat = GL_RGB;
slouken@1920
   630
        format = GL_COLOR_INDEX;
slouken@1920
   631
        type = GL_BITMAP;
slouken@1920
   632
        break;
slouken@1965
   633
    case SDL_PIXELFORMAT_INDEX8:
slouken@1974
   634
        if (!renderdata->GL_EXT_paletted_texture_supported) {
slouken@1974
   635
            SDL_SetError("Unsupported texture format");
slouken@1974
   636
            return -1;
slouken@1974
   637
        }
slouken@1974
   638
        internalFormat = GL_COLOR_INDEX8_EXT;
slouken@1920
   639
        format = GL_COLOR_INDEX;
slouken@1920
   640
        type = GL_UNSIGNED_BYTE;
slouken@1920
   641
        break;
slouken@1965
   642
    case SDL_PIXELFORMAT_RGB332:
slouken@1920
   643
        internalFormat = GL_R3_G3_B2;
slouken@1920
   644
        format = GL_RGB;
slouken@1920
   645
        type = GL_UNSIGNED_BYTE_3_3_2;
slouken@1920
   646
        break;
slouken@1965
   647
    case SDL_PIXELFORMAT_RGB444:
slouken@1920
   648
        internalFormat = GL_RGB4;
slouken@1920
   649
        format = GL_RGB;
slouken@1920
   650
        type = GL_UNSIGNED_SHORT_4_4_4_4;
slouken@1920
   651
        break;
slouken@1965
   652
    case SDL_PIXELFORMAT_RGB555:
slouken@1920
   653
        internalFormat = GL_RGB5;
slouken@1920
   654
        format = GL_RGB;
slouken@1920
   655
        type = GL_UNSIGNED_SHORT_5_5_5_1;
slouken@1920
   656
        break;
slouken@1965
   657
    case SDL_PIXELFORMAT_ARGB4444:
slouken@1920
   658
        internalFormat = GL_RGBA4;
slouken@1920
   659
        format = GL_BGRA;
slouken@1920
   660
        type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
slouken@1920
   661
        break;
slouken@1965
   662
    case SDL_PIXELFORMAT_ARGB1555:
slouken@1920
   663
        internalFormat = GL_RGB5_A1;
slouken@1920
   664
        format = GL_BGRA;
slouken@1920
   665
        type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
slouken@1920
   666
        break;
slouken@1965
   667
    case SDL_PIXELFORMAT_RGB565:
slouken@1920
   668
        internalFormat = GL_RGB8;
slouken@1920
   669
        format = GL_RGB;
slouken@1920
   670
        type = GL_UNSIGNED_SHORT_5_6_5;
slouken@1920
   671
        break;
slouken@1965
   672
    case SDL_PIXELFORMAT_RGB24:
slouken@1920
   673
        internalFormat = GL_RGB8;
slouken@1920
   674
        format = GL_RGB;
slouken@1920
   675
        type = GL_UNSIGNED_BYTE;
slouken@1920
   676
        break;
slouken@1965
   677
    case SDL_PIXELFORMAT_RGB888:
slouken@1920
   678
        internalFormat = GL_RGB8;
slouken@1924
   679
        format = GL_BGRA;
slouken@1924
   680
        type = GL_UNSIGNED_BYTE;
slouken@1920
   681
        break;
slouken@1965
   682
    case SDL_PIXELFORMAT_BGR24:
slouken@1920
   683
        internalFormat = GL_RGB8;
slouken@1920
   684
        format = GL_BGR;
slouken@1920
   685
        type = GL_UNSIGNED_BYTE;
slouken@1920
   686
        break;
slouken@1965
   687
    case SDL_PIXELFORMAT_BGR888:
slouken@1920
   688
        internalFormat = GL_RGB8;
slouken@1924
   689
        format = GL_RGBA;
slouken@1924
   690
        type = GL_UNSIGNED_BYTE;
slouken@1920
   691
        break;
slouken@1965
   692
    case SDL_PIXELFORMAT_ARGB8888:
slouken@2230
   693
#ifdef __MACOSX__
slouken@2230
   694
        internalFormat = GL_RGBA;
slouken@2230
   695
        format = GL_BGRA;
slouken@2230
   696
        type = GL_UNSIGNED_INT_8_8_8_8_REV;
slouken@2230
   697
#else
slouken@1920
   698
        internalFormat = GL_RGBA8;
slouken@1920
   699
        format = GL_BGRA;
slouken@1924
   700
        type = GL_UNSIGNED_BYTE;
slouken@2230
   701
#endif
slouken@1920
   702
        break;
slouken@1965
   703
    case SDL_PIXELFORMAT_ABGR8888:
slouken@1920
   704
        internalFormat = GL_RGBA8;
slouken@1920
   705
        format = GL_RGBA;
slouken@1924
   706
        type = GL_UNSIGNED_BYTE;
slouken@1920
   707
        break;
slouken@1965
   708
    case SDL_PIXELFORMAT_ARGB2101010:
slouken@1920
   709
        internalFormat = GL_RGB10_A2;
slouken@1920
   710
        format = GL_BGRA;
slouken@1920
   711
        type = GL_UNSIGNED_INT_2_10_10_10_REV;
slouken@1920
   712
        break;
slouken@2845
   713
    case SDL_PIXELFORMAT_UYVY:
slouken@2845
   714
        if (renderdata->GL_APPLE_ycbcr_422_supported) {
slouken@2845
   715
            internalFormat = GL_RGB;
slouken@2845
   716
            format = GL_YCBCR_422_APPLE;
slouken@2845
   717
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
slouken@2845
   718
            type = GL_UNSIGNED_SHORT_8_8_APPLE;
slouken@2844
   719
#else
slouken@2845
   720
            type = GL_UNSIGNED_SHORT_8_8_REV_APPLE;
slouken@2845
   721
#endif
slouken@2845
   722
        } else if (renderdata->GL_MESA_ycbcr_texture_supported) {
slouken@2845
   723
            internalFormat = GL_RGB;
slouken@2845
   724
            format = GL_YCBCR_MESA;
slouken@2845
   725
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
slouken@2845
   726
            type = GL_UNSIGNED_SHORT_8_8_MESA;
slouken@2845
   727
#else
slouken@2845
   728
            type = GL_UNSIGNED_SHORT_8_8_REV_MESA;
slouken@2845
   729
#endif
slouken@2845
   730
        } else if (renderdata->GL_ARB_fragment_program_supported) {
icculus@2835
   731
            if (renderdata->fragment_program_UYVY == 0) {
icculus@2835
   732
                renderdata->fragment_program_UYVY =
icculus@2835
   733
                    compile_shader(renderdata, GL_FRAGMENT_PROGRAM_ARB,
icculus@2835
   734
                                   fragment_program_UYVY_source_code);
icculus@2835
   735
                if (renderdata->fragment_program_UYVY == 0) {
icculus@2835
   736
                    SDL_SetError("Fragment program compile error");
icculus@2835
   737
                    return -1;
icculus@2835
   738
                }
icculus@2835
   739
            }
icculus@2835
   740
            shader = renderdata->fragment_program_UYVY;
icculus@2835
   741
            internalFormat = GL_RGBA;
icculus@2835
   742
            format = GL_RGBA;
icculus@2835
   743
            type = GL_UNSIGNED_BYTE;
icculus@2835
   744
        } else {
icculus@2835
   745
            SDL_SetError("Unsupported texture format");
icculus@2835
   746
            return -1;
icculus@2835
   747
        }
icculus@2835
   748
        break;
slouken@2845
   749
    case SDL_PIXELFORMAT_YUY2:
slouken@2845
   750
        if (renderdata->GL_APPLE_ycbcr_422_supported) {
slouken@2845
   751
            internalFormat = GL_RGB;
slouken@2845
   752
            format = GL_YCBCR_422_APPLE;
slouken@2845
   753
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
slouken@2845
   754
            type = GL_UNSIGNED_SHORT_8_8_REV_APPLE;
slouken@2845
   755
#else
slouken@2845
   756
            type = GL_UNSIGNED_SHORT_8_8_APPLE;
slouken@2844
   757
#endif
slouken@2845
   758
        } else if (renderdata->GL_MESA_ycbcr_texture_supported) {
slouken@2845
   759
            internalFormat = GL_RGB;
slouken@2845
   760
            format = GL_YCBCR_MESA;
slouken@2845
   761
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
slouken@2845
   762
            type = GL_UNSIGNED_SHORT_8_8_REV_MESA;
slouken@2845
   763
#else
slouken@2845
   764
            type = GL_UNSIGNED_SHORT_8_8_MESA;
slouken@2845
   765
#endif
slouken@2845
   766
        } else {
slouken@2845
   767
            SDL_SetError("Unsupported texture format");
slouken@2845
   768
            return -1;
slouken@2845
   769
        }
slouken@2845
   770
        break;
slouken@1920
   771
    default:
slouken@1920
   772
        SDL_SetError("Unsupported texture format");
slouken@1920
   773
        return -1;
slouken@1920
   774
    }
slouken@1920
   775
slouken@1920
   776
    data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
slouken@1918
   777
    if (!data) {
slouken@1918
   778
        SDL_OutOfMemory();
slouken@1918
   779
        return -1;
slouken@1918
   780
    }
slouken@1918
   781
icculus@2835
   782
    data->shader = shader;
icculus@2835
   783
slouken@1974
   784
    if (texture->format == SDL_PIXELFORMAT_INDEX8) {
slouken@1974
   785
        data->palette = (Uint8 *) SDL_malloc(3 * 256 * sizeof(Uint8));
slouken@1974
   786
        if (!data->palette) {
slouken@1974
   787
            SDL_OutOfMemory();
slouken@1974
   788
            SDL_free(data);
slouken@1974
   789
            return -1;
slouken@1974
   790
        }
slouken@1974
   791
        SDL_memset(data->palette, 0xFF, 3 * 256 * sizeof(Uint8));
slouken@1974
   792
    }
slouken@1974
   793
slouken@2222
   794
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
icculus@2835
   795
        data->pitch = texture->w * bytes_per_pixel(texture->format);
slouken@2222
   796
        data->pixels = SDL_malloc(texture->h * data->pitch);
slouken@2222
   797
        if (!data->pixels) {
slouken@2222
   798
            SDL_OutOfMemory();
slouken@2222
   799
            SDL_free(data);
slouken@2222
   800
            return -1;
slouken@2222
   801
        }
slouken@2222
   802
    }
slouken@2222
   803
slouken@1918
   804
    texture->driverdata = data;
slouken@1918
   805
slouken@1927
   806
    renderdata->glGetError();
slouken@1927
   807
    renderdata->glGenTextures(1, &data->texture);
slouken@1926
   808
    if (renderdata->GL_ARB_texture_rectangle_supported) {
slouken@1926
   809
        data->type = GL_TEXTURE_RECTANGLE_ARB;
slouken@1926
   810
        texture_w = texture->w;
slouken@1926
   811
        texture_h = texture->h;
icculus@2835
   812
        data->texw = (GLfloat) texture_w;
icculus@2835
   813
        data->texh = (GLfloat) texture_h;
slouken@1926
   814
    } else {
slouken@1926
   815
        data->type = GL_TEXTURE_2D;
slouken@1926
   816
        texture_w = power_of_2(texture->w);
slouken@1926
   817
        texture_h = power_of_2(texture->h);
icculus@2835
   818
        data->texw = (GLfloat) (texture->w) / texture_w;
slouken@1926
   819
        data->texh = (GLfloat) texture->h / texture_h;
slouken@1926
   820
    }
icculus@2835
   821
slouken@2839
   822
    /* YUV formats use RGBA but are really two bytes per pixel */
slouken@2839
   823
    if (internalFormat == GL_RGBA && bytes_per_pixel(texture->format) < 4) {
slouken@2884
   824
        data->HACK_RYAN_FIXME = 2;
slouken@2843
   825
    } else {
slouken@2884
   826
        data->HACK_RYAN_FIXME = 1;
slouken@2839
   827
    }
slouken@2843
   828
    texture_w /= data->HACK_RYAN_FIXME;
slouken@2839
   829
slouken@1920
   830
    data->format = format;
slouken@1920
   831
    data->formattype = type;
slouken@2884
   832
    renderdata->glEnable(data->type);
slouken@1927
   833
    renderdata->glBindTexture(data->type, data->texture);
slouken@2230
   834
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
slouken@2230
   835
                                GL_NEAREST);
slouken@2230
   836
    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
slouken@2230
   837
                                GL_NEAREST);
slouken@2230
   838
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
slouken@2230
   839
                                GL_CLAMP_TO_EDGE);
slouken@2230
   840
    renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
slouken@2230
   841
                                GL_CLAMP_TO_EDGE);
slouken@2840
   842
#ifdef __MACOSX__
slouken@2230
   843
#ifndef GL_TEXTURE_STORAGE_HINT_APPLE
slouken@2230
   844
#define GL_TEXTURE_STORAGE_HINT_APPLE       0x85BC
slouken@2230
   845
#endif
slouken@2230
   846
#ifndef STORAGE_CACHED_APPLE
slouken@2230
   847
#define STORAGE_CACHED_APPLE                0x85BE
slouken@2230
   848
#endif
slouken@2230
   849
#ifndef STORAGE_SHARED_APPLE
slouken@2230
   850
#define STORAGE_SHARED_APPLE                0x85BF
slouken@2230
   851
#endif
slouken@2230
   852
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@2230
   853
        renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
slouken@2230
   854
                                    GL_STORAGE_SHARED_APPLE);
slouken@2230
   855
    } else {
slouken@2230
   856
        renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
slouken@2230
   857
                                    GL_STORAGE_CACHED_APPLE);
slouken@2230
   858
    }
slouken@2809
   859
/* This causes a crash in testoverlay for some reason.  Apple bug? */
slouken@2809
   860
#if 0
bob@2295
   861
    if (texture->access == SDL_TEXTUREACCESS_STREAMING
bob@2295
   862
        && texture->format == SDL_PIXELFORMAT_ARGB8888) {
slouken@2237
   863
        /*
bob@2295
   864
           if (renderdata->glTextureRangeAPPLE) {
bob@2295
   865
           renderdata->glTextureRangeAPPLE(data->type,
bob@2295
   866
           texture->h * data->pitch,
bob@2295
   867
           data->pixels);
bob@2295
   868
           }
bob@2295
   869
         */
slouken@2230
   870
        renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
slouken@2230
   871
        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
slouken@2230
   872
                                 texture_h, 0, format, type, data->pixels);
slouken@2230
   873
    } else
slouken@2230
   874
#endif
slouken@2809
   875
#endif
slouken@2230
   876
    {
slouken@2230
   877
        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
slouken@2230
   878
                                 texture_h, 0, format, type, NULL);
slouken@2230
   879
    }
slouken@1927
   880
    result = renderdata->glGetError();
slouken@1924
   881
    if (result != GL_NO_ERROR) {
slouken@1924
   882
        GL_SetError("glTexImage2D()", result);
slouken@1924
   883
        return -1;
slouken@1924
   884
    }
slouken@1918
   885
    return 0;
slouken@1918
   886
}
slouken@1918
   887
slouken@1918
   888
static int
slouken@2222
   889
GL_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@2222
   890
                      void **pixels, int *pitch)
slouken@2222
   891
{
slouken@2222
   892
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@2222
   893
slouken@2222
   894
    *pixels = data->pixels;
slouken@2222
   895
    *pitch = data->pitch;
slouken@2222
   896
    return 0;
slouken@2222
   897
}
slouken@2222
   898
slouken@2222
   899
static int
slouken@1918
   900
GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
   901
                     const SDL_Color * colors, int firstcolor, int ncolors)
slouken@1918
   902
{
slouken@1918
   903
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
   904
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1974
   905
    Uint8 *palette;
slouken@1918
   906
slouken@1974
   907
    if (!data->palette) {
slouken@1974
   908
        SDL_SetError("Texture doesn't have a palette");
slouken@1974
   909
        return -1;
slouken@1974
   910
    }
slouken@1974
   911
    palette = data->palette + firstcolor * 3;
slouken@1974
   912
    while (ncolors--) {
slouken@1974
   913
        *palette++ = colors->r;
slouken@1974
   914
        *palette++ = colors->g;
slouken@1974
   915
        *palette++ = colors->b;
slouken@1974
   916
        ++colors;
slouken@1974
   917
    }
slouken@2884
   918
    renderdata->glEnable(data->type);
slouken@1974
   919
    renderdata->glBindTexture(data->type, data->texture);
slouken@1974
   920
    renderdata->glColorTableEXT(data->type, GL_RGB8, 256, GL_RGB,
slouken@1974
   921
                                GL_UNSIGNED_BYTE, data->palette);
slouken@1918
   922
    return 0;
slouken@1918
   923
}
slouken@1918
   924
slouken@1918
   925
static int
slouken@1918
   926
GL_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
   927
                     SDL_Color * colors, int firstcolor, int ncolors)
slouken@1918
   928
{
slouken@1974
   929
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
   930
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1974
   931
    Uint8 *palette;
slouken@1918
   932
slouken@1974
   933
    if (!data->palette) {
slouken@1974
   934
        SDL_SetError("Texture doesn't have a palette");
slouken@1974
   935
        return -1;
slouken@1974
   936
    }
slouken@1974
   937
    palette = data->palette + firstcolor * 3;
slouken@1974
   938
    while (ncolors--) {
slouken@1974
   939
        colors->r = *palette++;
slouken@1974
   940
        colors->g = *palette++;
slouken@1974
   941
        colors->b = *palette++;
slouken@1974
   942
        colors->unused = SDL_ALPHA_OPAQUE;
slouken@1974
   943
        ++colors;
slouken@1974
   944
    }
slouken@1918
   945
    return 0;
slouken@1918
   946
}
slouken@1918
   947
slouken@1924
   948
static void
slouken@1927
   949
SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
slouken@1927
   950
                   int pitch)
slouken@1924
   951
{
slouken@1965
   952
    if (texture->format == SDL_PIXELFORMAT_INDEX1LSB) {
slouken@1927
   953
        renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
slouken@1965
   954
    } else if (texture->format == SDL_PIXELFORMAT_INDEX1MSB) {
slouken@1927
   955
        renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
slouken@1924
   956
    }
slouken@1927
   957
    renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
slouken@2808
   958
    renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
slouken@2884
   959
                              (pitch / bytes_per_pixel(texture->format)) /
slouken@2884
   960
                              ((GL_TextureData *) texture->driverdata)->
slouken@2884
   961
                              HACK_RYAN_FIXME);
slouken@1924
   962
}
slouken@1924
   963
slouken@1918
   964
static int
slouken@1985
   965
GL_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   966
{
slouken@1986
   967
    return 0;
slouken@1985
   968
}
slouken@1985
   969
slouken@1985
   970
static int
slouken@1985
   971
GL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   972
{
slouken@1986
   973
    return 0;
slouken@1985
   974
}
slouken@1985
   975
slouken@1985
   976
static int
slouken@1985
   977
GL_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   978
{
slouken@1985
   979
    switch (texture->blendMode) {
slouken@2884
   980
    case SDL_BLENDMODE_NONE:
slouken@2884
   981
    case SDL_BLENDMODE_MASK:
slouken@2884
   982
    case SDL_BLENDMODE_BLEND:
slouken@2884
   983
    case SDL_BLENDMODE_ADD:
slouken@2884
   984
    case SDL_BLENDMODE_MOD:
slouken@1985
   985
        return 0;
slouken@1985
   986
    default:
slouken@1985
   987
        SDL_Unsupported();
slouken@2884
   988
        texture->blendMode = SDL_BLENDMODE_NONE;
slouken@1985
   989
        return -1;
slouken@1985
   990
    }
slouken@1985
   991
}
slouken@1985
   992
slouken@1985
   993
static int
slouken@1985
   994
GL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   995
{
slouken@1985
   996
    switch (texture->scaleMode) {
slouken@1985
   997
    case SDL_TEXTURESCALEMODE_NONE:
slouken@1985
   998
    case SDL_TEXTURESCALEMODE_FAST:
slouken@1985
   999
    case SDL_TEXTURESCALEMODE_SLOW:
slouken@1985
  1000
        return 0;
slouken@1985
  1001
    case SDL_TEXTURESCALEMODE_BEST:
slouken@1985
  1002
        SDL_Unsupported();
slouken@1985
  1003
        texture->scaleMode = SDL_TEXTURESCALEMODE_SLOW;
slouken@1985
  1004
        return -1;
slouken@1985
  1005
    default:
slouken@1985
  1006
        SDL_Unsupported();
slouken@1985
  1007
        texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
slouken@1985
  1008
        return -1;
slouken@1985
  1009
    }
slouken@1985
  1010
}
slouken@1985
  1011
slouken@1985
  1012
static int
slouken@1918
  1013
GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
  1014
                 const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1918
  1015
{
slouken@1927
  1016
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
  1017
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1924
  1018
    GLenum result;
slouken@1918
  1019
slouken@1927
  1020
    renderdata->glGetError();
slouken@1927
  1021
    SetupTextureUpdate(renderdata, texture, pitch);
slouken@2884
  1022
    renderdata->glEnable(data->type);
slouken@1927
  1023
    renderdata->glBindTexture(data->type, data->texture);
slouken@1927
  1024
    renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
slouken@1927
  1025
                                rect->h, data->format, data->formattype,
slouken@1927
  1026
                                pixels);
slouken@1927
  1027
    result = renderdata->glGetError();
slouken@1924
  1028
    if (result != GL_NO_ERROR) {
slouken@1924
  1029
        GL_SetError("glTexSubImage2D()", result);
slouken@1924
  1030
        return -1;
slouken@1924
  1031
    }
slouken@1918
  1032
    return 0;
slouken@1918
  1033
}
slouken@1918
  1034
slouken@1918
  1035
static int
slouken@1918
  1036
GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
  1037
               const SDL_Rect * rect, int markDirty, void **pixels,
slouken@1918
  1038
               int *pitch)
slouken@1918
  1039
{
slouken@1918
  1040
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1918
  1041
slouken@1920
  1042
    if (markDirty) {
slouken@1920
  1043
        SDL_AddDirtyRect(&data->dirty, rect);
slouken@1920
  1044
    }
slouken@1918
  1045
slouken@1920
  1046
    *pixels =
slouken@1920
  1047
        (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
icculus@2835
  1048
                  rect->x * bytes_per_pixel(texture->format));
slouken@1920
  1049
    *pitch = data->pitch;
slouken@1918
  1050
    return 0;
slouken@1918
  1051
}
slouken@1918
  1052
slouken@1918
  1053
static void
slouken@1918
  1054
GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1918
  1055
{
slouken@1918
  1056
}
slouken@1918
  1057
slouken@1918
  1058
static void
slouken@1918
  1059
GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
slouken@1918
  1060
                const SDL_Rect * rects)
slouken@1918
  1061
{
slouken@1918
  1062
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1918
  1063
    int i;
slouken@1918
  1064
slouken@1918
  1065
    for (i = 0; i < numrects; ++i) {
slouken@1920
  1066
        SDL_AddDirtyRect(&data->dirty, &rects[i]);
slouken@1918
  1067
    }
slouken@1918
  1068
}
slouken@1918
  1069
slouken@1918
  1070
static int
slouken@2884
  1071
GL_SetDrawColor(SDL_Renderer * renderer)
slouken@2884
  1072
{
slouken@2884
  1073
    return 0;
slouken@2884
  1074
}
slouken@2884
  1075
slouken@2884
  1076
static int
slouken@2884
  1077
GL_SetDrawBlendMode(SDL_Renderer * renderer)
slouken@2884
  1078
{
slouken@2884
  1079
    return 0;
slouken@2884
  1080
}
slouken@2884
  1081
slouken@2884
  1082
static int
slouken@2884
  1083
GL_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@1918
  1084
{
slouken@1918
  1085
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@1918
  1086
    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
slouken@1918
  1087
slouken@2884
  1088
    data->glColor4f((GLfloat) renderer->r * inv255f,
slouken@2884
  1089
                    (GLfloat) renderer->g * inv255f,
slouken@2884
  1090
                    (GLfloat) renderer->b * inv255f,
slouken@2884
  1091
                    (GLfloat) renderer->a * inv255f);
slouken@2884
  1092
    SetBlendMode(data, renderer->blendMode);
slouken@2884
  1093
    data->glRecti(rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
slouken@2884
  1094
slouken@2884
  1095
    return 0;
slouken@2884
  1096
}
slouken@2884
  1097
slouken@2884
  1098
static int
slouken@2884
  1099
GL_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
slouken@2884
  1100
{
slouken@2884
  1101
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@2884
  1102
    //data->glLineWidth(1.0);
slouken@2884
  1103
    //data->glPointSize(1.0);
slouken@2884
  1104
slouken@2884
  1105
    SetBlendMode(data, renderer->blendMode);
slouken@2884
  1106
slouken@2884
  1107
    data->glColor4f((GLfloat) renderer->r * inv255f,
slouken@2884
  1108
                    (GLfloat) renderer->g * inv255f,
slouken@2884
  1109
                    (GLfloat) renderer->b * inv255f,
slouken@2884
  1110
                    (GLfloat) renderer->a * inv255f);
slouken@2884
  1111
slouken@2884
  1112
    if ((x1 == x2) && (y1 == y2)) {
slouken@2884
  1113
        data->glBegin(GL_POINTS);
slouken@2884
  1114
        data->glVertex2i(x1, y1);
slouken@2884
  1115
        data->glEnd();
slouken@2884
  1116
    } else {
slouken@2884
  1117
        data->glBegin(GL_LINES);
slouken@2884
  1118
        data->glVertex2i(x1, y1);
slouken@2884
  1119
        data->glVertex2i(x2, y2);
slouken@2884
  1120
        data->glEnd();
slouken@2884
  1121
    }
slouken@1918
  1122
    return 0;
slouken@1918
  1123
}
slouken@1918
  1124
slouken@1918
  1125
static int
slouken@1918
  1126
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
  1127
              const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1918
  1128
{
slouken@1918
  1129
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@1918
  1130
    GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
slouken@1918
  1131
    int minx, miny, maxx, maxy;
slouken@1918
  1132
    GLfloat minu, maxu, minv, maxv;
slouken@1918
  1133
slouken@2275
  1134
    if (texturedata->dirty.list) {
slouken@1920
  1135
        SDL_DirtyRect *dirty;
slouken@1920
  1136
        void *pixels;
icculus@2835
  1137
        int bpp = bytes_per_pixel(texture->format);
slouken@1920
  1138
        int pitch = texturedata->pitch;
slouken@1920
  1139
slouken@1927
  1140
        SetupTextureUpdate(data, texture, pitch);
slouken@2884
  1141
        data->glEnable(texturedata->type);
slouken@1927
  1142
        data->glBindTexture(texturedata->type, texturedata->texture);
slouken@1920
  1143
        for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
slouken@1920
  1144
            SDL_Rect *rect = &dirty->rect;
slouken@1920
  1145
            pixels =
slouken@1920
  1146
                (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
slouken@1920
  1147
                          rect->x * bpp);
slouken@1927
  1148
            data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
slouken@2884
  1149
                                  rect->w / texturedata->HACK_RYAN_FIXME,
slouken@2884
  1150
                                  rect->h, texturedata->format,
slouken@1927
  1151
                                  texturedata->formattype, pixels);
slouken@1920
  1152
        }
slouken@1920
  1153
        SDL_ClearDirtyRects(&texturedata->dirty);
slouken@1920
  1154
    }
slouken@1920
  1155
slouken@1918
  1156
    minx = dstrect->x;
slouken@1918
  1157
    miny = dstrect->y;
slouken@1918
  1158
    maxx = dstrect->x + dstrect->w;
slouken@1918
  1159
    maxy = dstrect->y + dstrect->h;
slouken@1918
  1160
slouken@1918
  1161
    minu = (GLfloat) srcrect->x / texture->w;
slouken@1920
  1162
    minu *= texturedata->texw;
slouken@1918
  1163
    maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
slouken@1920
  1164
    maxu *= texturedata->texw;
slouken@1918
  1165
    minv = (GLfloat) srcrect->y / texture->h;
slouken@1920
  1166
    minv *= texturedata->texh;
slouken@1918
  1167
    maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
slouken@1920
  1168
    maxv *= texturedata->texh;
slouken@1918
  1169
slouken@2884
  1170
    data->glEnable(texturedata->type);
slouken@1927
  1171
    data->glBindTexture(texturedata->type, texturedata->texture);
slouken@1918
  1172
slouken@1985
  1173
    if (texture->modMode) {
slouken@1985
  1174
        data->glColor4f((GLfloat) texture->r * inv255f,
slouken@1985
  1175
                        (GLfloat) texture->g * inv255f,
slouken@1985
  1176
                        (GLfloat) texture->b * inv255f,
slouken@1985
  1177
                        (GLfloat) texture->a * inv255f);
slouken@1985
  1178
    } else {
slouken@1985
  1179
        data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
slouken@1985
  1180
    }
slouken@1985
  1181
slouken@2884
  1182
    SetBlendMode(data, texture->blendMode);
slouken@1918
  1183
slouken@1985
  1184
    if (texture->scaleMode != data->scaleMode) {
slouken@1985
  1185
        switch (texture->scaleMode) {
slouken@1965
  1186
        case SDL_TEXTURESCALEMODE_NONE:
slouken@1965
  1187
        case SDL_TEXTURESCALEMODE_FAST:
slouken@1927
  1188
            data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
slouken@1927
  1189
                                  GL_NEAREST);
slouken@1927
  1190
            data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
slouken@1927
  1191
                                  GL_NEAREST);
slouken@1927
  1192
            break;
slouken@1965
  1193
        case SDL_TEXTURESCALEMODE_SLOW:
slouken@1965
  1194
        case SDL_TEXTURESCALEMODE_BEST:
slouken@1927
  1195
            data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
slouken@1927
  1196
                                  GL_LINEAR);
slouken@1927
  1197
            data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
slouken@1927
  1198
                                  GL_LINEAR);
slouken@1927
  1199
            break;
slouken@1927
  1200
        }
slouken@1985
  1201
        data->scaleMode = texture->scaleMode;
slouken@1918
  1202
    }
slouken@1918
  1203
icculus@2835
  1204
    if (texturedata->shader != 0) {
icculus@2835
  1205
        data->glEnable(GL_FRAGMENT_PROGRAM_ARB);
icculus@2835
  1206
        data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, texturedata->shader);
icculus@2835
  1207
    }
icculus@2835
  1208
slouken@1927
  1209
    data->glBegin(GL_TRIANGLE_STRIP);
slouken@1927
  1210
    data->glTexCoord2f(minu, minv);
slouken@1927
  1211
    data->glVertex2i(minx, miny);
slouken@1927
  1212
    data->glTexCoord2f(maxu, minv);
slouken@1927
  1213
    data->glVertex2i(maxx, miny);
slouken@1927
  1214
    data->glTexCoord2f(minu, maxv);
slouken@1927
  1215
    data->glVertex2i(minx, maxy);
slouken@1927
  1216
    data->glTexCoord2f(maxu, maxv);
slouken@1927
  1217
    data->glVertex2i(maxx, maxy);
slouken@1927
  1218
    data->glEnd();
slouken@1918
  1219
icculus@2835
  1220
    if (texturedata->shader != 0) {
icculus@2835
  1221
        data->glDisable(GL_FRAGMENT_PROGRAM_ARB);
icculus@2835
  1222
    }
slouken@2884
  1223
slouken@2884
  1224
    data->glDisable(texturedata->type);
slouken@2884
  1225
slouken@1918
  1226
    return 0;
slouken@1918
  1227
}
slouken@1918
  1228
slouken@1918
  1229
static void
slouken@1918
  1230
GL_RenderPresent(SDL_Renderer * renderer)
slouken@1918
  1231
{
slouken@1918
  1232
    SDL_GL_SwapWindow(renderer->window);
slouken@1918
  1233
}
slouken@1918
  1234
slouken@1918
  1235
static void
slouken@1918
  1236
GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1918
  1237
{
slouken@1927
  1238
    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
slouken@1918
  1239
    GL_TextureData *data = (GL_TextureData *) texture->driverdata;
slouken@1918
  1240
slouken@1918
  1241
    if (!data) {
slouken@1918
  1242
        return;
slouken@1918
  1243
    }
slouken@1918
  1244
    if (data->texture) {
slouken@1927
  1245
        renderdata->glDeleteTextures(1, &data->texture);
slouken@1918
  1246
    }
slouken@1974
  1247
    if (data->palette) {
slouken@1974
  1248
        SDL_free(data->palette);
slouken@1974
  1249
    }
slouken@1920
  1250
    if (data->pixels) {
slouken@1920
  1251
        SDL_free(data->pixels);
slouken@1920
  1252
    }
slouken@1920
  1253
    SDL_FreeDirtyRects(&data->dirty);
slouken@1918
  1254
    SDL_free(data);
slouken@1918
  1255
    texture->driverdata = NULL;
slouken@1918
  1256
}
slouken@1918
  1257
slouken@1975
  1258
static void
slouken@1918
  1259
GL_DestroyRenderer(SDL_Renderer * renderer)
slouken@1918
  1260
{
slouken@1918
  1261
    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
slouken@1918
  1262
slouken@1918
  1263
    if (data) {
slouken@1920
  1264
        if (data->context) {
icculus@2835
  1265
            if (data->GL_ARB_fragment_program_supported) {
icculus@2835
  1266
                data->glDisable(GL_FRAGMENT_PROGRAM_ARB);
icculus@2835
  1267
                data->glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
icculus@2835
  1268
                if (data->fragment_program_UYVY != 0) {
slouken@2884
  1269
                    data->glDeleteProgramsARB(1,
slouken@2884
  1270
                                              &data->fragment_program_UYVY);
icculus@2835
  1271
                }
icculus@2835
  1272
            }
icculus@2835
  1273
bob@2328
  1274
            /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
slouken@1920
  1275
            SDL_GL_DeleteContext(data->context);
slouken@1918
  1276
        }
slouken@1918
  1277
        SDL_free(data);
slouken@1918
  1278
    }
slouken@1918
  1279
    SDL_free(renderer);
slouken@1918
  1280
}
slouken@1918
  1281
slouken@1952
  1282
#endif /* SDL_VIDEO_RENDER_OGL */
slouken@1918
  1283
slouken@1918
  1284
/* vi: set ts=4 sw=4 expandtab: */