src/render/SDL_render.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 01 Aug 2013 09:15:36 -0700
changeset 7563 c128ed448c30
parent 7511 4ce3cc948a00
child 7719 31b5f9ff36ca
child 8477 ad08f0d710f3
permissions -rw-r--r--
Fixed bug 1968 - SDL_RenderCopy stretch loses proportion on viewport boundaries for 3D renderers

driedfruit

SDL_RenderCopy clips dstrect against the viewport. Then it adjusts the
srcrect by "appropriate" amount of pixels. This amount is actually
wrong, quite a lot, because of the rounding errors introduced in the "*
factor / factor" scale.

real_srcrect.x += (deltax * real_srcrect.w) / dstrect->w;
real_srcrect.w += (deltaw * real_srcrect.w) / dstrect->w;

For example:

I have a 32 x 32 srcrect and a 64 x 64 dstrect. So far the
stretching is done perfectly, by a factor of 2.

Now, consider dstrect being clipped against the viewport, so it becomes
56 x 64. Now, the factor becomes 1.75 ! The adjustment to "srcrect"
can't handle this, cause srcrect is in integers.

And thus we now have incorrect mapping, with dstrect not being in the
right proportion to srcrect.

The problem is most evident when upscaling stuff, like displaying a 8x8
texture with a zoom of 64 or more, and moving it beyond the corners of
the screen. It *looks* really really bad.

Note: RenderCopyEX does no such clipping, and is right to do so. The fix would be to remove any such clipping from RenderCopy too. And then fix the software renderer, because it has the same fault, independently of RenderCopy.

[attached patch]
this leaves Software Renderer buggy, as it does it's own clipping later on
slouken@5154
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@5154
     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@5154
     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@5154
    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@5154
    20
*/
slouken@5154
    21
#include "SDL_config.h"
slouken@5154
    22
slouken@5154
    23
/* The SDL 2D rendering system */
slouken@5154
    24
slouken@5192
    25
#include "SDL_hints.h"
slouken@5221
    26
#include "SDL_log.h"
slouken@5154
    27
#include "SDL_render.h"
slouken@5154
    28
#include "SDL_sysrender.h"
slouken@5195
    29
#include "software/SDL_render_sw_c.h"
slouken@5154
    30
slouken@5154
    31
slouken@5528
    32
#define SDL_WINDOWRENDERDATA    "_SDL_WindowRenderData"
slouken@5528
    33
slouken@5154
    34
#define CHECK_RENDERER_MAGIC(renderer, retval) \
slouken@5154
    35
    if (!renderer || renderer->magic != &renderer_magic) { \
slouken@5154
    36
        SDL_SetError("Invalid renderer"); \
slouken@5154
    37
        return retval; \
slouken@5154
    38
    }
slouken@5154
    39
slouken@5154
    40
#define CHECK_TEXTURE_MAGIC(texture, retval) \
slouken@5154
    41
    if (!texture || texture->magic != &texture_magic) { \
slouken@5154
    42
        SDL_SetError("Invalid texture"); \
slouken@5154
    43
        return retval; \
slouken@5154
    44
    }
slouken@5154
    45
slouken@5154
    46
slouken@7109
    47
#if !SDL_RENDER_DISABLED
slouken@5154
    48
static const SDL_RenderDriver *render_drivers[] = {
slouken@5154
    49
#if SDL_VIDEO_RENDER_D3D
slouken@5154
    50
    &D3D_RenderDriver,
slouken@5154
    51
#endif
slouken@5154
    52
#if SDL_VIDEO_RENDER_OGL
slouken@5154
    53
    &GL_RenderDriver,
slouken@5154
    54
#endif
slouken@5209
    55
#if SDL_VIDEO_RENDER_OGL_ES2
slouken@5209
    56
    &GLES2_RenderDriver,
slouken@5209
    57
#endif
slouken@5154
    58
#if SDL_VIDEO_RENDER_OGL_ES
slouken@5201
    59
    &GLES_RenderDriver,
slouken@5201
    60
#endif
slouken@5199
    61
#if SDL_VIDEO_RENDER_DIRECTFB
slouken@5199
    62
    &DirectFB_RenderDriver,
slouken@5199
    63
#endif
kimonline@7009
    64
#if SDL_VIDEO_RENDER_PSP
kimonline@7009
    65
    &PSP_RenderDriver,
kimonline@7009
    66
#endif
slouken@5154
    67
    &SW_RenderDriver
slouken@7109
    68
};
slouken@5226
    69
#endif /* !SDL_RENDER_DISABLED */
slouken@7109
    70
slouken@5154
    71
static char renderer_magic;
slouken@5154
    72
static char texture_magic;
slouken@5154
    73
slouken@6530
    74
static int UpdateLogicalSize(SDL_Renderer *renderer);
slouken@6530
    75
slouken@5154
    76
int
slouken@5154
    77
SDL_GetNumRenderDrivers(void)
slouken@5154
    78
{
slouken@7109
    79
#if !SDL_RENDER_DISABLED
slouken@5154
    80
    return SDL_arraysize(render_drivers);
slouken@7109
    81
#else
slouken@7109
    82
    return 0;
slouken@7109
    83
#endif
slouken@5154
    84
}
slouken@5154
    85
slouken@5154
    86
int
slouken@5154
    87
SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
slouken@5154
    88
{
slouken@7109
    89
#if !SDL_RENDER_DISABLED
slouken@5154
    90
    if (index < 0 || index >= SDL_GetNumRenderDrivers()) {
icculus@7037
    91
        return SDL_SetError("index must be in the range of 0 - %d",
icculus@7037
    92
                            SDL_GetNumRenderDrivers() - 1);
slouken@5154
    93
    }
slouken@5154
    94
    *info = render_drivers[index]->info;
slouken@5154
    95
    return 0;
slouken@7109
    96
#else
slouken@7109
    97
    return SDL_SetError("SDL not built with rendering support");
slouken@7109
    98
#endif
slouken@5154
    99
}
slouken@5154
   100
slouken@5154
   101
static int
slouken@5154
   102
SDL_RendererEventWatch(void *userdata, SDL_Event *event)
slouken@5154
   103
{
slouken@5154
   104
    SDL_Renderer *renderer = (SDL_Renderer *)userdata;
slouken@5154
   105
slouken@5297
   106
    if (event->type == SDL_WINDOWEVENT) {
slouken@5154
   107
        SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
slouken@5154
   108
        if (window == renderer->window) {
slouken@5297
   109
            if (renderer->WindowEvent) {
slouken@5297
   110
                renderer->WindowEvent(renderer, &event->window);
slouken@5297
   111
            }
slouken@5297
   112
slouken@7240
   113
            if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
slouken@6530
   114
                if (renderer->logical_w) {
slouken@6530
   115
                    UpdateLogicalSize(renderer);
slouken@7240
   116
                } else {
slouken@7240
   117
                    /* Window was resized, reset viewport */
slouken@6528
   118
                    int w, h;
slouken@6528
   119
slouken@6260
   120
                    SDL_GetWindowSize(window, &w, &h);
slouken@6260
   121
                    if (renderer->target) {
slouken@6260
   122
                        renderer->viewport_backup.x = 0;
slouken@6260
   123
                        renderer->viewport_backup.y = 0;
slouken@6260
   124
                        renderer->viewport_backup.w = w;
slouken@6260
   125
                        renderer->viewport_backup.h = h;
slouken@6260
   126
                    } else {
slouken@6528
   127
                        renderer->viewport.x = 0;
slouken@6528
   128
                        renderer->viewport.y = 0;
slouken@6528
   129
                        renderer->viewport.w = w;
slouken@6528
   130
                        renderer->viewport.h = h;
slouken@6528
   131
                        renderer->UpdateViewport(renderer);
slouken@6260
   132
                    }
slouken@6260
   133
                }
slouken@6260
   134
            } else if (event->window.event == SDL_WINDOWEVENT_HIDDEN) {
slouken@6260
   135
                renderer->hidden = SDL_TRUE;
slouken@6260
   136
            } else if (event->window.event == SDL_WINDOWEVENT_SHOWN) {
slouken@6260
   137
                if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED)) {
slouken@6260
   138
                    renderer->hidden = SDL_FALSE;
slouken@6260
   139
                }
slouken@6060
   140
            } else if (event->window.event == SDL_WINDOWEVENT_MINIMIZED) {
slouken@6260
   141
                renderer->hidden = SDL_TRUE;
slouken@6060
   142
            } else if (event->window.event == SDL_WINDOWEVENT_RESTORED) {
slouken@6260
   143
                if (!(SDL_GetWindowFlags(window) & SDL_WINDOW_HIDDEN)) {
slouken@6260
   144
                    renderer->hidden = SDL_FALSE;
slouken@6260
   145
                }
slouken@5297
   146
            }
slouken@5154
   147
        }
slouken@6530
   148
    } else if (event->type == SDL_MOUSEMOTION) {
slouken@6530
   149
        if (renderer->logical_w) {
slouken@6530
   150
            event->motion.x -= renderer->viewport.x;
slouken@6530
   151
            event->motion.y -= renderer->viewport.y;
slouken@6530
   152
            event->motion.x = (int)(event->motion.x / renderer->scale.x);
slouken@6530
   153
            event->motion.y = (int)(event->motion.y / renderer->scale.y);
slouken@7496
   154
            if (event->motion.xrel > 0) {
slouken@7496
   155
                event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / renderer->scale.x));
slouken@7496
   156
            } else if (event->motion.xrel < 0) {
slouken@7496
   157
                event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / renderer->scale.x));
slouken@7496
   158
            }
slouken@7496
   159
            if (event->motion.yrel > 0) {
slouken@7496
   160
                event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / renderer->scale.y));
slouken@7496
   161
            } else if (event->motion.yrel < 0) {
slouken@7496
   162
                event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / renderer->scale.y));
slouken@7496
   163
            }
slouken@6530
   164
        }
slouken@6530
   165
    } else if (event->type == SDL_MOUSEBUTTONDOWN ||
slouken@6530
   166
               event->type == SDL_MOUSEBUTTONUP) {
slouken@6530
   167
        if (renderer->logical_w) {
slouken@6530
   168
            event->button.x -= renderer->viewport.x;
slouken@6530
   169
            event->button.y -= renderer->viewport.y;
slouken@6530
   170
            event->button.x = (int)(event->button.x / renderer->scale.x);
slouken@6530
   171
            event->button.y = (int)(event->button.y / renderer->scale.y);
slouken@6530
   172
        }
slouken@5154
   173
    }
slouken@5154
   174
    return 0;
slouken@5154
   175
}
slouken@5154
   176
slouken@6258
   177
int
slouken@6258
   178
SDL_CreateWindowAndRenderer(int width, int height, Uint32 window_flags,
slouken@6258
   179
                            SDL_Window **window, SDL_Renderer **renderer)
slouken@6258
   180
{
slouken@6258
   181
    *window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED,
slouken@6258
   182
                                     SDL_WINDOWPOS_UNDEFINED,
slouken@6258
   183
                                     width, height, window_flags);
slouken@6258
   184
    if (!*window) {
slouken@6258
   185
        *renderer = NULL;
slouken@6258
   186
        return -1;
slouken@6258
   187
    }
slouken@6258
   188
slouken@6258
   189
    *renderer = SDL_CreateRenderer(*window, -1, 0);
slouken@6258
   190
    if (!*renderer) {
slouken@6258
   191
        return -1;
slouken@6258
   192
    }
slouken@6258
   193
slouken@6258
   194
    return 0;
slouken@6258
   195
}
slouken@6258
   196
slouken@5154
   197
SDL_Renderer *
slouken@5154
   198
SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
slouken@5154
   199
{
slouken@7109
   200
#if !SDL_RENDER_DISABLED
slouken@5154
   201
    SDL_Renderer *renderer = NULL;
slouken@5154
   202
    int n = SDL_GetNumRenderDrivers();
slouken@5192
   203
    const char *hint;
slouken@5192
   204
slouken@5528
   205
    if (!window) {
slouken@5528
   206
        SDL_SetError("Invalid window");
slouken@5528
   207
        return NULL;
slouken@5528
   208
    }
slouken@5528
   209
slouken@5528
   210
    if (SDL_GetRenderer(window)) {
slouken@5528
   211
        SDL_SetError("Renderer already associated with window");
slouken@5528
   212
        return NULL;
slouken@5528
   213
    }
slouken@5528
   214
slouken@5192
   215
    hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
slouken@5192
   216
    if (hint) {
slouken@5192
   217
        if (*hint == '0') {
slouken@5192
   218
            flags &= ~SDL_RENDERER_PRESENTVSYNC;
slouken@5192
   219
        } else {
slouken@5192
   220
            flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@5192
   221
        }
slouken@5192
   222
    }
slouken@5154
   223
slouken@5154
   224
    if (index < 0) {
slouken@5192
   225
        hint = SDL_GetHint(SDL_HINT_RENDER_DRIVER);
slouken@5192
   226
        if (hint) {
slouken@5154
   227
            for (index = 0; index < n; ++index) {
slouken@5154
   228
                const SDL_RenderDriver *driver = render_drivers[index];
slouken@5154
   229
slouken@5192
   230
                if (SDL_strcasecmp(hint, driver->info.name) == 0) {
slouken@5154
   231
                    /* Create a new renderer instance */
slouken@5154
   232
                    renderer = driver->CreateRenderer(window, flags);
slouken@5154
   233
                    break;
slouken@5154
   234
                }
slouken@5154
   235
            }
slouken@5192
   236
        }
slouken@5192
   237
slouken@5192
   238
        if (!renderer) {
slouken@5154
   239
            for (index = 0; index < n; ++index) {
slouken@5154
   240
                const SDL_RenderDriver *driver = render_drivers[index];
slouken@5154
   241
slouken@5154
   242
                if ((driver->info.flags & flags) == flags) {
slouken@5154
   243
                    /* Create a new renderer instance */
slouken@5154
   244
                    renderer = driver->CreateRenderer(window, flags);
slouken@5154
   245
                    if (renderer) {
slouken@5154
   246
                        /* Yay, we got one! */
slouken@5154
   247
                        break;
slouken@5154
   248
                    }
slouken@5154
   249
                }
slouken@5154
   250
            }
slouken@5154
   251
        }
slouken@5154
   252
        if (index == n) {
slouken@5154
   253
            SDL_SetError("Couldn't find matching render driver");
slouken@5154
   254
            return NULL;
slouken@5154
   255
        }
slouken@5154
   256
    } else {
slouken@5154
   257
        if (index >= SDL_GetNumRenderDrivers()) {
slouken@5154
   258
            SDL_SetError("index must be -1 or in the range of 0 - %d",
slouken@5154
   259
                         SDL_GetNumRenderDrivers() - 1);
slouken@5154
   260
            return NULL;
slouken@5154
   261
        }
slouken@5154
   262
        /* Create a new renderer instance */
slouken@5154
   263
        renderer = render_drivers[index]->CreateRenderer(window, flags);
slouken@5154
   264
    }
slouken@5154
   265
slouken@5154
   266
    if (renderer) {
slouken@5154
   267
        renderer->magic = &renderer_magic;
slouken@5166
   268
        renderer->window = window;
slouken@6528
   269
        renderer->scale.x = 1.0f;
slouken@6528
   270
        renderer->scale.y = 1.0f;
slouken@5154
   271
slouken@6260
   272
        if (SDL_GetWindowFlags(window) & (SDL_WINDOW_HIDDEN|SDL_WINDOW_MINIMIZED)) {
slouken@6260
   273
            renderer->hidden = SDL_TRUE;
slouken@6060
   274
        } else {
slouken@6260
   275
            renderer->hidden = SDL_FALSE;
slouken@6060
   276
        }
slouken@6060
   277
slouken@5528
   278
        SDL_SetWindowData(window, SDL_WINDOWRENDERDATA, renderer);
slouken@5528
   279
slouken@5297
   280
        SDL_RenderSetViewport(renderer, NULL);
slouken@5297
   281
slouken@5154
   282
        SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
slouken@5221
   283
slouken@5221
   284
        SDL_LogInfo(SDL_LOG_CATEGORY_RENDER,
slouken@5221
   285
                    "Created renderer: %s", renderer->info.name);
slouken@5154
   286
    }
slouken@5154
   287
    return renderer;
slouken@7109
   288
#else
slouken@7109
   289
    SDL_SetError("SDL not built with rendering support");
slouken@7109
   290
    return NULL;
slouken@7109
   291
#endif
slouken@5154
   292
}
slouken@5154
   293
slouken@5166
   294
SDL_Renderer *
slouken@5166
   295
SDL_CreateSoftwareRenderer(SDL_Surface * surface)
slouken@5166
   296
{
slouken@5226
   297
#if !SDL_RENDER_DISABLED
slouken@5297
   298
    SDL_Renderer *renderer;
slouken@5297
   299
slouken@5297
   300
    renderer = SW_CreateRendererForSurface(surface);
slouken@5297
   301
slouken@5297
   302
    if (renderer) {
slouken@5297
   303
        renderer->magic = &renderer_magic;
slouken@6532
   304
        renderer->scale.x = 1.0f;
slouken@6532
   305
        renderer->scale.y = 1.0f;
slouken@5297
   306
slouken@5297
   307
        SDL_RenderSetViewport(renderer, NULL);
slouken@5297
   308
    }
slouken@5297
   309
    return renderer;
slouken@5226
   310
#else
slouken@5226
   311
    SDL_SetError("SDL not built with rendering support");
slouken@5226
   312
    return NULL;
slouken@5226
   313
#endif /* !SDL_RENDER_DISABLED */
slouken@5166
   314
}
slouken@5166
   315
slouken@5528
   316
SDL_Renderer *
slouken@5528
   317
SDL_GetRenderer(SDL_Window * window)
slouken@5528
   318
{
slouken@5528
   319
    return (SDL_Renderer *)SDL_GetWindowData(window, SDL_WINDOWRENDERDATA);
slouken@5528
   320
}
slouken@5528
   321
slouken@5154
   322
int
slouken@5154
   323
SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info)
slouken@5154
   324
{
slouken@5154
   325
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   326
slouken@5154
   327
    *info = renderer->info;
slouken@5154
   328
    return 0;
slouken@5154
   329
}
slouken@5154
   330
slouken@7239
   331
int
slouken@7239
   332
SDL_GetRendererOutputSize(SDL_Renderer * renderer, int *w, int *h)
slouken@7239
   333
{
slouken@7239
   334
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@7239
   335
slouken@7239
   336
    if (renderer->target) {
slouken@7239
   337
        return SDL_QueryTexture(renderer->target, NULL, NULL, w, h);
slouken@7239
   338
    } else if (renderer->window) {
slouken@7239
   339
        SDL_GetWindowSize(renderer->window, w, h);
slouken@7239
   340
        return 0;
slouken@7239
   341
    } else if (renderer->GetOutputSize) {
slouken@7239
   342
        return renderer->GetOutputSize(renderer, w, h);
slouken@7239
   343
    } else {
slouken@7239
   344
        /* This should never happen */
slouken@7239
   345
        SDL_SetError("Renderer doesn't support querying output size");
slouken@7239
   346
        return -1;
slouken@7239
   347
    }
slouken@7239
   348
}
slouken@7239
   349
slouken@5156
   350
static SDL_bool
slouken@5156
   351
IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
slouken@5156
   352
{
slouken@5156
   353
    Uint32 i;
slouken@5156
   354
slouken@5156
   355
    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
slouken@5156
   356
        if (renderer->info.texture_formats[i] == format) {
slouken@5156
   357
            return SDL_TRUE;
slouken@5156
   358
        }
slouken@5156
   359
    }
slouken@5156
   360
    return SDL_FALSE;
slouken@5156
   361
}
slouken@5156
   362
slouken@5156
   363
static Uint32
slouken@5156
   364
GetClosestSupportedFormat(SDL_Renderer * renderer, Uint32 format)
slouken@5156
   365
{
slouken@5156
   366
    Uint32 i;
slouken@5156
   367
slouken@5268
   368
    if (SDL_ISPIXELFORMAT_FOURCC(format)) {
slouken@5268
   369
        /* Look for an exact match */
slouken@5268
   370
        for (i = 0; i < renderer->info.num_texture_formats; ++i) {
slouken@5268
   371
            if (renderer->info.texture_formats[i] == format) {
slouken@5268
   372
                return renderer->info.texture_formats[i];
slouken@5268
   373
            }
slouken@5268
   374
        }
slouken@5268
   375
    } else {
slouken@5268
   376
        SDL_bool hasAlpha = SDL_ISPIXELFORMAT_ALPHA(format);
slouken@5268
   377
slouken@5268
   378
        /* We just want to match the first format that has the same channels */
slouken@5268
   379
        for (i = 0; i < renderer->info.num_texture_formats; ++i) {
slouken@5300
   380
            if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
slouken@5300
   381
                SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == hasAlpha) {
slouken@5268
   382
                return renderer->info.texture_formats[i];
slouken@5268
   383
            }
slouken@5156
   384
        }
slouken@5156
   385
    }
slouken@5156
   386
    return renderer->info.texture_formats[0];
slouken@5156
   387
}
slouken@5156
   388
slouken@5154
   389
SDL_Texture *
slouken@5154
   390
SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
slouken@5154
   391
{
slouken@5154
   392
    SDL_Texture *texture;
slouken@5154
   393
slouken@5154
   394
    CHECK_RENDERER_MAGIC(renderer, NULL);
slouken@5154
   395
slouken@5413
   396
    if (!format) {
slouken@5413
   397
        format = renderer->info.texture_formats[0];
slouken@5413
   398
    }
slouken@5156
   399
    if (SDL_ISPIXELFORMAT_INDEXED(format)) {
slouken@5156
   400
        SDL_SetError("Palettized textures are not supported");
slouken@5156
   401
        return NULL;
slouken@5156
   402
    }
slouken@5154
   403
    if (w <= 0 || h <= 0) {
slouken@5154
   404
        SDL_SetError("Texture dimensions can't be 0");
slouken@5156
   405
        return NULL;
slouken@5154
   406
    }
slouken@5154
   407
    texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
slouken@5154
   408
    if (!texture) {
slouken@5154
   409
        SDL_OutOfMemory();
slouken@5156
   410
        return NULL;
slouken@5154
   411
    }
slouken@5154
   412
    texture->magic = &texture_magic;
slouken@5154
   413
    texture->format = format;
slouken@5154
   414
    texture->access = access;
slouken@5154
   415
    texture->w = w;
slouken@5154
   416
    texture->h = h;
slouken@5154
   417
    texture->r = 255;
slouken@5154
   418
    texture->g = 255;
slouken@5154
   419
    texture->b = 255;
slouken@5154
   420
    texture->a = 255;
slouken@5154
   421
    texture->renderer = renderer;
slouken@5154
   422
    texture->next = renderer->textures;
slouken@5154
   423
    if (renderer->textures) {
slouken@5154
   424
        renderer->textures->prev = texture;
slouken@5154
   425
    }
slouken@5154
   426
    renderer->textures = texture;
slouken@5154
   427
slouken@5156
   428
    if (IsSupportedFormat(renderer, format)) {
slouken@5156
   429
        if (renderer->CreateTexture(renderer, texture) < 0) {
slouken@5156
   430
            SDL_DestroyTexture(texture);
slouken@5156
   431
            return 0;
slouken@5156
   432
        }
slouken@5156
   433
    } else {
slouken@5156
   434
        texture->native = SDL_CreateTexture(renderer,
slouken@5156
   435
                                GetClosestSupportedFormat(renderer, format),
slouken@5156
   436
                                access, w, h);
slouken@5156
   437
        if (!texture->native) {
slouken@5156
   438
            SDL_DestroyTexture(texture);
slouken@5156
   439
            return NULL;
slouken@5156
   440
        }
slouken@5156
   441
slouken@6497
   442
        /* Swap textures to have texture before texture->native in the list */
slouken@6497
   443
        texture->native->next = texture->next;
slouken@6533
   444
        if (texture->native->next) {
slouken@6533
   445
            texture->native->next->prev = texture->native;
slouken@6533
   446
        }
slouken@6497
   447
        texture->prev = texture->native->prev;
slouken@6533
   448
        if (texture->prev) {
slouken@6533
   449
            texture->prev->next = texture;
slouken@6533
   450
        }
slouken@6497
   451
        texture->native->prev = texture;
slouken@6497
   452
        texture->next = texture->native;
slouken@6497
   453
        renderer->textures = texture;
slouken@6497
   454
slouken@5156
   455
        if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@5156
   456
            texture->yuv = SDL_SW_CreateYUVTexture(format, w, h);
slouken@5156
   457
            if (!texture->yuv) {
slouken@5156
   458
                SDL_DestroyTexture(texture);
slouken@5156
   459
                return NULL;
slouken@5156
   460
            }
slouken@5156
   461
        } else if (access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5156
   462
            /* The pitch is 4 byte aligned */
slouken@5156
   463
            texture->pitch = (((w * SDL_BYTESPERPIXEL(format)) + 3) & ~3);
slouken@5342
   464
            texture->pixels = SDL_calloc(1, texture->pitch * h);
slouken@5156
   465
            if (!texture->pixels) {
slouken@5156
   466
                SDL_DestroyTexture(texture);
slouken@5156
   467
                return NULL;
slouken@5156
   468
            }
slouken@5156
   469
        }
slouken@5154
   470
    }
slouken@5154
   471
    return texture;
slouken@5154
   472
}
slouken@5154
   473
slouken@5154
   474
SDL_Texture *
slouken@5158
   475
SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface)
slouken@5154
   476
{
slouken@5158
   477
    const SDL_PixelFormat *fmt;
slouken@5158
   478
    SDL_bool needAlpha;
slouken@5158
   479
    Uint32 i;
slouken@5158
   480
    Uint32 format;
slouken@5158
   481
    SDL_Texture *texture;
slouken@5154
   482
slouken@5154
   483
    CHECK_RENDERER_MAGIC(renderer, NULL);
slouken@5154
   484
slouken@5154
   485
    if (!surface) {
slouken@5154
   486
        SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
slouken@5154
   487
        return NULL;
slouken@5154
   488
    }
slouken@5158
   489
slouken@5158
   490
    /* See what the best texture format is */
slouken@5154
   491
    fmt = surface->format;
slouken@5158
   492
    if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) {
slouken@5158
   493
        needAlpha = SDL_TRUE;
slouken@5154
   494
    } else {
slouken@5158
   495
        needAlpha = SDL_FALSE;
slouken@5158
   496
    }
slouken@5158
   497
    format = renderer->info.texture_formats[0];
slouken@5158
   498
    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
slouken@5268
   499
        if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) &&
slouken@5268
   500
            SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) {
slouken@5158
   501
            format = renderer->info.texture_formats[i];
slouken@5158
   502
            break;
slouken@5154
   503
        }
slouken@5154
   504
    }
slouken@5154
   505
slouken@5158
   506
    texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
slouken@5158
   507
                                surface->w, surface->h);
slouken@5154
   508
    if (!texture) {
slouken@5158
   509
        return NULL;
slouken@5154
   510
    }
slouken@5158
   511
slouken@5288
   512
    if (format == surface->format->format) {
slouken@5154
   513
        if (SDL_MUSTLOCK(surface)) {
slouken@5154
   514
            SDL_LockSurface(surface);
slouken@5158
   515
            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
slouken@5154
   516
            SDL_UnlockSurface(surface);
slouken@5154
   517
        } else {
slouken@5158
   518
            SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch);
slouken@5154
   519
        }
slouken@5154
   520
    } else {
slouken@5297
   521
        SDL_PixelFormat *dst_fmt;
slouken@5158
   522
        SDL_Surface *temp = NULL;
slouken@5154
   523
slouken@5154
   524
        /* Set up a destination surface for the texture update */
slouken@5297
   525
        dst_fmt = SDL_AllocFormat(format);
slouken@5297
   526
        temp = SDL_ConvertSurface(surface, dst_fmt, 0);
slouken@5297
   527
        SDL_FreeFormat(dst_fmt);
slouken@5158
   528
        if (temp) {
slouken@5158
   529
            SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch);
slouken@5158
   530
            SDL_FreeSurface(temp);
slouken@5158
   531
        } else {
slouken@5154
   532
            SDL_DestroyTexture(texture);
slouken@5158
   533
            return NULL;
slouken@5154
   534
        }
slouken@5154
   535
    }
slouken@5154
   536
slouken@5154
   537
    {
slouken@5154
   538
        Uint8 r, g, b, a;
slouken@5154
   539
        SDL_BlendMode blendMode;
slouken@5154
   540
slouken@5154
   541
        SDL_GetSurfaceColorMod(surface, &r, &g, &b);
slouken@5154
   542
        SDL_SetTextureColorMod(texture, r, g, b);
slouken@5154
   543
slouken@5154
   544
        SDL_GetSurfaceAlphaMod(surface, &a);
slouken@5154
   545
        SDL_SetTextureAlphaMod(texture, a);
slouken@5154
   546
slouken@5154
   547
        if (SDL_GetColorKey(surface, NULL) == 0) {
slouken@5154
   548
            /* We converted to a texture with alpha format */
slouken@5154
   549
            SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
slouken@5154
   550
        } else {
slouken@5154
   551
            SDL_GetSurfaceBlendMode(surface, &blendMode);
slouken@5154
   552
            SDL_SetTextureBlendMode(texture, blendMode);
slouken@5154
   553
        }
slouken@5154
   554
    }
slouken@5154
   555
    return texture;
slouken@5154
   556
}
slouken@5154
   557
slouken@5154
   558
int
slouken@5154
   559
SDL_QueryTexture(SDL_Texture * texture, Uint32 * format, int *access,
slouken@5154
   560
                 int *w, int *h)
slouken@5154
   561
{
slouken@5154
   562
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   563
slouken@5154
   564
    if (format) {
slouken@5154
   565
        *format = texture->format;
slouken@5154
   566
    }
slouken@5154
   567
    if (access) {
slouken@5154
   568
        *access = texture->access;
slouken@5154
   569
    }
slouken@5154
   570
    if (w) {
slouken@5154
   571
        *w = texture->w;
slouken@5154
   572
    }
slouken@5154
   573
    if (h) {
slouken@5154
   574
        *h = texture->h;
slouken@5154
   575
    }
slouken@5154
   576
    return 0;
slouken@5154
   577
}
slouken@5154
   578
slouken@5154
   579
int
slouken@5154
   580
SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
slouken@5154
   581
{
slouken@5154
   582
    SDL_Renderer *renderer;
slouken@5154
   583
slouken@5154
   584
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   585
slouken@5154
   586
    renderer = texture->renderer;
slouken@5154
   587
    if (r < 255 || g < 255 || b < 255) {
slouken@5154
   588
        texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
slouken@5154
   589
    } else {
slouken@5154
   590
        texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
slouken@5154
   591
    }
slouken@5154
   592
    texture->r = r;
slouken@5154
   593
    texture->g = g;
slouken@5154
   594
    texture->b = b;
slouken@5156
   595
    if (texture->native) {
slouken@5156
   596
        return SDL_SetTextureColorMod(texture->native, r, g, b);
slouken@5156
   597
    } else if (renderer->SetTextureColorMod) {
slouken@5154
   598
        return renderer->SetTextureColorMod(renderer, texture);
slouken@5154
   599
    } else {
slouken@5154
   600
        return 0;
slouken@5154
   601
    }
slouken@5154
   602
}
slouken@5154
   603
slouken@5154
   604
int
slouken@5154
   605
SDL_GetTextureColorMod(SDL_Texture * texture, Uint8 * r, Uint8 * g,
slouken@5154
   606
                       Uint8 * b)
slouken@5154
   607
{
slouken@5154
   608
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   609
slouken@5154
   610
    if (r) {
slouken@5154
   611
        *r = texture->r;
slouken@5154
   612
    }
slouken@5154
   613
    if (g) {
slouken@5154
   614
        *g = texture->g;
slouken@5154
   615
    }
slouken@5154
   616
    if (b) {
slouken@5154
   617
        *b = texture->b;
slouken@5154
   618
    }
slouken@5154
   619
    return 0;
slouken@5154
   620
}
slouken@5154
   621
slouken@5154
   622
int
slouken@5154
   623
SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha)
slouken@5154
   624
{
slouken@5154
   625
    SDL_Renderer *renderer;
slouken@5154
   626
slouken@5154
   627
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   628
slouken@5154
   629
    renderer = texture->renderer;
slouken@5154
   630
    if (alpha < 255) {
slouken@5154
   631
        texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
slouken@5154
   632
    } else {
slouken@5154
   633
        texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
slouken@5154
   634
    }
slouken@5154
   635
    texture->a = alpha;
slouken@5156
   636
    if (texture->native) {
slouken@5156
   637
        return SDL_SetTextureAlphaMod(texture->native, alpha);
slouken@5156
   638
    } else if (renderer->SetTextureAlphaMod) {
slouken@5154
   639
        return renderer->SetTextureAlphaMod(renderer, texture);
slouken@5154
   640
    } else {
slouken@5154
   641
        return 0;
slouken@5154
   642
    }
slouken@5154
   643
}
slouken@5154
   644
slouken@5154
   645
int
slouken@5154
   646
SDL_GetTextureAlphaMod(SDL_Texture * texture, Uint8 * alpha)
slouken@5154
   647
{
slouken@5154
   648
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   649
slouken@5154
   650
    if (alpha) {
slouken@5154
   651
        *alpha = texture->a;
slouken@5154
   652
    }
slouken@5154
   653
    return 0;
slouken@5154
   654
}
slouken@5154
   655
slouken@5154
   656
int
slouken@5154
   657
SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode)
slouken@5154
   658
{
slouken@5154
   659
    SDL_Renderer *renderer;
slouken@5154
   660
slouken@5154
   661
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   662
slouken@5154
   663
    renderer = texture->renderer;
slouken@5154
   664
    texture->blendMode = blendMode;
slouken@5156
   665
    if (texture->native) {
slouken@5180
   666
        return SDL_SetTextureBlendMode(texture->native, blendMode);
slouken@5156
   667
    } else if (renderer->SetTextureBlendMode) {
slouken@5154
   668
        return renderer->SetTextureBlendMode(renderer, texture);
slouken@5154
   669
    } else {
slouken@5154
   670
        return 0;
slouken@5154
   671
    }
slouken@5154
   672
}
slouken@5154
   673
slouken@5154
   674
int
slouken@5154
   675
SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode)
slouken@5154
   676
{
slouken@5154
   677
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   678
slouken@5154
   679
    if (blendMode) {
slouken@5154
   680
        *blendMode = texture->blendMode;
slouken@5154
   681
    }
slouken@5154
   682
    return 0;
slouken@5154
   683
}
slouken@5154
   684
slouken@5156
   685
static int
slouken@5156
   686
SDL_UpdateTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   687
                     const void *pixels, int pitch)
slouken@5156
   688
{
slouken@5156
   689
    SDL_Texture *native = texture->native;
slouken@5156
   690
    SDL_Rect full_rect;
slouken@5156
   691
slouken@5156
   692
    if (SDL_SW_UpdateYUVTexture(texture->yuv, rect, pixels, pitch) < 0) {
slouken@5156
   693
        return -1;
slouken@5156
   694
    }
slouken@5156
   695
slouken@5156
   696
    full_rect.x = 0;
slouken@5156
   697
    full_rect.y = 0;
slouken@5156
   698
    full_rect.w = texture->w;
slouken@5156
   699
    full_rect.h = texture->h;
slouken@5156
   700
    rect = &full_rect;
slouken@5156
   701
slouken@5156
   702
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5156
   703
        /* We can lock the texture and copy to it */
slouken@5156
   704
        void *native_pixels;
slouken@5156
   705
        int native_pitch;
slouken@5156
   706
slouken@5156
   707
        if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   708
            return -1;
slouken@5156
   709
        }
slouken@5156
   710
        SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
slouken@5156
   711
                            rect->w, rect->h, native_pixels, native_pitch);
slouken@5156
   712
        SDL_UnlockTexture(native);
slouken@5156
   713
    } else {
slouken@5156
   714
        /* Use a temporary buffer for updating */
slouken@5156
   715
        void *temp_pixels;
slouken@5156
   716
        int temp_pitch;
slouken@5156
   717
slouken@5156
   718
        temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
slouken@5156
   719
        temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@5156
   720
        if (!temp_pixels) {
icculus@7037
   721
            return SDL_OutOfMemory();
slouken@5156
   722
        }
slouken@5156
   723
        SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
slouken@5156
   724
                            rect->w, rect->h, temp_pixels, temp_pitch);
slouken@5156
   725
        SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
slouken@5156
   726
        SDL_free(temp_pixels);
slouken@5156
   727
    }
slouken@5156
   728
    return 0;
slouken@5156
   729
}
slouken@5156
   730
slouken@5156
   731
static int
slouken@5156
   732
SDL_UpdateTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   733
                        const void *pixels, int pitch)
slouken@5156
   734
{
slouken@5156
   735
    SDL_Texture *native = texture->native;
slouken@5156
   736
slouken@5156
   737
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5156
   738
        /* We can lock the texture and copy to it */
slouken@5156
   739
        void *native_pixels;
slouken@5156
   740
        int native_pitch;
slouken@5156
   741
slouken@5156
   742
        if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   743
            return -1;
slouken@5156
   744
        }
slouken@5156
   745
        SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
   746
                          texture->format, pixels, pitch,
slouken@5156
   747
                          native->format, native_pixels, native_pitch);
slouken@5156
   748
        SDL_UnlockTexture(native);
slouken@5156
   749
    } else {
slouken@5156
   750
        /* Use a temporary buffer for updating */
slouken@5156
   751
        void *temp_pixels;
slouken@5156
   752
        int temp_pitch;
slouken@5156
   753
slouken@5156
   754
        temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
slouken@5156
   755
        temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@5156
   756
        if (!temp_pixels) {
icculus@7037
   757
            return SDL_OutOfMemory();
slouken@5156
   758
        }
slouken@5156
   759
        SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
   760
                          texture->format, pixels, pitch,
slouken@5156
   761
                          native->format, temp_pixels, temp_pitch);
slouken@5156
   762
        SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
slouken@5156
   763
        SDL_free(temp_pixels);
slouken@5156
   764
    }
slouken@5156
   765
    return 0;
slouken@5156
   766
}
slouken@5156
   767
slouken@5154
   768
int
slouken@5154
   769
SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5154
   770
                  const void *pixels, int pitch)
slouken@5154
   771
{
slouken@5154
   772
    SDL_Renderer *renderer;
slouken@5154
   773
    SDL_Rect full_rect;
slouken@5154
   774
slouken@5154
   775
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   776
slouken@7409
   777
    if (!pixels) {
slouken@7409
   778
        return SDL_InvalidParamError("pixels");
slouken@7409
   779
    }
slouken@7409
   780
    if (!pitch) {
slouken@7409
   781
        return SDL_InvalidParamError("pitch");
slouken@7409
   782
    }
slouken@7409
   783
slouken@5154
   784
    if (!rect) {
slouken@5154
   785
        full_rect.x = 0;
slouken@5154
   786
        full_rect.y = 0;
slouken@5154
   787
        full_rect.w = texture->w;
slouken@5154
   788
        full_rect.h = texture->h;
slouken@5154
   789
        rect = &full_rect;
slouken@5154
   790
    }
slouken@5156
   791
slouken@5156
   792
    if (texture->yuv) {
slouken@5156
   793
        return SDL_UpdateTextureYUV(texture, rect, pixels, pitch);
slouken@5156
   794
    } else if (texture->native) {
slouken@5156
   795
        return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
slouken@5156
   796
    } else {
slouken@5156
   797
        renderer = texture->renderer;
slouken@5156
   798
        return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
slouken@5156
   799
    }
slouken@5156
   800
}
slouken@5156
   801
slouken@5156
   802
static int
slouken@5156
   803
SDL_LockTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   804
                   void **pixels, int *pitch)
slouken@5156
   805
{
slouken@5156
   806
    return SDL_SW_LockYUVTexture(texture->yuv, rect, pixels, pitch);
slouken@5156
   807
}
slouken@5156
   808
slouken@5156
   809
static int
slouken@5156
   810
SDL_LockTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   811
                      void **pixels, int *pitch)
slouken@5156
   812
{
slouken@5156
   813
    texture->locked_rect = *rect;
slouken@5156
   814
    *pixels = (void *) ((Uint8 *) texture->pixels +
slouken@5156
   815
                        rect->y * texture->pitch +
slouken@5156
   816
                        rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@5156
   817
    *pitch = texture->pitch;
slouken@5156
   818
    return 0;
slouken@5154
   819
}
slouken@5154
   820
slouken@5154
   821
int
slouken@5156
   822
SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5154
   823
                void **pixels, int *pitch)
slouken@5154
   824
{
slouken@5154
   825
    SDL_Renderer *renderer;
slouken@5154
   826
    SDL_Rect full_rect;
slouken@5154
   827
slouken@5154
   828
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   829
slouken@5154
   830
    if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
icculus@7037
   831
        return SDL_SetError("SDL_LockTexture(): texture must be streaming");
slouken@5154
   832
    }
slouken@5156
   833
slouken@5154
   834
    if (!rect) {
slouken@5154
   835
        full_rect.x = 0;
slouken@5154
   836
        full_rect.y = 0;
slouken@5154
   837
        full_rect.w = texture->w;
slouken@5154
   838
        full_rect.h = texture->h;
slouken@5154
   839
        rect = &full_rect;
slouken@5154
   840
    }
slouken@5156
   841
slouken@5156
   842
    if (texture->yuv) {
slouken@5156
   843
        return SDL_LockTextureYUV(texture, rect, pixels, pitch);
slouken@5156
   844
    } else if (texture->native) {
slouken@5156
   845
        return SDL_LockTextureNative(texture, rect, pixels, pitch);
slouken@5156
   846
    } else {
slouken@5156
   847
        renderer = texture->renderer;
slouken@5156
   848
        return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
slouken@5156
   849
    }
slouken@5156
   850
}
slouken@5156
   851
slouken@5156
   852
static void
slouken@5156
   853
SDL_UnlockTextureYUV(SDL_Texture * texture)
slouken@5156
   854
{
slouken@5156
   855
    SDL_Texture *native = texture->native;
slouken@5156
   856
    void *native_pixels;
slouken@5156
   857
    int native_pitch;
slouken@5156
   858
    SDL_Rect rect;
slouken@5156
   859
slouken@5156
   860
    rect.x = 0;
slouken@5156
   861
    rect.y = 0;
slouken@5156
   862
    rect.w = texture->w;
slouken@5156
   863
    rect.h = texture->h;
slouken@5156
   864
slouken@5156
   865
    if (SDL_LockTexture(native, &rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   866
        return;
slouken@5156
   867
    }
slouken@5156
   868
    SDL_SW_CopyYUVToRGB(texture->yuv, &rect, native->format,
slouken@5156
   869
                        rect.w, rect.h, native_pixels, native_pitch);
slouken@5156
   870
    SDL_UnlockTexture(native);
slouken@5156
   871
}
slouken@5156
   872
slouken@6044
   873
static void
slouken@5156
   874
SDL_UnlockTextureNative(SDL_Texture * texture)
slouken@5156
   875
{
slouken@5156
   876
    SDL_Texture *native = texture->native;
slouken@5156
   877
    void *native_pixels;
slouken@5156
   878
    int native_pitch;
slouken@5156
   879
    const SDL_Rect *rect = &texture->locked_rect;
slouken@5156
   880
    const void* pixels = (void *) ((Uint8 *) texture->pixels +
slouken@5156
   881
                        rect->y * texture->pitch +
slouken@5156
   882
                        rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@5156
   883
    int pitch = texture->pitch;
slouken@5156
   884
slouken@5156
   885
    if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   886
        return;
slouken@5156
   887
    }
slouken@5156
   888
    SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
   889
                      texture->format, pixels, pitch,
slouken@5156
   890
                      native->format, native_pixels, native_pitch);
slouken@5156
   891
    SDL_UnlockTexture(native);
slouken@5154
   892
}
slouken@5154
   893
slouken@5154
   894
void
slouken@5154
   895
SDL_UnlockTexture(SDL_Texture * texture)
slouken@5154
   896
{
slouken@5154
   897
    SDL_Renderer *renderer;
slouken@5154
   898
slouken@5154
   899
    CHECK_TEXTURE_MAGIC(texture, );
slouken@5154
   900
slouken@5154
   901
    if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
slouken@5154
   902
        return;
slouken@5154
   903
    }
slouken@5156
   904
    if (texture->yuv) {
slouken@5156
   905
        SDL_UnlockTextureYUV(texture);
slouken@5156
   906
    } else if (texture->native) {
slouken@5156
   907
        SDL_UnlockTextureNative(texture);
slouken@5156
   908
    } else {
slouken@5156
   909
        renderer = texture->renderer;
slouken@5156
   910
        renderer->UnlockTexture(renderer, texture);
slouken@5154
   911
    }
slouken@5154
   912
}
slouken@5154
   913
slouken@6246
   914
SDL_bool
slouken@6246
   915
SDL_RenderTargetSupported(SDL_Renderer *renderer)
slouken@6246
   916
{
slouken@6247
   917
    if (!renderer || !renderer->SetRenderTarget) {
slouken@6246
   918
        return SDL_FALSE;
slouken@6246
   919
    }
slouken@6246
   920
    return (renderer->info.flags & SDL_RENDERER_TARGETTEXTURE) != 0;
slouken@6246
   921
}
slouken@6246
   922
slouken@6246
   923
int
slouken@6247
   924
SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
slouken@6246
   925
{
slouken@6246
   926
    if (!SDL_RenderTargetSupported(renderer)) {
icculus@7037
   927
        return SDL_Unsupported();
slouken@6246
   928
    }
slouken@6246
   929
    if (texture == renderer->target) {
slouken@6246
   930
        /* Nothing to do! */
slouken@6246
   931
        return 0;
slouken@6246
   932
    }
slouken@6246
   933
slouken@6246
   934
    /* texture == NULL is valid and means reset the target to the window */
slouken@6246
   935
    if (texture) {
slouken@6246
   936
        CHECK_TEXTURE_MAGIC(texture, -1);
slouken@6246
   937
        if (renderer != texture->renderer) {
icculus@7037
   938
            return SDL_SetError("Texture was not created with this renderer");
slouken@6246
   939
        }
gabomdq@6337
   940
        if (texture->access != SDL_TEXTUREACCESS_TARGET) {
icculus@7037
   941
            return SDL_SetError("Texture not created with SDL_TEXTUREACCESS_TARGET");
slouken@6246
   942
        }
slouken@6246
   943
        if (texture->native) {
slouken@6246
   944
            /* Always render to the native texture */
slouken@6246
   945
            texture = texture->native;
slouken@6246
   946
        }
slouken@6246
   947
    }
slouken@6246
   948
slouken@6246
   949
    if (texture && !renderer->target) {
slouken@6246
   950
        /* Make a backup of the viewport */
slouken@6246
   951
        renderer->viewport_backup = renderer->viewport;
slouken@7141
   952
        renderer->clip_rect_backup = renderer->clip_rect;
slouken@6528
   953
        renderer->scale_backup = renderer->scale;
slouken@6581
   954
        renderer->logical_w_backup = renderer->logical_w;
slouken@6581
   955
        renderer->logical_h_backup = renderer->logical_h;
slouken@6246
   956
    }
slouken@6246
   957
    renderer->target = texture;
slouken@6246
   958
slouken@6247
   959
    if (renderer->SetRenderTarget(renderer, texture) < 0) {
slouken@6246
   960
        return -1;
slouken@6246
   961
    }
slouken@6246
   962
slouken@6246
   963
    if (texture) {
slouken@6528
   964
        renderer->viewport.x = 0;
slouken@6528
   965
        renderer->viewport.y = 0;
slouken@6528
   966
        renderer->viewport.w = texture->w;
slouken@6528
   967
        renderer->viewport.h = texture->h;
slouken@6528
   968
        renderer->scale.x = 1.0f;
slouken@6528
   969
        renderer->scale.y = 1.0f;
slouken@7339
   970
        renderer->logical_w = texture->w;
slouken@7339
   971
        renderer->logical_h = texture->h;
slouken@6246
   972
    } else {
slouken@6528
   973
        renderer->viewport = renderer->viewport_backup;
slouken@7141
   974
        renderer->clip_rect = renderer->clip_rect_backup;
slouken@6528
   975
        renderer->scale = renderer->scale_backup;
slouken@6581
   976
        renderer->logical_w = renderer->logical_w_backup;
slouken@6581
   977
        renderer->logical_h = renderer->logical_h_backup;
slouken@6246
   978
    }
slouken@6528
   979
    if (renderer->UpdateViewport(renderer) < 0) {
slouken@6246
   980
        return -1;
slouken@6246
   981
    }
slouken@7141
   982
    if (renderer->UpdateClipRect(renderer) < 0) {
slouken@7141
   983
        return -1;
slouken@7141
   984
    }
slouken@6246
   985
slouken@6246
   986
    /* All set! */
slouken@6246
   987
    return 0;
slouken@6246
   988
}
slouken@6246
   989
slouken@6578
   990
SDL_Texture *
slouken@6578
   991
SDL_GetRenderTarget(SDL_Renderer *renderer)
slouken@6578
   992
{
slouken@6578
   993
    return renderer->target;
slouken@6578
   994
}
slouken@6578
   995
slouken@6530
   996
static int
slouken@6530
   997
UpdateLogicalSize(SDL_Renderer *renderer)
slouken@6530
   998
{
slouken@6530
   999
    int w, h;
slouken@6530
  1000
    float want_aspect;
slouken@6530
  1001
    float real_aspect;
slouken@6530
  1002
    float scale;
slouken@6530
  1003
    SDL_Rect viewport;
slouken@6530
  1004
slouken@7239
  1005
    if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
slouken@7239
  1006
        return -1;
slouken@6530
  1007
    }
slouken@6530
  1008
slouken@6530
  1009
    want_aspect = (float)renderer->logical_w / renderer->logical_h;
slouken@6530
  1010
    real_aspect = (float)w / h;
slouken@6530
  1011
slouken@6530
  1012
    /* Clear the scale because we're setting viewport in output coordinates */
slouken@6530
  1013
    SDL_RenderSetScale(renderer, 1.0f, 1.0f);
slouken@6530
  1014
slouken@6530
  1015
    if (SDL_fabs(want_aspect-real_aspect) < 0.0001) {
slouken@6530
  1016
        /* The aspect ratios are the same, just scale appropriately */
slouken@6530
  1017
        scale = (float)w / renderer->logical_w;
slouken@6530
  1018
        SDL_RenderSetViewport(renderer, NULL);
slouken@6530
  1019
    } else if (want_aspect > real_aspect) {
slouken@6530
  1020
        /* We want a wider aspect ratio than is available - letterbox it */
slouken@6530
  1021
        scale = (float)w / renderer->logical_w;
slouken@6530
  1022
        viewport.x = 0;
slouken@6530
  1023
        viewport.w = w;
slouken@6530
  1024
        viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
slouken@6530
  1025
        viewport.y = (h - viewport.h) / 2;
slouken@6530
  1026
        SDL_RenderSetViewport(renderer, &viewport);
slouken@6530
  1027
    } else {
slouken@6530
  1028
        /* We want a narrower aspect ratio than is available - use side-bars */
slouken@6530
  1029
        scale = (float)h / renderer->logical_h;
slouken@6530
  1030
        viewport.y = 0;
slouken@6530
  1031
        viewport.h = h;
slouken@6530
  1032
        viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
slouken@6530
  1033
        viewport.x = (w - viewport.w) / 2;
slouken@6530
  1034
        SDL_RenderSetViewport(renderer, &viewport);
slouken@6530
  1035
    }
slouken@6530
  1036
slouken@6530
  1037
    /* Set the new scale */
slouken@6530
  1038
    SDL_RenderSetScale(renderer, scale, scale);
slouken@6531
  1039
slouken@6531
  1040
    return 0;
slouken@6530
  1041
}
slouken@6530
  1042
slouken@6530
  1043
int
slouken@6530
  1044
SDL_RenderSetLogicalSize(SDL_Renderer * renderer, int w, int h)
slouken@6530
  1045
{
slouken@6530
  1046
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@6530
  1047
slouken@6530
  1048
    if (!w || !h) {
slouken@6530
  1049
        /* Clear any previous logical resolution */
slouken@6530
  1050
        renderer->logical_w = 0;
slouken@6530
  1051
        renderer->logical_h = 0;
slouken@6530
  1052
        SDL_RenderSetViewport(renderer, NULL);
slouken@6530
  1053
        SDL_RenderSetScale(renderer, 1.0f, 1.0f);
slouken@6530
  1054
        return 0;
slouken@6530
  1055
    }
slouken@6530
  1056
slouken@6530
  1057
    renderer->logical_w = w;
slouken@6530
  1058
    renderer->logical_h = h;
slouken@6530
  1059
slouken@6530
  1060
    return UpdateLogicalSize(renderer);
slouken@6530
  1061
}
slouken@6530
  1062
slouken@6530
  1063
void
slouken@6530
  1064
SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h)
slouken@6530
  1065
{
slouken@6530
  1066
    CHECK_RENDERER_MAGIC(renderer, );
slouken@6530
  1067
slouken@6530
  1068
    if (w) {
slouken@6530
  1069
        *w = renderer->logical_w;
slouken@6530
  1070
    }
slouken@6530
  1071
    if (h) {
slouken@6530
  1072
        *h = renderer->logical_h;
slouken@6530
  1073
    }
slouken@6530
  1074
}
slouken@6530
  1075
slouken@5297
  1076
int
slouken@5297
  1077
SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@5297
  1078
{
slouken@5297
  1079
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5297
  1080
slouken@5297
  1081
    if (rect) {
slouken@6528
  1082
        renderer->viewport.x = (int)SDL_floor(rect->x * renderer->scale.x);
slouken@6528
  1083
        renderer->viewport.y = (int)SDL_floor(rect->y * renderer->scale.y);
slouken@6528
  1084
        renderer->viewport.w = (int)SDL_ceil(rect->w * renderer->scale.x);
slouken@6528
  1085
        renderer->viewport.h = (int)SDL_ceil(rect->h * renderer->scale.y);
slouken@5297
  1086
    } else {
slouken@5297
  1087
        renderer->viewport.x = 0;
slouken@5297
  1088
        renderer->viewport.y = 0;
slouken@7239
  1089
        if (SDL_GetRendererOutputSize(renderer, &renderer->viewport.w, &renderer->viewport.h) < 0) {
slouken@7239
  1090
            return -1;
slouken@5297
  1091
        }
slouken@5297
  1092
    }
slouken@5297
  1093
    return renderer->UpdateViewport(renderer);
slouken@5297
  1094
}
slouken@5297
  1095
slouken@5224
  1096
void
slouken@5297
  1097
SDL_RenderGetViewport(SDL_Renderer * renderer, SDL_Rect * rect)
slouken@5224
  1098
{
slouken@5224
  1099
    CHECK_RENDERER_MAGIC(renderer, );
slouken@5224
  1100
slouken@6528
  1101
    if (rect) {
slouken@6528
  1102
        rect->x = (int)(renderer->viewport.x / renderer->scale.x);
slouken@6528
  1103
        rect->y = (int)(renderer->viewport.y / renderer->scale.y);
slouken@6528
  1104
        rect->w = (int)(renderer->viewport.w / renderer->scale.x);
slouken@6528
  1105
        rect->h = (int)(renderer->viewport.h / renderer->scale.y);
slouken@6528
  1106
    }
slouken@6528
  1107
}
slouken@6528
  1108
slouken@6528
  1109
int
slouken@7141
  1110
SDL_RenderSetClipRect(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@7141
  1111
{
philipp@7143
  1112
    CHECK_RENDERER_MAGIC(renderer, -1)
slouken@7141
  1113
slouken@7141
  1114
    if (rect) {
slouken@7141
  1115
        renderer->clip_rect.x = (int)SDL_floor(rect->x * renderer->scale.x);
slouken@7141
  1116
        renderer->clip_rect.y = (int)SDL_floor(rect->y * renderer->scale.y);
slouken@7141
  1117
        renderer->clip_rect.w = (int)SDL_ceil(rect->w * renderer->scale.x);
slouken@7141
  1118
        renderer->clip_rect.h = (int)SDL_ceil(rect->h * renderer->scale.y);
slouken@7141
  1119
    } else {
slouken@7141
  1120
        SDL_zero(renderer->clip_rect);
slouken@7141
  1121
    }
slouken@7141
  1122
    return renderer->UpdateClipRect(renderer);
slouken@7141
  1123
}
slouken@7141
  1124
slouken@7141
  1125
void
slouken@7141
  1126
SDL_RenderGetClipRect(SDL_Renderer * renderer, SDL_Rect * rect)
slouken@7141
  1127
{
slouken@7141
  1128
    CHECK_RENDERER_MAGIC(renderer, )
slouken@7141
  1129
slouken@7141
  1130
    if (rect) {
slouken@7141
  1131
        rect->x = (int)(renderer->clip_rect.x / renderer->scale.x);
slouken@7141
  1132
        rect->y = (int)(renderer->clip_rect.y / renderer->scale.y);
slouken@7141
  1133
        rect->w = (int)(renderer->clip_rect.w / renderer->scale.x);
slouken@7141
  1134
        rect->h = (int)(renderer->clip_rect.h / renderer->scale.y);
slouken@7141
  1135
    }
slouken@7141
  1136
}
slouken@7141
  1137
slouken@7141
  1138
int
slouken@6528
  1139
SDL_RenderSetScale(SDL_Renderer * renderer, float scaleX, float scaleY)
slouken@6528
  1140
{
slouken@6528
  1141
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@6528
  1142
slouken@6528
  1143
    renderer->scale.x = scaleX;
slouken@6528
  1144
    renderer->scale.y = scaleY;
slouken@6528
  1145
    return 0;
slouken@6528
  1146
}
slouken@6528
  1147
slouken@6528
  1148
void
slouken@6528
  1149
SDL_RenderGetScale(SDL_Renderer * renderer, float *scaleX, float *scaleY)
slouken@6528
  1150
{
slouken@6528
  1151
    CHECK_RENDERER_MAGIC(renderer, );
slouken@6528
  1152
slouken@6528
  1153
    if (scaleX) {
slouken@6528
  1154
        *scaleX = renderer->scale.x;
slouken@6528
  1155
    }
slouken@6528
  1156
    if (scaleY) {
slouken@6528
  1157
        *scaleY = renderer->scale.y;
slouken@6528
  1158
    }
slouken@5224
  1159
}
slouken@5224
  1160
slouken@5154
  1161
int
slouken@5154
  1162
SDL_SetRenderDrawColor(SDL_Renderer * renderer,
slouken@5154
  1163
                       Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5154
  1164
{
slouken@5154
  1165
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1166
slouken@5154
  1167
    renderer->r = r;
slouken@5154
  1168
    renderer->g = g;
slouken@5154
  1169
    renderer->b = b;
slouken@5154
  1170
    renderer->a = a;
slouken@5154
  1171
    return 0;
slouken@5154
  1172
}
slouken@5154
  1173
slouken@5154
  1174
int
slouken@5154
  1175
SDL_GetRenderDrawColor(SDL_Renderer * renderer,
slouken@5154
  1176
                       Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
slouken@5154
  1177
{
slouken@5154
  1178
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1179
slouken@5154
  1180
    if (r) {
slouken@5154
  1181
        *r = renderer->r;
slouken@5154
  1182
    }
slouken@5154
  1183
    if (g) {
slouken@5154
  1184
        *g = renderer->g;
slouken@5154
  1185
    }
slouken@5154
  1186
    if (b) {
slouken@5154
  1187
        *b = renderer->b;
slouken@5154
  1188
    }
slouken@5154
  1189
    if (a) {
slouken@5154
  1190
        *a = renderer->a;
slouken@5154
  1191
    }
slouken@5154
  1192
    return 0;
slouken@5154
  1193
}
slouken@5154
  1194
slouken@5154
  1195
int
slouken@5154
  1196
SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
slouken@5154
  1197
{
slouken@5154
  1198
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1199
slouken@5154
  1200
    renderer->blendMode = blendMode;
slouken@5154
  1201
    return 0;
slouken@5154
  1202
}
slouken@5154
  1203
slouken@5154
  1204
int
slouken@5154
  1205
SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode *blendMode)
slouken@5154
  1206
{
slouken@5154
  1207
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1208
slouken@5154
  1209
    *blendMode = renderer->blendMode;
slouken@5154
  1210
    return 0;
slouken@5154
  1211
}
slouken@5154
  1212
slouken@5154
  1213
int
slouken@5154
  1214
SDL_RenderClear(SDL_Renderer * renderer)
slouken@5154
  1215
{
slouken@5154
  1216
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1217
slouken@6260
  1218
    /* Don't draw while we're hidden */
slouken@6260
  1219
    if (renderer->hidden) {
slouken@6060
  1220
        return 0;
slouken@6060
  1221
    }
slouken@5154
  1222
    return renderer->RenderClear(renderer);
slouken@5154
  1223
}
slouken@5154
  1224
slouken@5154
  1225
int
slouken@5154
  1226
SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
slouken@5154
  1227
{
slouken@5154
  1228
    SDL_Point point;
slouken@5154
  1229
slouken@5154
  1230
    point.x = x;
slouken@5154
  1231
    point.y = y;
slouken@5154
  1232
    return SDL_RenderDrawPoints(renderer, &point, 1);
slouken@5154
  1233
}
slouken@5154
  1234
slouken@6528
  1235
static int
slouken@6528
  1236
RenderDrawPointsWithRects(SDL_Renderer * renderer,
slouken@6528
  1237
                     const SDL_Point * points, int count)
slouken@6528
  1238
{
slouken@6528
  1239
    SDL_FRect *frects;
slouken@6528
  1240
    int i;
slouken@6528
  1241
    int status;
slouken@6528
  1242
slouken@6528
  1243
    frects = SDL_stack_alloc(SDL_FRect, count);
slouken@6528
  1244
    if (!frects) {
icculus@7037
  1245
        return SDL_OutOfMemory();
slouken@6528
  1246
    }
slouken@6528
  1247
    for (i = 0; i < count; ++i) {
slouken@6528
  1248
        frects[i].x = points[i].x * renderer->scale.x;
slouken@6528
  1249
        frects[i].y = points[i].y * renderer->scale.y;
slouken@6528
  1250
        frects[i].w = renderer->scale.x;
slouken@6528
  1251
        frects[i].h = renderer->scale.y;
slouken@6528
  1252
    }
slouken@6528
  1253
slouken@6528
  1254
    status = renderer->RenderFillRects(renderer, frects, count);
slouken@6528
  1255
slouken@6528
  1256
    SDL_stack_free(frects);
slouken@6528
  1257
slouken@6528
  1258
    return status;
slouken@6528
  1259
}
slouken@6528
  1260
slouken@5154
  1261
int
slouken@5154
  1262
SDL_RenderDrawPoints(SDL_Renderer * renderer,
slouken@5154
  1263
                     const SDL_Point * points, int count)
slouken@5154
  1264
{
slouken@6528
  1265
    SDL_FPoint *fpoints;
slouken@6528
  1266
    int i;
slouken@6528
  1267
    int status;
slouken@6528
  1268
slouken@5154
  1269
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1270
slouken@5154
  1271
    if (!points) {
icculus@7037
  1272
        return SDL_SetError("SDL_RenderDrawPoints(): Passed NULL points");
slouken@5154
  1273
    }
slouken@5154
  1274
    if (count < 1) {
slouken@5154
  1275
        return 0;
slouken@5154
  1276
    }
slouken@6260
  1277
    /* Don't draw while we're hidden */
slouken@6260
  1278
    if (renderer->hidden) {
slouken@6060
  1279
        return 0;
slouken@6060
  1280
    }
slouken@6528
  1281
slouken@6528
  1282
    if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
slouken@6528
  1283
        return RenderDrawPointsWithRects(renderer, points, count);
slouken@6528
  1284
    }
slouken@6528
  1285
slouken@6528
  1286
    fpoints = SDL_stack_alloc(SDL_FPoint, count);
slouken@6528
  1287
    if (!fpoints) {
icculus@7037
  1288
        return SDL_OutOfMemory();
slouken@6528
  1289
    }
slouken@6528
  1290
    for (i = 0; i < count; ++i) {
slouken@6528
  1291
        fpoints[i].x = points[i].x * renderer->scale.x;
slouken@6528
  1292
        fpoints[i].y = points[i].y * renderer->scale.y;
slouken@6528
  1293
    }
slouken@6528
  1294
slouken@6528
  1295
    status = renderer->RenderDrawPoints(renderer, fpoints, count);
slouken@6528
  1296
slouken@6528
  1297
    SDL_stack_free(fpoints);
slouken@6528
  1298
slouken@6528
  1299
    return status;
slouken@5154
  1300
}
slouken@5154
  1301
slouken@5154
  1302
int
slouken@5154
  1303
SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
slouken@5154
  1304
{
slouken@5154
  1305
    SDL_Point points[2];
slouken@5154
  1306
slouken@5154
  1307
    points[0].x = x1;
slouken@5154
  1308
    points[0].y = y1;
slouken@5154
  1309
    points[1].x = x2;
slouken@5154
  1310
    points[1].y = y2;
slouken@5154
  1311
    return SDL_RenderDrawLines(renderer, points, 2);
slouken@5154
  1312
}
slouken@5154
  1313
slouken@6528
  1314
static int
slouken@6528
  1315
RenderDrawLinesWithRects(SDL_Renderer * renderer,
slouken@6528
  1316
                     const SDL_Point * points, int count)
slouken@6528
  1317
{
slouken@6528
  1318
    SDL_FRect *frect;
slouken@6528
  1319
    SDL_FRect *frects;
slouken@6528
  1320
    SDL_FPoint fpoints[2];
slouken@6528
  1321
    int i, nrects;
slouken@6528
  1322
    int status;
slouken@6528
  1323
slouken@6528
  1324
    frects = SDL_stack_alloc(SDL_FRect, count-1);
slouken@6528
  1325
    if (!frects) {
icculus@7037
  1326
        return SDL_OutOfMemory();
slouken@6528
  1327
    }
slouken@6528
  1328
slouken@6528
  1329
    status = 0;
slouken@6528
  1330
    nrects = 0;
slouken@6528
  1331
    for (i = 0; i < count-1; ++i) {
slouken@6528
  1332
        if (points[i].x == points[i+1].x) {
slouken@6528
  1333
            int minY = SDL_min(points[i].y, points[i+1].y);
slouken@6528
  1334
            int maxY = SDL_max(points[i].y, points[i+1].y);
slouken@6528
  1335
slouken@6528
  1336
            frect = &frects[nrects++];
slouken@6528
  1337
            frect->x = points[i].x * renderer->scale.x;
slouken@6528
  1338
            frect->y = minY * renderer->scale.y;
slouken@6528
  1339
            frect->w = renderer->scale.x;
slouken@6528
  1340
            frect->h = (maxY - minY + 1) * renderer->scale.y;
slouken@6528
  1341
        } else if (points[i].y == points[i+1].y) {
slouken@6528
  1342
            int minX = SDL_min(points[i].x, points[i+1].x);
slouken@6528
  1343
            int maxX = SDL_max(points[i].x, points[i+1].x);
slouken@6528
  1344
slouken@6528
  1345
            frect = &frects[nrects++];
slouken@6528
  1346
            frect->x = minX * renderer->scale.x;
slouken@6528
  1347
            frect->y = points[i].y * renderer->scale.y;
slouken@6528
  1348
            frect->w = (maxX - minX + 1) * renderer->scale.x;
slouken@6528
  1349
            frect->h = renderer->scale.y;
slouken@6528
  1350
        } else {
slouken@6528
  1351
            /* FIXME: We can't use a rect for this line... */
aschiffler@7073
  1352
            fpoints[0].x = points[i].x * renderer->scale.x;
aschiffler@7073
  1353
            fpoints[0].y = points[i].y * renderer->scale.y;
aschiffler@7073
  1354
            fpoints[1].x = points[i+1].x * renderer->scale.x;
aschiffler@7073
  1355
            fpoints[1].y = points[i+1].y * renderer->scale.y;
slouken@6528
  1356
            status += renderer->RenderDrawLines(renderer, fpoints, 2);
slouken@6528
  1357
        }
slouken@6528
  1358
    }
slouken@6528
  1359
slouken@6528
  1360
    status += renderer->RenderFillRects(renderer, frects, nrects);
slouken@6528
  1361
slouken@6528
  1362
    SDL_stack_free(frects);
slouken@6528
  1363
slouken@6528
  1364
    if (status < 0) {
slouken@6528
  1365
        status = -1;
slouken@6528
  1366
    }
slouken@6528
  1367
    return status;
slouken@6528
  1368
}
slouken@6528
  1369
slouken@5154
  1370
int
slouken@5154
  1371
SDL_RenderDrawLines(SDL_Renderer * renderer,
slouken@5154
  1372
                    const SDL_Point * points, int count)
slouken@5154
  1373
{
slouken@6528
  1374
    SDL_FPoint *fpoints;
slouken@6528
  1375
    int i;
slouken@6528
  1376
    int status;
slouken@6528
  1377
slouken@5154
  1378
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1379
slouken@5154
  1380
    if (!points) {
icculus@7037
  1381
        return SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
slouken@5154
  1382
    }
slouken@5154
  1383
    if (count < 2) {
slouken@5154
  1384
        return 0;
slouken@5154
  1385
    }
slouken@6260
  1386
    /* Don't draw while we're hidden */
slouken@6260
  1387
    if (renderer->hidden) {
slouken@6060
  1388
        return 0;
slouken@6060
  1389
    }
slouken@6528
  1390
slouken@6528
  1391
    if (renderer->scale.x != 1.0f || renderer->scale.y != 1.0f) {
slouken@6528
  1392
        return RenderDrawLinesWithRects(renderer, points, count);
slouken@6528
  1393
    }
slouken@6528
  1394
slouken@6528
  1395
    fpoints = SDL_stack_alloc(SDL_FPoint, count);
slouken@6528
  1396
    if (!fpoints) {
icculus@7037
  1397
        return SDL_OutOfMemory();
slouken@6528
  1398
    }
slouken@6528
  1399
    for (i = 0; i < count; ++i) {
slouken@6528
  1400
        fpoints[i].x = points[i].x * renderer->scale.x;
slouken@6528
  1401
        fpoints[i].y = points[i].y * renderer->scale.y;
slouken@6528
  1402
    }
slouken@6528
  1403
slouken@6528
  1404
    status = renderer->RenderDrawLines(renderer, fpoints, count);
slouken@6528
  1405
slouken@6528
  1406
    SDL_stack_free(fpoints);
slouken@6528
  1407
slouken@6528
  1408
    return status;
slouken@5154
  1409
}
slouken@5154
  1410
slouken@5154
  1411
int
slouken@5154
  1412
SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@5154
  1413
{
slouken@5154
  1414
    SDL_Rect full_rect;
slouken@5154
  1415
    SDL_Point points[5];
slouken@5154
  1416
slouken@5154
  1417
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1418
slouken@5154
  1419
    /* If 'rect' == NULL, then outline the whole surface */
slouken@5154
  1420
    if (!rect) {
slouken@6528
  1421
        SDL_RenderGetViewport(renderer, &full_rect);
slouken@5154
  1422
        full_rect.x = 0;
slouken@5154
  1423
        full_rect.y = 0;
slouken@5154
  1424
        rect = &full_rect;
slouken@5154
  1425
    }
slouken@5154
  1426
slouken@5154
  1427
    points[0].x = rect->x;
slouken@5154
  1428
    points[0].y = rect->y;
slouken@5154
  1429
    points[1].x = rect->x+rect->w-1;
slouken@5154
  1430
    points[1].y = rect->y;
slouken@5154
  1431
    points[2].x = rect->x+rect->w-1;
slouken@5154
  1432
    points[2].y = rect->y+rect->h-1;
slouken@5154
  1433
    points[3].x = rect->x;
slouken@5154
  1434
    points[3].y = rect->y+rect->h-1;
slouken@5154
  1435
    points[4].x = rect->x;
slouken@5154
  1436
    points[4].y = rect->y;
slouken@5154
  1437
    return SDL_RenderDrawLines(renderer, points, 5);
slouken@5154
  1438
}
slouken@5154
  1439
slouken@5154
  1440
int
slouken@5154
  1441
SDL_RenderDrawRects(SDL_Renderer * renderer,
slouken@5297
  1442
                    const SDL_Rect * rects, int count)
slouken@5154
  1443
{
slouken@5154
  1444
    int i;
slouken@5154
  1445
slouken@5154
  1446
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1447
slouken@5154
  1448
    if (!rects) {
icculus@7037
  1449
        return SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
slouken@5154
  1450
    }
slouken@5154
  1451
    if (count < 1) {
slouken@5154
  1452
        return 0;
slouken@5154
  1453
    }
slouken@5154
  1454
slouken@6260
  1455
    /* Don't draw while we're hidden */
slouken@6260
  1456
    if (renderer->hidden) {
slouken@6060
  1457
        return 0;
slouken@6060
  1458
    }
slouken@5154
  1459
    for (i = 0; i < count; ++i) {
slouken@5297
  1460
        if (SDL_RenderDrawRect(renderer, &rects[i]) < 0) {
slouken@5154
  1461
            return -1;
slouken@5154
  1462
        }
slouken@5154
  1463
    }
slouken@5154
  1464
    return 0;
slouken@5154
  1465
}
slouken@5154
  1466
slouken@5154
  1467
int
slouken@5154
  1468
SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@5154
  1469
{
slouken@7511
  1470
    SDL_Rect full_rect = { 0, 0, 0, 0 };
slouken@6232
  1471
slouken@5331
  1472
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@6232
  1473
slouken@5331
  1474
    /* If 'rect' == NULL, then outline the whole surface */
slouken@5331
  1475
    if (!rect) {
slouken@6528
  1476
        SDL_RenderGetViewport(renderer, &full_rect);
slouken@5331
  1477
        full_rect.x = 0;
slouken@5331
  1478
        full_rect.y = 0;
slouken@5331
  1479
        rect = &full_rect;
slouken@5331
  1480
    }
slouken@5297
  1481
    return SDL_RenderFillRects(renderer, rect, 1);
slouken@5154
  1482
}
slouken@5154
  1483
slouken@5154
  1484
int
slouken@5154
  1485
SDL_RenderFillRects(SDL_Renderer * renderer,
slouken@5297
  1486
                    const SDL_Rect * rects, int count)
slouken@5154
  1487
{
slouken@6528
  1488
    SDL_FRect *frects;
slouken@6528
  1489
    int i;
slouken@6528
  1490
    int status;
slouken@6528
  1491
slouken@5154
  1492
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1493
slouken@5154
  1494
    if (!rects) {
icculus@7037
  1495
        return SDL_SetError("SDL_RenderFillRects(): Passed NULL rects");
slouken@5154
  1496
    }
slouken@5154
  1497
    if (count < 1) {
slouken@5154
  1498
        return 0;
slouken@5154
  1499
    }
slouken@6260
  1500
    /* Don't draw while we're hidden */
slouken@6260
  1501
    if (renderer->hidden) {
slouken@6060
  1502
        return 0;
slouken@6060
  1503
    }
slouken@6528
  1504
slouken@6528
  1505
    frects = SDL_stack_alloc(SDL_FRect, count);
slouken@6528
  1506
    if (!frects) {
icculus@7037
  1507
        return SDL_OutOfMemory();
slouken@6528
  1508
    }
slouken@6528
  1509
    for (i = 0; i < count; ++i) {
slouken@6528
  1510
        frects[i].x = rects[i].x * renderer->scale.x;
slouken@6528
  1511
        frects[i].y = rects[i].y * renderer->scale.y;
slouken@6528
  1512
        frects[i].w = rects[i].w * renderer->scale.x;
slouken@6528
  1513
        frects[i].h = rects[i].h * renderer->scale.y;
slouken@6528
  1514
    }
slouken@6528
  1515
slouken@6528
  1516
    status = renderer->RenderFillRects(renderer, frects, count);
slouken@6528
  1517
slouken@6528
  1518
    SDL_stack_free(frects);
slouken@6528
  1519
slouken@6528
  1520
    return status;
slouken@5154
  1521
}
slouken@5154
  1522
slouken@5154
  1523
int
slouken@5154
  1524
SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5154
  1525
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@5154
  1526
{
icculus@6545
  1527
    SDL_Rect real_srcrect = { 0, 0, 0, 0 };
icculus@6545
  1528
    SDL_Rect real_dstrect = { 0, 0, 0, 0 };
slouken@6528
  1529
    SDL_FRect frect;
slouken@5154
  1530
slouken@5154
  1531
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1532
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
  1533
slouken@5154
  1534
    if (renderer != texture->renderer) {
icculus@7037
  1535
        return SDL_SetError("Texture was not created with this renderer");
slouken@5154
  1536
    }
slouken@5154
  1537
slouken@5154
  1538
    real_srcrect.x = 0;
slouken@5154
  1539
    real_srcrect.y = 0;
slouken@5154
  1540
    real_srcrect.w = texture->w;
slouken@5154
  1541
    real_srcrect.h = texture->h;
slouken@5154
  1542
    if (srcrect) {
slouken@5154
  1543
        if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
slouken@5154
  1544
            return 0;
slouken@5154
  1545
        }
slouken@5154
  1546
    }
slouken@5154
  1547
slouken@6528
  1548
    SDL_RenderGetViewport(renderer, &real_dstrect);
slouken@5154
  1549
    real_dstrect.x = 0;
slouken@5154
  1550
    real_dstrect.y = 0;
slouken@5369
  1551
    if (dstrect) {
slouken@7563
  1552
        if (!SDL_HasIntersection(dstrect, &real_dstrect)) {
slouken@5369
  1553
            return 0;
slouken@5369
  1554
        }
slouken@7563
  1555
        real_dstrect = *dstrect;
slouken@5154
  1556
    }
slouken@5154
  1557
slouken@5156
  1558
    if (texture->native) {
slouken@5156
  1559
        texture = texture->native;
slouken@5156
  1560
    }
slouken@5156
  1561
slouken@6260
  1562
    /* Don't draw while we're hidden */
slouken@6260
  1563
    if (renderer->hidden) {
slouken@6060
  1564
        return 0;
slouken@6060
  1565
    }
slouken@6528
  1566
slouken@6528
  1567
    frect.x = real_dstrect.x * renderer->scale.x;
slouken@6528
  1568
    frect.y = real_dstrect.y * renderer->scale.y;
slouken@6528
  1569
    frect.w = real_dstrect.w * renderer->scale.x;
slouken@6528
  1570
    frect.h = real_dstrect.h * renderer->scale.y;
slouken@6528
  1571
slouken@6528
  1572
    return renderer->RenderCopy(renderer, texture, &real_srcrect, &frect);
slouken@5154
  1573
}
slouken@5154
  1574
gabomdq@6320
  1575
gabomdq@6320
  1576
int
gabomdq@6320
  1577
SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
gabomdq@6320
  1578
               const SDL_Rect * srcrect, const SDL_Rect * dstrect,
gabomdq@6320
  1579
               const double angle, const SDL_Point *center, const SDL_RendererFlip flip)
gabomdq@6320
  1580
{
icculus@6546
  1581
    SDL_Rect real_srcrect = { 0, 0, 0, 0 };
icculus@6546
  1582
    SDL_Rect real_dstrect = { 0, 0, 0, 0 };
gabomdq@6320
  1583
    SDL_Point real_center;
slouken@6528
  1584
    SDL_FRect frect;
slouken@6528
  1585
    SDL_FPoint fcenter;
gabomdq@6320
  1586
gabomdq@6320
  1587
    CHECK_RENDERER_MAGIC(renderer, -1);
gabomdq@6320
  1588
    CHECK_TEXTURE_MAGIC(texture, -1);
gabomdq@6320
  1589
gabomdq@6320
  1590
    if (renderer != texture->renderer) {
icculus@7037
  1591
        return SDL_SetError("Texture was not created with this renderer");
gabomdq@6320
  1592
    }
gabomdq@6320
  1593
    if (!renderer->RenderCopyEx) {
icculus@7037
  1594
        return SDL_SetError("Renderer does not support RenderCopyEx");
gabomdq@6320
  1595
    }
slouken@7191
  1596
gabomdq@6320
  1597
    real_srcrect.x = 0;
gabomdq@6320
  1598
    real_srcrect.y = 0;
gabomdq@6320
  1599
    real_srcrect.w = texture->w;
gabomdq@6320
  1600
    real_srcrect.h = texture->h;
gabomdq@6320
  1601
    if (srcrect) {
gabomdq@6320
  1602
        if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
gabomdq@6320
  1603
            return 0;
gabomdq@6320
  1604
        }
gabomdq@6320
  1605
    }
gabomdq@6320
  1606
gabomdq@6320
  1607
    /* We don't intersect the dstrect with the viewport as RenderCopy does because of potential rotation clipping issues... TODO: should we? */
slouken@6528
  1608
    if (dstrect) {
slouken@6528
  1609
        real_dstrect = *dstrect;
slouken@6528
  1610
    } else {
slouken@6528
  1611
        SDL_RenderGetViewport(renderer, &real_dstrect);
gabomdq@6399
  1612
        real_dstrect.x = 0;
gabomdq@6399
  1613
        real_dstrect.y = 0;
gabomdq@6320
  1614
    }
gabomdq@6320
  1615
gabomdq@6320
  1616
    if (texture->native) {
gabomdq@6320
  1617
        texture = texture->native;
gabomdq@6320
  1618
    }
gabomdq@6320
  1619
gabomdq@6320
  1620
    if(center) real_center = *center;
gabomdq@6320
  1621
    else {
gabomdq@6320
  1622
        real_center.x = real_dstrect.w/2;
gabomdq@6320
  1623
        real_center.y = real_dstrect.h/2;
gabomdq@6320
  1624
    }
gabomdq@6320
  1625
slouken@6528
  1626
    frect.x = real_dstrect.x * renderer->scale.x;
slouken@6528
  1627
    frect.y = real_dstrect.y * renderer->scale.y;
slouken@6528
  1628
    frect.w = real_dstrect.w * renderer->scale.x;
slouken@6528
  1629
    frect.h = real_dstrect.h * renderer->scale.y;
slouken@6528
  1630
slouken@6528
  1631
    fcenter.x = real_center.x * renderer->scale.x;
slouken@6528
  1632
    fcenter.y = real_center.y * renderer->scale.y;
slouken@6528
  1633
slouken@6528
  1634
    return renderer->RenderCopyEx(renderer, texture, &real_srcrect, &frect, angle, &fcenter, flip);
gabomdq@6320
  1635
}
gabomdq@6320
  1636
slouken@5154
  1637
int
slouken@5154
  1638
SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@5154
  1639
                     Uint32 format, void * pixels, int pitch)
slouken@5154
  1640
{
slouken@5154
  1641
    SDL_Rect real_rect;
slouken@5154
  1642
slouken@5154
  1643
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1644
slouken@5154
  1645
    if (!renderer->RenderReadPixels) {
icculus@7037
  1646
        return SDL_Unsupported();
slouken@5154
  1647
    }
slouken@5154
  1648
slouken@5154
  1649
    if (!format) {
icculus@6389
  1650
        format = SDL_GetWindowPixelFormat(renderer->window);
slouken@5154
  1651
    }
slouken@5154
  1652
slouken@5464
  1653
    real_rect.x = renderer->viewport.x;
slouken@5464
  1654
    real_rect.y = renderer->viewport.y;
slouken@5297
  1655
    real_rect.w = renderer->viewport.w;
slouken@5297
  1656
    real_rect.h = renderer->viewport.h;
slouken@5154
  1657
    if (rect) {
slouken@5154
  1658
        if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
slouken@5154
  1659
            return 0;
slouken@5154
  1660
        }
slouken@5154
  1661
        if (real_rect.y > rect->y) {
slouken@5154
  1662
            pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
slouken@5154
  1663
        }
slouken@5154
  1664
        if (real_rect.x > rect->x) {
slouken@5464
  1665
            int bpp = SDL_BYTESPERPIXEL(format);
slouken@5154
  1666
            pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
slouken@5154
  1667
        }
slouken@5154
  1668
    }
slouken@5154
  1669
slouken@5154
  1670
    return renderer->RenderReadPixels(renderer, &real_rect,
slouken@5154
  1671
                                      format, pixels, pitch);
slouken@5154
  1672
}
slouken@5154
  1673
slouken@5154
  1674
void
slouken@5154
  1675
SDL_RenderPresent(SDL_Renderer * renderer)
slouken@5154
  1676
{
slouken@5154
  1677
    CHECK_RENDERER_MAGIC(renderer, );
slouken@5154
  1678
slouken@6260
  1679
    /* Don't draw while we're hidden */
slouken@6260
  1680
    if (renderer->hidden) {
slouken@6060
  1681
        return;
slouken@6060
  1682
    }
slouken@5154
  1683
    renderer->RenderPresent(renderer);
slouken@5154
  1684
}
slouken@5154
  1685
slouken@5154
  1686
void
slouken@5154
  1687
SDL_DestroyTexture(SDL_Texture * texture)
slouken@5154
  1688
{
slouken@5154
  1689
    SDL_Renderer *renderer;
slouken@5154
  1690
slouken@5154
  1691
    CHECK_TEXTURE_MAGIC(texture, );
slouken@7419
  1692
slouken@7419
  1693
    renderer = texture->renderer;
slouken@7419
  1694
    if (texture == renderer->target) {
slouken@7419
  1695
        SDL_SetRenderTarget(renderer, NULL);
slouken@7419
  1696
    }
slouken@7419
  1697
slouken@5154
  1698
    texture->magic = NULL;
slouken@5154
  1699
slouken@5154
  1700
    if (texture->next) {
slouken@5154
  1701
        texture->next->prev = texture->prev;
slouken@5154
  1702
    }
slouken@5154
  1703
    if (texture->prev) {
slouken@5154
  1704
        texture->prev->next = texture->next;
slouken@5154
  1705
    } else {
slouken@5154
  1706
        renderer->textures = texture->next;
slouken@5154
  1707
    }
slouken@5154
  1708
slouken@5156
  1709
    if (texture->native) {
slouken@5156
  1710
        SDL_DestroyTexture(texture->native);
slouken@5156
  1711
    }
slouken@5156
  1712
    if (texture->yuv) {
slouken@5156
  1713
        SDL_SW_DestroyYUVTexture(texture->yuv);
slouken@5156
  1714
    }
slouken@5156
  1715
    if (texture->pixels) {
slouken@5156
  1716
        SDL_free(texture->pixels);
slouken@5156
  1717
    }
slouken@5156
  1718
slouken@5154
  1719
    renderer->DestroyTexture(renderer, texture);
slouken@5154
  1720
    SDL_free(texture);
slouken@5154
  1721
}
slouken@5154
  1722
slouken@5154
  1723
void
slouken@5154
  1724
SDL_DestroyRenderer(SDL_Renderer * renderer)
slouken@5154
  1725
{
slouken@5154
  1726
    CHECK_RENDERER_MAGIC(renderer, );
slouken@5154
  1727
slouken@5154
  1728
    SDL_DelEventWatch(SDL_RendererEventWatch, renderer);
slouken@5154
  1729
slouken@5154
  1730
    /* Free existing textures for this renderer */
slouken@5154
  1731
    while (renderer->textures) {
slouken@5154
  1732
        SDL_DestroyTexture(renderer->textures);
slouken@5154
  1733
    }
slouken@5154
  1734
slouken@6417
  1735
    if (renderer->window) {
slouken@6417
  1736
        SDL_SetWindowData(renderer->window, SDL_WINDOWRENDERDATA, NULL);
slouken@6417
  1737
    }
slouken@5528
  1738
slouken@5154
  1739
    /* It's no longer magical... */
slouken@5154
  1740
    renderer->magic = NULL;
slouken@5154
  1741
slouken@5154
  1742
    /* Free the renderer instance */
slouken@5154
  1743
    renderer->DestroyRenderer(renderer);
slouken@5154
  1744
}
slouken@5154
  1745
gabomdq@6414
  1746
int SDL_GL_BindTexture(SDL_Texture *texture, float *texw, float *texh)
gabomdq@6414
  1747
{
gabomdq@6414
  1748
    SDL_Renderer *renderer;
gabomdq@6414
  1749
gabomdq@6415
  1750
    CHECK_TEXTURE_MAGIC(texture, -1);
gabomdq@6414
  1751
    renderer = texture->renderer;
slouken@7318
  1752
    if (texture->native) {
slouken@7318
  1753
        return SDL_GL_BindTexture(texture->native, texw, texh);
slouken@7318
  1754
    } else if (renderer && renderer->GL_BindTexture) {
gabomdq@6414
  1755
        return renderer->GL_BindTexture(renderer, texture, texw, texh);
slouken@7318
  1756
    } else {
slouken@7318
  1757
        return SDL_Unsupported();
gabomdq@6414
  1758
    }
gabomdq@6414
  1759
}
gabomdq@6414
  1760
gabomdq@6414
  1761
int SDL_GL_UnbindTexture(SDL_Texture *texture)
gabomdq@6414
  1762
{
gabomdq@6414
  1763
    SDL_Renderer *renderer;
gabomdq@6414
  1764
gabomdq@6415
  1765
    CHECK_TEXTURE_MAGIC(texture, -1);
gabomdq@6414
  1766
    renderer = texture->renderer;
gabomdq@6414
  1767
    if (renderer && renderer->GL_UnbindTexture) {
gabomdq@6414
  1768
        return renderer->GL_UnbindTexture(renderer, texture);
gabomdq@6414
  1769
    }
gabomdq@6414
  1770
icculus@7037
  1771
    return SDL_Unsupported();
gabomdq@6414
  1772
}
gabomdq@6414
  1773
slouken@5154
  1774
/* vi: set ts=4 sw=4 expandtab: */