src/render/SDL_render.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 03 Feb 2011 00:22:18 -0800
changeset 5157 657543cc92f9
parent 5156 307ccc9c135e
child 5158 b3ccd1947786
permissions -rw-r--r--
Making the API simpler, removed the writepixels interface
slouken@5154
     1
/*
slouken@5154
     2
    SDL - Simple DirectMedia Layer
slouken@5154
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@5154
     4
slouken@5154
     5
    This library is free software; you can redistribute it and/or
slouken@5154
     6
    modify it under the terms of the GNU Lesser General Public
slouken@5154
     7
    License as published by the Free Software Foundation; either
slouken@5154
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@5154
     9
slouken@5154
    10
    This library is distributed in the hope that it will be useful,
slouken@5154
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@5154
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@5154
    13
    Lesser General Public License for more details.
slouken@5154
    14
slouken@5154
    15
    You should have received a copy of the GNU Lesser General Public
slouken@5154
    16
    License along with this library; if not, write to the Free Software
slouken@5154
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@5154
    18
slouken@5154
    19
    Sam Lantinga
slouken@5154
    20
    slouken@libsdl.org
slouken@5154
    21
*/
slouken@5154
    22
#include "SDL_config.h"
slouken@5154
    23
slouken@5154
    24
/* The SDL 2D rendering system */
slouken@5154
    25
slouken@5154
    26
#include "SDL_render.h"
slouken@5154
    27
#include "SDL_sysrender.h"
slouken@5154
    28
#include "../video/SDL_pixels_c.h"
slouken@5154
    29
slouken@5154
    30
slouken@5154
    31
#define CHECK_RENDERER_MAGIC(renderer, retval) \
slouken@5154
    32
    if (!renderer || renderer->magic != &renderer_magic) { \
slouken@5154
    33
        SDL_SetError("Invalid renderer"); \
slouken@5154
    34
        return retval; \
slouken@5154
    35
    }
slouken@5154
    36
slouken@5154
    37
#define CHECK_TEXTURE_MAGIC(texture, retval) \
slouken@5154
    38
    if (!texture || texture->magic != &texture_magic) { \
slouken@5154
    39
        SDL_SetError("Invalid texture"); \
slouken@5154
    40
        return retval; \
slouken@5154
    41
    }
slouken@5154
    42
slouken@5154
    43
slouken@5154
    44
static const SDL_RenderDriver *render_drivers[] = {
slouken@5154
    45
#if SDL_VIDEO_RENDER_D3D
slouken@5154
    46
    &D3D_RenderDriver,
slouken@5154
    47
#endif
slouken@5154
    48
#if SDL_VIDEO_RENDER_OGL
slouken@5154
    49
    &GL_RenderDriver,
slouken@5154
    50
#endif
slouken@5154
    51
#if SDL_VIDEO_RENDER_OGL_ES
slouken@5154
    52
    &GL_ES_RenderDriver,
slouken@5154
    53
#endif
slouken@5154
    54
    &SW_RenderDriver
slouken@5154
    55
};
slouken@5154
    56
static char renderer_magic;
slouken@5154
    57
static char texture_magic;
slouken@5154
    58
slouken@5154
    59
int
slouken@5154
    60
SDL_GetNumRenderDrivers(void)
slouken@5154
    61
{
slouken@5154
    62
    return SDL_arraysize(render_drivers);
slouken@5154
    63
}
slouken@5154
    64
slouken@5154
    65
int
slouken@5154
    66
SDL_GetRenderDriverInfo(int index, SDL_RendererInfo * info)
slouken@5154
    67
{
slouken@5154
    68
    if (index < 0 || index >= SDL_GetNumRenderDrivers()) {
slouken@5154
    69
        SDL_SetError("index must be in the range of 0 - %d",
slouken@5154
    70
                     SDL_GetNumRenderDrivers() - 1);
slouken@5154
    71
        return -1;
slouken@5154
    72
    }
slouken@5154
    73
    *info = render_drivers[index]->info;
slouken@5154
    74
    return 0;
slouken@5154
    75
}
slouken@5154
    76
slouken@5154
    77
static int
slouken@5154
    78
SDL_RendererEventWatch(void *userdata, SDL_Event *event)
slouken@5154
    79
{
slouken@5154
    80
    SDL_Renderer *renderer = (SDL_Renderer *)userdata;
slouken@5154
    81
slouken@5154
    82
    if (event->type == SDL_WINDOWEVENT && renderer->WindowEvent) {
slouken@5154
    83
        SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
slouken@5154
    84
        if (window == renderer->window) {
slouken@5154
    85
            renderer->WindowEvent(renderer, &event->window);
slouken@5154
    86
        }
slouken@5154
    87
    }
slouken@5154
    88
    return 0;
slouken@5154
    89
}
slouken@5154
    90
slouken@5154
    91
SDL_Renderer *
slouken@5154
    92
SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
slouken@5154
    93
{
slouken@5154
    94
    SDL_Renderer *renderer = NULL;
slouken@5154
    95
    int n = SDL_GetNumRenderDrivers();
slouken@5154
    96
slouken@5154
    97
    if (index < 0) {
slouken@5154
    98
        char *override = SDL_getenv("SDL_VIDEO_RENDERER");
slouken@5154
    99
slouken@5154
   100
        if (override) {
slouken@5154
   101
            for (index = 0; index < n; ++index) {
slouken@5154
   102
                const SDL_RenderDriver *driver = render_drivers[index];
slouken@5154
   103
slouken@5154
   104
                if (SDL_strcasecmp(override, driver->info.name) == 0) {
slouken@5154
   105
                    /* Create a new renderer instance */
slouken@5154
   106
                    renderer = driver->CreateRenderer(window, flags);
slouken@5154
   107
                    break;
slouken@5154
   108
                }
slouken@5154
   109
            }
slouken@5154
   110
        } else {
slouken@5154
   111
            for (index = 0; index < n; ++index) {
slouken@5154
   112
                const SDL_RenderDriver *driver = render_drivers[index];
slouken@5154
   113
slouken@5154
   114
                if ((driver->info.flags & flags) == flags) {
slouken@5154
   115
                    /* Create a new renderer instance */
slouken@5154
   116
                    renderer = driver->CreateRenderer(window, flags);
slouken@5154
   117
                    if (renderer) {
slouken@5154
   118
                        /* Yay, we got one! */
slouken@5154
   119
                        break;
slouken@5154
   120
                    }
slouken@5154
   121
                }
slouken@5154
   122
            }
slouken@5154
   123
        }
slouken@5154
   124
        if (index == n) {
slouken@5154
   125
            SDL_SetError("Couldn't find matching render driver");
slouken@5154
   126
            return NULL;
slouken@5154
   127
        }
slouken@5154
   128
    } else {
slouken@5154
   129
        if (index >= SDL_GetNumRenderDrivers()) {
slouken@5154
   130
            SDL_SetError("index must be -1 or in the range of 0 - %d",
slouken@5154
   131
                         SDL_GetNumRenderDrivers() - 1);
slouken@5154
   132
            return NULL;
slouken@5154
   133
        }
slouken@5154
   134
        /* Create a new renderer instance */
slouken@5154
   135
        renderer = render_drivers[index]->CreateRenderer(window, flags);
slouken@5154
   136
    }
slouken@5154
   137
slouken@5154
   138
    if (renderer) {
slouken@5154
   139
        renderer->magic = &renderer_magic;
slouken@5154
   140
slouken@5154
   141
        SDL_AddEventWatch(SDL_RendererEventWatch, renderer);
slouken@5154
   142
    }
slouken@5154
   143
    return renderer;
slouken@5154
   144
}
slouken@5154
   145
slouken@5154
   146
int
slouken@5154
   147
SDL_GetRendererInfo(SDL_Renderer * renderer, SDL_RendererInfo * info)
slouken@5154
   148
{
slouken@5154
   149
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   150
slouken@5154
   151
    *info = renderer->info;
slouken@5154
   152
    return 0;
slouken@5154
   153
}
slouken@5154
   154
slouken@5156
   155
static SDL_bool
slouken@5156
   156
IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
slouken@5156
   157
{
slouken@5156
   158
    Uint32 i;
slouken@5156
   159
slouken@5156
   160
    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
slouken@5156
   161
        if (renderer->info.texture_formats[i] == format) {
slouken@5156
   162
            return SDL_TRUE;
slouken@5156
   163
        }
slouken@5156
   164
    }
slouken@5156
   165
    return SDL_FALSE;
slouken@5156
   166
}
slouken@5156
   167
slouken@5156
   168
static Uint32
slouken@5156
   169
GetClosestSupportedFormat(SDL_Renderer * renderer, Uint32 format)
slouken@5156
   170
{
slouken@5156
   171
    Uint32 i;
slouken@5156
   172
    SDL_bool hasAlpha = SDL_ISPIXELFORMAT_ALPHA(format);
slouken@5156
   173
slouken@5156
   174
    /* We just want to match the first format that has the same channels */
slouken@5156
   175
    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
slouken@5156
   176
        if (SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == hasAlpha) {
slouken@5156
   177
            return renderer->info.texture_formats[i];
slouken@5156
   178
        }
slouken@5156
   179
    }
slouken@5156
   180
    return renderer->info.texture_formats[0];
slouken@5156
   181
}
slouken@5156
   182
slouken@5154
   183
SDL_Texture *
slouken@5154
   184
SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
slouken@5154
   185
{
slouken@5154
   186
    SDL_Texture *texture;
slouken@5154
   187
slouken@5154
   188
    CHECK_RENDERER_MAGIC(renderer, NULL);
slouken@5154
   189
slouken@5156
   190
    if (SDL_ISPIXELFORMAT_INDEXED(format)) {
slouken@5156
   191
        SDL_SetError("Palettized textures are not supported");
slouken@5156
   192
        return NULL;
slouken@5156
   193
    }
slouken@5154
   194
    if (w <= 0 || h <= 0) {
slouken@5154
   195
        SDL_SetError("Texture dimensions can't be 0");
slouken@5156
   196
        return NULL;
slouken@5154
   197
    }
slouken@5154
   198
    texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
slouken@5154
   199
    if (!texture) {
slouken@5154
   200
        SDL_OutOfMemory();
slouken@5156
   201
        return NULL;
slouken@5154
   202
    }
slouken@5154
   203
    texture->magic = &texture_magic;
slouken@5154
   204
    texture->format = format;
slouken@5154
   205
    texture->access = access;
slouken@5154
   206
    texture->w = w;
slouken@5154
   207
    texture->h = h;
slouken@5154
   208
    texture->r = 255;
slouken@5154
   209
    texture->g = 255;
slouken@5154
   210
    texture->b = 255;
slouken@5154
   211
    texture->a = 255;
slouken@5154
   212
    texture->renderer = renderer;
slouken@5154
   213
    texture->next = renderer->textures;
slouken@5154
   214
    if (renderer->textures) {
slouken@5154
   215
        renderer->textures->prev = texture;
slouken@5154
   216
    }
slouken@5154
   217
    renderer->textures = texture;
slouken@5154
   218
slouken@5156
   219
    if (IsSupportedFormat(renderer, format)) {
slouken@5156
   220
        if (renderer->CreateTexture(renderer, texture) < 0) {
slouken@5156
   221
            SDL_DestroyTexture(texture);
slouken@5156
   222
            return 0;
slouken@5156
   223
        }
slouken@5156
   224
    } else {
slouken@5156
   225
        texture->native = SDL_CreateTexture(renderer,
slouken@5156
   226
                                GetClosestSupportedFormat(renderer, format),
slouken@5156
   227
                                access, w, h);
slouken@5156
   228
        if (!texture->native) {
slouken@5156
   229
            SDL_DestroyTexture(texture);
slouken@5156
   230
            return NULL;
slouken@5156
   231
        }
slouken@5156
   232
slouken@5156
   233
        if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@5156
   234
            texture->yuv = SDL_SW_CreateYUVTexture(format, w, h);
slouken@5156
   235
            if (!texture->yuv) {
slouken@5156
   236
                SDL_DestroyTexture(texture);
slouken@5156
   237
                return NULL;
slouken@5156
   238
            }
slouken@5156
   239
        } else if (access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5156
   240
            /* The pitch is 4 byte aligned */
slouken@5156
   241
            texture->pitch = (((w * SDL_BYTESPERPIXEL(format)) + 3) & ~3);
slouken@5156
   242
            texture->pixels = SDL_malloc(texture->pitch * h);
slouken@5156
   243
            if (!texture->pixels) {
slouken@5156
   244
                SDL_DestroyTexture(texture);
slouken@5156
   245
                return NULL;
slouken@5156
   246
            }
slouken@5156
   247
        }
slouken@5154
   248
    }
slouken@5154
   249
    return texture;
slouken@5154
   250
}
slouken@5154
   251
slouken@5154
   252
SDL_Texture *
slouken@5154
   253
SDL_CreateTextureFromSurface(SDL_Renderer * renderer, Uint32 format, SDL_Surface * surface)
slouken@5154
   254
{
slouken@5154
   255
    SDL_Texture *texture;
slouken@5154
   256
    Uint32 requested_format = format;
slouken@5154
   257
    SDL_PixelFormat *fmt;
slouken@5154
   258
    int bpp;
slouken@5154
   259
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@5154
   260
slouken@5154
   261
    CHECK_RENDERER_MAGIC(renderer, NULL);
slouken@5154
   262
slouken@5154
   263
    if (!surface) {
slouken@5154
   264
        SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface");
slouken@5154
   265
        return NULL;
slouken@5154
   266
    }
slouken@5154
   267
    fmt = surface->format;
slouken@5154
   268
slouken@5154
   269
    if (format) {
slouken@5154
   270
        if (!SDL_PixelFormatEnumToMasks
slouken@5154
   271
            (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@5154
   272
            SDL_SetError("Unknown pixel format");
slouken@5154
   273
            return 0;
slouken@5154
   274
        }
slouken@5154
   275
    } else {
slouken@5154
   276
        SDL_bool hasColorkey;
slouken@5154
   277
        SDL_BlendMode blendMode;
slouken@5154
   278
        SDL_bool hasBlending;
slouken@5154
   279
slouken@5154
   280
        hasColorkey = (SDL_GetColorKey(surface, NULL) == 0);
slouken@5154
   281
slouken@5154
   282
        SDL_GetSurfaceBlendMode(surface, &blendMode);
slouken@5154
   283
        hasBlending = (blendMode == SDL_BLENDMODE_BLEND);
slouken@5154
   284
slouken@5154
   285
        if (surface->format->Amask || (!hasColorkey && !hasBlending)) {
slouken@5154
   286
            Uint32 it;
slouken@5154
   287
            int pfmt;
slouken@5154
   288
slouken@5154
   289
            /* Pixel formats, sorted by best first */
slouken@5154
   290
            static const Uint32 sdl_pformats[] = {
slouken@5154
   291
                SDL_PIXELFORMAT_ARGB8888,
slouken@5154
   292
                SDL_PIXELFORMAT_RGBA8888,
slouken@5154
   293
                SDL_PIXELFORMAT_ABGR8888,
slouken@5154
   294
                SDL_PIXELFORMAT_BGRA8888,
slouken@5154
   295
                SDL_PIXELFORMAT_RGB888,
slouken@5154
   296
                SDL_PIXELFORMAT_BGR888,
slouken@5154
   297
                SDL_PIXELFORMAT_RGB24,
slouken@5154
   298
                SDL_PIXELFORMAT_BGR24,
slouken@5154
   299
                SDL_PIXELFORMAT_RGB565,
slouken@5154
   300
                SDL_PIXELFORMAT_BGR565,
slouken@5154
   301
                SDL_PIXELFORMAT_ARGB1555,
slouken@5154
   302
                SDL_PIXELFORMAT_RGBA5551,
slouken@5154
   303
                SDL_PIXELFORMAT_ABGR1555,
slouken@5154
   304
                SDL_PIXELFORMAT_BGRA5551,
slouken@5154
   305
                SDL_PIXELFORMAT_RGB555,
slouken@5154
   306
                SDL_PIXELFORMAT_BGR555,
slouken@5154
   307
                SDL_PIXELFORMAT_ARGB4444,
slouken@5154
   308
                SDL_PIXELFORMAT_RGBA4444,
slouken@5154
   309
                SDL_PIXELFORMAT_ABGR4444,
slouken@5154
   310
                SDL_PIXELFORMAT_BGRA4444,
slouken@5154
   311
                SDL_PIXELFORMAT_RGB444,
slouken@5154
   312
                SDL_PIXELFORMAT_ARGB2101010,
slouken@5154
   313
                SDL_PIXELFORMAT_RGB332,
slouken@5154
   314
                SDL_PIXELFORMAT_UNKNOWN
slouken@5154
   315
            };
slouken@5154
   316
slouken@5154
   317
            bpp = fmt->BitsPerPixel;
slouken@5154
   318
            Rmask = fmt->Rmask;
slouken@5154
   319
            Gmask = fmt->Gmask;
slouken@5154
   320
            Bmask = fmt->Bmask;
slouken@5154
   321
            Amask = fmt->Amask;
slouken@5154
   322
slouken@5154
   323
            format =
slouken@5154
   324
                SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
slouken@5154
   325
            if (!format) {
slouken@5154
   326
                SDL_SetError("Unknown pixel format");
slouken@5154
   327
                return 0;
slouken@5154
   328
            }
slouken@5154
   329
slouken@5154
   330
            /* Search requested format in the supported texture */
slouken@5154
   331
            /* formats by current renderer                      */
slouken@5154
   332
            for (it = 0; it < renderer->info.num_texture_formats; it++) {
slouken@5154
   333
                if (renderer->info.texture_formats[it] == format) {
slouken@5154
   334
                    break;
slouken@5154
   335
                }
slouken@5154
   336
            }
slouken@5154
   337
slouken@5154
   338
            /* If requested format can't be found, search any best */
slouken@5154
   339
            /* format which renderer provides                      */
slouken@5154
   340
            if (it == renderer->info.num_texture_formats) {
slouken@5154
   341
                pfmt = 0;
slouken@5154
   342
                for (;;) {
slouken@5154
   343
                    if (sdl_pformats[pfmt] == SDL_PIXELFORMAT_UNKNOWN) {
slouken@5154
   344
                        break;
slouken@5154
   345
                    }
slouken@5154
   346
slouken@5154
   347
                    for (it = 0; it < renderer->info.num_texture_formats;
slouken@5154
   348
                         it++) {
slouken@5154
   349
                        if (renderer->info.texture_formats[it] ==
slouken@5154
   350
                            sdl_pformats[pfmt]) {
slouken@5154
   351
                            break;
slouken@5154
   352
                        }
slouken@5154
   353
                    }
slouken@5154
   354
slouken@5154
   355
                    if (it != renderer->info.num_texture_formats) {
slouken@5154
   356
                        /* The best format has been found */
slouken@5154
   357
                        break;
slouken@5154
   358
                    }
slouken@5154
   359
                    pfmt++;
slouken@5154
   360
                }
slouken@5154
   361
slouken@5154
   362
                /* If any format can't be found, then return an error */
slouken@5154
   363
                if (it == renderer->info.num_texture_formats) {
slouken@5154
   364
                    SDL_SetError
slouken@5154
   365
                        ("Any of the supported pixel formats can't be found");
slouken@5154
   366
                    return 0;
slouken@5154
   367
                }
slouken@5154
   368
slouken@5154
   369
                /* Convert found pixel format back to color masks */
slouken@5154
   370
                if (SDL_PixelFormatEnumToMasks
slouken@5154
   371
                    (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
slouken@5154
   372
                     &Bmask, &Amask) != SDL_TRUE) {
slouken@5154
   373
                    SDL_SetError("Unknown pixel format");
slouken@5154
   374
                    return 0;
slouken@5154
   375
                }
slouken@5154
   376
            }
slouken@5154
   377
        } else {
slouken@5154
   378
            /* Need a format with alpha */
slouken@5154
   379
            Uint32 it;
slouken@5154
   380
            int apfmt;
slouken@5154
   381
slouken@5154
   382
            /* Pixel formats with alpha, sorted by best first */
slouken@5154
   383
            static const Uint32 sdl_alpha_pformats[] = {
slouken@5154
   384
                SDL_PIXELFORMAT_ARGB8888,
slouken@5154
   385
                SDL_PIXELFORMAT_RGBA8888,
slouken@5154
   386
                SDL_PIXELFORMAT_ABGR8888,
slouken@5154
   387
                SDL_PIXELFORMAT_BGRA8888,
slouken@5154
   388
                SDL_PIXELFORMAT_ARGB1555,
slouken@5154
   389
                SDL_PIXELFORMAT_RGBA5551,
slouken@5154
   390
                SDL_PIXELFORMAT_ABGR1555,
slouken@5154
   391
                SDL_PIXELFORMAT_BGRA5551,
slouken@5154
   392
                SDL_PIXELFORMAT_ARGB4444,
slouken@5154
   393
                SDL_PIXELFORMAT_RGBA4444,
slouken@5154
   394
                SDL_PIXELFORMAT_ABGR4444,
slouken@5154
   395
                SDL_PIXELFORMAT_BGRA4444,
slouken@5154
   396
                SDL_PIXELFORMAT_ARGB2101010,
slouken@5154
   397
                SDL_PIXELFORMAT_UNKNOWN
slouken@5154
   398
            };
slouken@5154
   399
slouken@5154
   400
            if (surface->format->Amask) {
slouken@5154
   401
                /* If surface already has alpha, then try an original */
slouken@5154
   402
                /* surface format first                               */
slouken@5154
   403
                bpp = fmt->BitsPerPixel;
slouken@5154
   404
                Rmask = fmt->Rmask;
slouken@5154
   405
                Gmask = fmt->Gmask;
slouken@5154
   406
                Bmask = fmt->Bmask;
slouken@5154
   407
                Amask = fmt->Amask;
slouken@5154
   408
            } else {
slouken@5154
   409
                bpp = 32;
slouken@5154
   410
                Rmask = 0x00FF0000;
slouken@5154
   411
                Gmask = 0x0000FF00;
slouken@5154
   412
                Bmask = 0x000000FF;
slouken@5154
   413
                Amask = 0xFF000000;
slouken@5154
   414
            }
slouken@5154
   415
slouken@5154
   416
            format =
slouken@5154
   417
                SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
slouken@5154
   418
            if (!format) {
slouken@5154
   419
                SDL_SetError("Unknown pixel format");
slouken@5154
   420
                return 0;
slouken@5154
   421
            }
slouken@5154
   422
slouken@5154
   423
            /* Search this format in the supported texture formats */
slouken@5154
   424
            /* by current renderer                                 */
slouken@5154
   425
            for (it = 0; it < renderer->info.num_texture_formats; it++) {
slouken@5154
   426
                if (renderer->info.texture_formats[it] == format) {
slouken@5154
   427
                    break;
slouken@5154
   428
                }
slouken@5154
   429
            }
slouken@5154
   430
slouken@5154
   431
            /* If this format can't be found, search any best       */
slouken@5154
   432
            /* compatible format with alpha which renderer provides */
slouken@5154
   433
            if (it == renderer->info.num_texture_formats) {
slouken@5154
   434
                apfmt = 0;
slouken@5154
   435
                for (;;) {
slouken@5154
   436
                    if (sdl_alpha_pformats[apfmt] == SDL_PIXELFORMAT_UNKNOWN) {
slouken@5154
   437
                        break;
slouken@5154
   438
                    }
slouken@5154
   439
slouken@5154
   440
                    for (it = 0; it < renderer->info.num_texture_formats;
slouken@5154
   441
                         it++) {
slouken@5154
   442
                        if (renderer->info.texture_formats[it] ==
slouken@5154
   443
                            sdl_alpha_pformats[apfmt]) {
slouken@5154
   444
                            break;
slouken@5154
   445
                        }
slouken@5154
   446
                    }
slouken@5154
   447
slouken@5154
   448
                    if (it != renderer->info.num_texture_formats) {
slouken@5154
   449
                        /* Compatible format has been found */
slouken@5154
   450
                        break;
slouken@5154
   451
                    }
slouken@5154
   452
                    apfmt++;
slouken@5154
   453
                }
slouken@5154
   454
slouken@5154
   455
                /* If compatible format can't be found, then return an error */
slouken@5154
   456
                if (it == renderer->info.num_texture_formats) {
slouken@5154
   457
                    SDL_SetError("Compatible pixel format can't be found");
slouken@5154
   458
                    return 0;
slouken@5154
   459
                }
slouken@5154
   460
slouken@5154
   461
                /* Convert found pixel format back to color masks */
slouken@5154
   462
                if (SDL_PixelFormatEnumToMasks
slouken@5154
   463
                    (renderer->info.texture_formats[it], &bpp, &Rmask, &Gmask,
slouken@5154
   464
                     &Bmask, &Amask) != SDL_TRUE) {
slouken@5154
   465
                    SDL_SetError("Unknown pixel format");
slouken@5154
   466
                    return 0;
slouken@5154
   467
                }
slouken@5154
   468
            }
slouken@5154
   469
        }
slouken@5154
   470
slouken@5154
   471
        format = SDL_MasksToPixelFormatEnum(bpp, Rmask, Gmask, Bmask, Amask);
slouken@5154
   472
        if (!format) {
slouken@5154
   473
            SDL_SetError("Unknown pixel format");
slouken@5154
   474
            return 0;
slouken@5154
   475
        }
slouken@5154
   476
    }
slouken@5154
   477
slouken@5154
   478
    texture =
slouken@5154
   479
        SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
slouken@5154
   480
                          surface->w, surface->h);
slouken@5154
   481
    if (!texture && !requested_format) {
slouken@5154
   482
        SDL_DisplayMode desktop_mode;
slouken@5154
   483
        SDL_GetDesktopDisplayMode(&desktop_mode);
slouken@5154
   484
        format = desktop_mode.format;
slouken@5154
   485
        texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC,
slouken@5154
   486
                                    surface->w, surface->h);
slouken@5154
   487
    }
slouken@5154
   488
    if (!texture) {
slouken@5154
   489
        return 0;
slouken@5154
   490
    }
slouken@5154
   491
    if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask
slouken@5154
   492
        && Bmask == fmt->Bmask && Amask == fmt->Amask) {
slouken@5154
   493
        if (SDL_MUSTLOCK(surface)) {
slouken@5154
   494
            SDL_LockSurface(surface);
slouken@5154
   495
            SDL_UpdateTexture(texture, NULL, surface->pixels,
slouken@5154
   496
                              surface->pitch);
slouken@5154
   497
            SDL_UnlockSurface(surface);
slouken@5154
   498
        } else {
slouken@5154
   499
            SDL_UpdateTexture(texture, NULL, surface->pixels,
slouken@5154
   500
                              surface->pitch);
slouken@5154
   501
        }
slouken@5154
   502
    } else {
slouken@5154
   503
        SDL_PixelFormat dst_fmt;
slouken@5154
   504
        SDL_Surface *dst = NULL;
slouken@5154
   505
slouken@5154
   506
        /* Set up a destination surface for the texture update */
slouken@5154
   507
        SDL_InitFormat(&dst_fmt, bpp, Rmask, Gmask, Bmask, Amask);
slouken@5154
   508
        dst = SDL_ConvertSurface(surface, &dst_fmt, 0);
slouken@5154
   509
        if (dst) {
slouken@5154
   510
            SDL_UpdateTexture(texture, NULL, dst->pixels, dst->pitch);
slouken@5154
   511
            SDL_FreeSurface(dst);
slouken@5154
   512
        }
slouken@5154
   513
        if (!dst) {
slouken@5154
   514
            SDL_DestroyTexture(texture);
slouken@5154
   515
            return 0;
slouken@5154
   516
        }
slouken@5154
   517
    }
slouken@5154
   518
slouken@5154
   519
    {
slouken@5154
   520
        Uint8 r, g, b, a;
slouken@5154
   521
        SDL_BlendMode blendMode;
slouken@5154
   522
slouken@5154
   523
        SDL_GetSurfaceColorMod(surface, &r, &g, &b);
slouken@5154
   524
        SDL_SetTextureColorMod(texture, r, g, b);
slouken@5154
   525
slouken@5154
   526
        SDL_GetSurfaceAlphaMod(surface, &a);
slouken@5154
   527
        SDL_SetTextureAlphaMod(texture, a);
slouken@5154
   528
slouken@5154
   529
        if (SDL_GetColorKey(surface, NULL) == 0) {
slouken@5154
   530
            /* We converted to a texture with alpha format */
slouken@5154
   531
            SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
slouken@5154
   532
        } else {
slouken@5154
   533
            SDL_GetSurfaceBlendMode(surface, &blendMode);
slouken@5154
   534
            SDL_SetTextureBlendMode(texture, blendMode);
slouken@5154
   535
        }
slouken@5154
   536
    }
slouken@5154
   537
    return texture;
slouken@5154
   538
}
slouken@5154
   539
slouken@5154
   540
int
slouken@5154
   541
SDL_QueryTexture(SDL_Texture * texture, Uint32 * format, int *access,
slouken@5154
   542
                 int *w, int *h)
slouken@5154
   543
{
slouken@5154
   544
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   545
slouken@5154
   546
    if (format) {
slouken@5154
   547
        *format = texture->format;
slouken@5154
   548
    }
slouken@5154
   549
    if (access) {
slouken@5154
   550
        *access = texture->access;
slouken@5154
   551
    }
slouken@5154
   552
    if (w) {
slouken@5154
   553
        *w = texture->w;
slouken@5154
   554
    }
slouken@5154
   555
    if (h) {
slouken@5154
   556
        *h = texture->h;
slouken@5154
   557
    }
slouken@5154
   558
    return 0;
slouken@5154
   559
}
slouken@5154
   560
slouken@5154
   561
int
slouken@5154
   562
SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
slouken@5154
   563
{
slouken@5154
   564
    SDL_Renderer *renderer;
slouken@5154
   565
slouken@5154
   566
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   567
slouken@5154
   568
    renderer = texture->renderer;
slouken@5154
   569
    if (r < 255 || g < 255 || b < 255) {
slouken@5154
   570
        texture->modMode |= SDL_TEXTUREMODULATE_COLOR;
slouken@5154
   571
    } else {
slouken@5154
   572
        texture->modMode &= ~SDL_TEXTUREMODULATE_COLOR;
slouken@5154
   573
    }
slouken@5154
   574
    texture->r = r;
slouken@5154
   575
    texture->g = g;
slouken@5154
   576
    texture->b = b;
slouken@5156
   577
    if (texture->native) {
slouken@5156
   578
        return SDL_SetTextureColorMod(texture->native, r, g, b);
slouken@5156
   579
    } else if (renderer->SetTextureColorMod) {
slouken@5154
   580
        return renderer->SetTextureColorMod(renderer, texture);
slouken@5154
   581
    } else {
slouken@5154
   582
        return 0;
slouken@5154
   583
    }
slouken@5154
   584
}
slouken@5154
   585
slouken@5154
   586
int
slouken@5154
   587
SDL_GetTextureColorMod(SDL_Texture * texture, Uint8 * r, Uint8 * g,
slouken@5154
   588
                       Uint8 * b)
slouken@5154
   589
{
slouken@5154
   590
    SDL_Renderer *renderer;
slouken@5154
   591
slouken@5154
   592
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   593
slouken@5154
   594
    renderer = texture->renderer;
slouken@5154
   595
    if (r) {
slouken@5154
   596
        *r = texture->r;
slouken@5154
   597
    }
slouken@5154
   598
    if (g) {
slouken@5154
   599
        *g = texture->g;
slouken@5154
   600
    }
slouken@5154
   601
    if (b) {
slouken@5154
   602
        *b = texture->b;
slouken@5154
   603
    }
slouken@5154
   604
    return 0;
slouken@5154
   605
}
slouken@5154
   606
slouken@5154
   607
int
slouken@5154
   608
SDL_SetTextureAlphaMod(SDL_Texture * texture, Uint8 alpha)
slouken@5154
   609
{
slouken@5154
   610
    SDL_Renderer *renderer;
slouken@5154
   611
slouken@5154
   612
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   613
slouken@5154
   614
    renderer = texture->renderer;
slouken@5154
   615
    if (alpha < 255) {
slouken@5154
   616
        texture->modMode |= SDL_TEXTUREMODULATE_ALPHA;
slouken@5154
   617
    } else {
slouken@5154
   618
        texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
slouken@5154
   619
    }
slouken@5154
   620
    texture->a = alpha;
slouken@5156
   621
    if (texture->native) {
slouken@5156
   622
        return SDL_SetTextureAlphaMod(texture->native, alpha);
slouken@5156
   623
    } else if (renderer->SetTextureAlphaMod) {
slouken@5154
   624
        return renderer->SetTextureAlphaMod(renderer, texture);
slouken@5154
   625
    } else {
slouken@5154
   626
        return 0;
slouken@5154
   627
    }
slouken@5154
   628
}
slouken@5154
   629
slouken@5154
   630
int
slouken@5154
   631
SDL_GetTextureAlphaMod(SDL_Texture * texture, Uint8 * alpha)
slouken@5154
   632
{
slouken@5154
   633
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   634
slouken@5154
   635
    if (alpha) {
slouken@5154
   636
        *alpha = texture->a;
slouken@5154
   637
    }
slouken@5154
   638
    return 0;
slouken@5154
   639
}
slouken@5154
   640
slouken@5154
   641
int
slouken@5154
   642
SDL_SetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode blendMode)
slouken@5154
   643
{
slouken@5154
   644
    SDL_Renderer *renderer;
slouken@5154
   645
slouken@5154
   646
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   647
slouken@5154
   648
    renderer = texture->renderer;
slouken@5154
   649
    texture->blendMode = blendMode;
slouken@5156
   650
    if (texture->native) {
slouken@5156
   651
        return SDL_SetTextureBlendMode(texture, blendMode);
slouken@5156
   652
    } else if (renderer->SetTextureBlendMode) {
slouken@5154
   653
        return renderer->SetTextureBlendMode(renderer, texture);
slouken@5154
   654
    } else {
slouken@5154
   655
        return 0;
slouken@5154
   656
    }
slouken@5154
   657
}
slouken@5154
   658
slouken@5154
   659
int
slouken@5154
   660
SDL_GetTextureBlendMode(SDL_Texture * texture, SDL_BlendMode *blendMode)
slouken@5154
   661
{
slouken@5154
   662
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   663
slouken@5154
   664
    if (blendMode) {
slouken@5154
   665
        *blendMode = texture->blendMode;
slouken@5154
   666
    }
slouken@5154
   667
    return 0;
slouken@5154
   668
}
slouken@5154
   669
slouken@5156
   670
static int
slouken@5156
   671
SDL_UpdateTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   672
                     const void *pixels, int pitch)
slouken@5156
   673
{
slouken@5156
   674
    SDL_Texture *native = texture->native;
slouken@5156
   675
    SDL_Rect full_rect;
slouken@5156
   676
slouken@5156
   677
    if (SDL_SW_UpdateYUVTexture(texture->yuv, rect, pixels, pitch) < 0) {
slouken@5156
   678
        return -1;
slouken@5156
   679
    }
slouken@5156
   680
slouken@5156
   681
    full_rect.x = 0;
slouken@5156
   682
    full_rect.y = 0;
slouken@5156
   683
    full_rect.w = texture->w;
slouken@5156
   684
    full_rect.h = texture->h;
slouken@5156
   685
    rect = &full_rect;
slouken@5156
   686
slouken@5156
   687
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5156
   688
        /* We can lock the texture and copy to it */
slouken@5156
   689
        void *native_pixels;
slouken@5156
   690
        int native_pitch;
slouken@5156
   691
slouken@5156
   692
        if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   693
            return -1;
slouken@5156
   694
        }
slouken@5156
   695
        SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
slouken@5156
   696
                            rect->w, rect->h, native_pixels, native_pitch);
slouken@5156
   697
        SDL_UnlockTexture(native);
slouken@5156
   698
    } else {
slouken@5156
   699
        /* Use a temporary buffer for updating */
slouken@5156
   700
        void *temp_pixels;
slouken@5156
   701
        int temp_pitch;
slouken@5156
   702
slouken@5156
   703
        temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
slouken@5156
   704
        temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@5156
   705
        if (!temp_pixels) {
slouken@5156
   706
            SDL_OutOfMemory();
slouken@5156
   707
            return -1;
slouken@5156
   708
        }
slouken@5156
   709
        SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
slouken@5156
   710
                            rect->w, rect->h, temp_pixels, temp_pitch);
slouken@5156
   711
        SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
slouken@5156
   712
        SDL_free(temp_pixels);
slouken@5156
   713
    }
slouken@5156
   714
    return 0;
slouken@5156
   715
}
slouken@5156
   716
slouken@5156
   717
static int
slouken@5156
   718
SDL_UpdateTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   719
                        const void *pixels, int pitch)
slouken@5156
   720
{
slouken@5156
   721
    SDL_Texture *native = texture->native;
slouken@5156
   722
slouken@5156
   723
    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
slouken@5156
   724
        /* We can lock the texture and copy to it */
slouken@5156
   725
        void *native_pixels;
slouken@5156
   726
        int native_pitch;
slouken@5156
   727
slouken@5156
   728
        if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   729
            return -1;
slouken@5156
   730
        }
slouken@5156
   731
        SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
   732
                          texture->format, pixels, pitch,
slouken@5156
   733
                          native->format, native_pixels, native_pitch);
slouken@5156
   734
        SDL_UnlockTexture(native);
slouken@5156
   735
    } else {
slouken@5156
   736
        /* Use a temporary buffer for updating */
slouken@5156
   737
        void *temp_pixels;
slouken@5156
   738
        int temp_pitch;
slouken@5156
   739
slouken@5156
   740
        temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
slouken@5156
   741
        temp_pixels = SDL_malloc(rect->h * temp_pitch);
slouken@5156
   742
        if (!temp_pixels) {
slouken@5156
   743
            SDL_OutOfMemory();
slouken@5156
   744
            return -1;
slouken@5156
   745
        }
slouken@5156
   746
        SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
   747
                          texture->format, pixels, pitch,
slouken@5156
   748
                          native->format, temp_pixels, temp_pitch);
slouken@5156
   749
        SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
slouken@5156
   750
        SDL_free(temp_pixels);
slouken@5156
   751
    }
slouken@5156
   752
    return 0;
slouken@5156
   753
}
slouken@5156
   754
slouken@5154
   755
int
slouken@5154
   756
SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5154
   757
                  const void *pixels, int pitch)
slouken@5154
   758
{
slouken@5154
   759
    SDL_Renderer *renderer;
slouken@5154
   760
    SDL_Rect full_rect;
slouken@5154
   761
slouken@5154
   762
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   763
slouken@5154
   764
    if (!rect) {
slouken@5154
   765
        full_rect.x = 0;
slouken@5154
   766
        full_rect.y = 0;
slouken@5154
   767
        full_rect.w = texture->w;
slouken@5154
   768
        full_rect.h = texture->h;
slouken@5154
   769
        rect = &full_rect;
slouken@5154
   770
    }
slouken@5156
   771
slouken@5156
   772
    if (texture->yuv) {
slouken@5156
   773
        return SDL_UpdateTextureYUV(texture, rect, pixels, pitch);
slouken@5156
   774
    } else if (texture->native) {
slouken@5156
   775
        return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
slouken@5156
   776
    } else {
slouken@5156
   777
        renderer = texture->renderer;
slouken@5156
   778
        return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
slouken@5156
   779
    }
slouken@5156
   780
}
slouken@5156
   781
slouken@5156
   782
static int
slouken@5156
   783
SDL_LockTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   784
                   void **pixels, int *pitch)
slouken@5156
   785
{
slouken@5156
   786
    return SDL_SW_LockYUVTexture(texture->yuv, rect, pixels, pitch);
slouken@5156
   787
}
slouken@5156
   788
slouken@5156
   789
static int
slouken@5156
   790
SDL_LockTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5156
   791
                      void **pixels, int *pitch)
slouken@5156
   792
{
slouken@5156
   793
    texture->locked_rect = *rect;
slouken@5156
   794
    *pixels = (void *) ((Uint8 *) texture->pixels +
slouken@5156
   795
                        rect->y * texture->pitch +
slouken@5156
   796
                        rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@5156
   797
    *pitch = texture->pitch;
slouken@5156
   798
    return 0;
slouken@5154
   799
}
slouken@5154
   800
slouken@5154
   801
int
slouken@5156
   802
SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
slouken@5154
   803
                void **pixels, int *pitch)
slouken@5154
   804
{
slouken@5154
   805
    SDL_Renderer *renderer;
slouken@5154
   806
    SDL_Rect full_rect;
slouken@5154
   807
slouken@5154
   808
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
   809
slouken@5154
   810
    if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
slouken@5154
   811
        SDL_SetError("SDL_LockTexture(): texture must be streaming");
slouken@5154
   812
        return -1;
slouken@5154
   813
    }
slouken@5156
   814
slouken@5154
   815
    if (!rect) {
slouken@5154
   816
        full_rect.x = 0;
slouken@5154
   817
        full_rect.y = 0;
slouken@5154
   818
        full_rect.w = texture->w;
slouken@5154
   819
        full_rect.h = texture->h;
slouken@5154
   820
        rect = &full_rect;
slouken@5154
   821
    }
slouken@5156
   822
slouken@5156
   823
    if (texture->yuv) {
slouken@5156
   824
        return SDL_LockTextureYUV(texture, rect, pixels, pitch);
slouken@5156
   825
    } else if (texture->native) {
slouken@5156
   826
        return SDL_LockTextureNative(texture, rect, pixels, pitch);
slouken@5156
   827
    } else {
slouken@5156
   828
        renderer = texture->renderer;
slouken@5156
   829
        return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
slouken@5156
   830
    }
slouken@5156
   831
}
slouken@5156
   832
slouken@5156
   833
static void
slouken@5156
   834
SDL_UnlockTextureYUV(SDL_Texture * texture)
slouken@5156
   835
{
slouken@5156
   836
    SDL_Texture *native = texture->native;
slouken@5156
   837
    void *native_pixels;
slouken@5156
   838
    int native_pitch;
slouken@5156
   839
    SDL_Rect rect;
slouken@5156
   840
slouken@5156
   841
    rect.x = 0;
slouken@5156
   842
    rect.y = 0;
slouken@5156
   843
    rect.w = texture->w;
slouken@5156
   844
    rect.h = texture->h;
slouken@5156
   845
slouken@5156
   846
    if (SDL_LockTexture(native, &rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   847
        return;
slouken@5156
   848
    }
slouken@5156
   849
    SDL_SW_CopyYUVToRGB(texture->yuv, &rect, native->format,
slouken@5156
   850
                        rect.w, rect.h, native_pixels, native_pitch);
slouken@5156
   851
    SDL_UnlockTexture(native);
slouken@5156
   852
}
slouken@5156
   853
slouken@5156
   854
void
slouken@5156
   855
SDL_UnlockTextureNative(SDL_Texture * texture)
slouken@5156
   856
{
slouken@5156
   857
    SDL_Texture *native = texture->native;
slouken@5156
   858
    void *native_pixels;
slouken@5156
   859
    int native_pitch;
slouken@5156
   860
    const SDL_Rect *rect = &texture->locked_rect;
slouken@5156
   861
    const void* pixels = (void *) ((Uint8 *) texture->pixels +
slouken@5156
   862
                        rect->y * texture->pitch +
slouken@5156
   863
                        rect->x * SDL_BYTESPERPIXEL(texture->format));
slouken@5156
   864
    int pitch = texture->pitch;
slouken@5156
   865
slouken@5156
   866
    if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
slouken@5156
   867
        return;
slouken@5156
   868
    }
slouken@5156
   869
    SDL_ConvertPixels(rect->w, rect->h,
slouken@5156
   870
                      texture->format, pixels, pitch,
slouken@5156
   871
                      native->format, native_pixels, native_pitch);
slouken@5156
   872
    SDL_UnlockTexture(native);
slouken@5154
   873
}
slouken@5154
   874
slouken@5154
   875
void
slouken@5154
   876
SDL_UnlockTexture(SDL_Texture * texture)
slouken@5154
   877
{
slouken@5154
   878
    SDL_Renderer *renderer;
slouken@5154
   879
slouken@5154
   880
    CHECK_TEXTURE_MAGIC(texture, );
slouken@5154
   881
slouken@5154
   882
    if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
slouken@5154
   883
        return;
slouken@5154
   884
    }
slouken@5156
   885
    if (texture->yuv) {
slouken@5156
   886
        SDL_UnlockTextureYUV(texture);
slouken@5156
   887
    } else if (texture->native) {
slouken@5156
   888
        SDL_UnlockTextureNative(texture);
slouken@5156
   889
    } else {
slouken@5156
   890
        renderer = texture->renderer;
slouken@5156
   891
        renderer->UnlockTexture(renderer, texture);
slouken@5154
   892
    }
slouken@5154
   893
}
slouken@5154
   894
slouken@5154
   895
int
slouken@5154
   896
SDL_SetRenderDrawColor(SDL_Renderer * renderer,
slouken@5154
   897
                       Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5154
   898
{
slouken@5154
   899
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   900
slouken@5154
   901
    renderer->r = r;
slouken@5154
   902
    renderer->g = g;
slouken@5154
   903
    renderer->b = b;
slouken@5154
   904
    renderer->a = a;
slouken@5154
   905
    return 0;
slouken@5154
   906
}
slouken@5154
   907
slouken@5154
   908
int
slouken@5154
   909
SDL_GetRenderDrawColor(SDL_Renderer * renderer,
slouken@5154
   910
                       Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
slouken@5154
   911
{
slouken@5154
   912
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   913
slouken@5154
   914
    if (r) {
slouken@5154
   915
        *r = renderer->r;
slouken@5154
   916
    }
slouken@5154
   917
    if (g) {
slouken@5154
   918
        *g = renderer->g;
slouken@5154
   919
    }
slouken@5154
   920
    if (b) {
slouken@5154
   921
        *b = renderer->b;
slouken@5154
   922
    }
slouken@5154
   923
    if (a) {
slouken@5154
   924
        *a = renderer->a;
slouken@5154
   925
    }
slouken@5154
   926
    return 0;
slouken@5154
   927
}
slouken@5154
   928
slouken@5154
   929
int
slouken@5154
   930
SDL_SetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
slouken@5154
   931
{
slouken@5154
   932
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   933
slouken@5154
   934
    renderer->blendMode = blendMode;
slouken@5154
   935
    return 0;
slouken@5154
   936
}
slouken@5154
   937
slouken@5154
   938
int
slouken@5154
   939
SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer, SDL_BlendMode *blendMode)
slouken@5154
   940
{
slouken@5154
   941
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   942
slouken@5154
   943
    *blendMode = renderer->blendMode;
slouken@5154
   944
    return 0;
slouken@5154
   945
}
slouken@5154
   946
slouken@5154
   947
int
slouken@5154
   948
SDL_RenderClear(SDL_Renderer * renderer)
slouken@5154
   949
{
slouken@5154
   950
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   951
slouken@5154
   952
    if (!renderer->RenderClear) {
slouken@5154
   953
        SDL_BlendMode blendMode = renderer->blendMode;
slouken@5154
   954
        int status;
slouken@5154
   955
slouken@5154
   956
        if (blendMode >= SDL_BLENDMODE_BLEND) {
slouken@5154
   957
            SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
slouken@5154
   958
        }
slouken@5154
   959
slouken@5154
   960
        status = SDL_RenderFillRect(renderer, NULL);
slouken@5154
   961
slouken@5154
   962
        if (blendMode >= SDL_BLENDMODE_BLEND) {
slouken@5154
   963
            SDL_SetRenderDrawBlendMode(renderer, blendMode);
slouken@5154
   964
        }
slouken@5154
   965
        return status;
slouken@5154
   966
    }
slouken@5154
   967
    return renderer->RenderClear(renderer);
slouken@5154
   968
}
slouken@5154
   969
slouken@5154
   970
int
slouken@5154
   971
SDL_RenderDrawPoint(SDL_Renderer * renderer, int x, int y)
slouken@5154
   972
{
slouken@5154
   973
    SDL_Point point;
slouken@5154
   974
slouken@5154
   975
    point.x = x;
slouken@5154
   976
    point.y = y;
slouken@5154
   977
    return SDL_RenderDrawPoints(renderer, &point, 1);
slouken@5154
   978
}
slouken@5154
   979
slouken@5154
   980
int
slouken@5154
   981
SDL_RenderDrawPoints(SDL_Renderer * renderer,
slouken@5154
   982
                     const SDL_Point * points, int count)
slouken@5154
   983
{
slouken@5154
   984
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
   985
slouken@5154
   986
    if (!points) {
slouken@5154
   987
        SDL_SetError("SDL_RenderDrawPoints(): Passed NULL points");
slouken@5154
   988
        return -1;
slouken@5154
   989
    }
slouken@5154
   990
    if (count < 1) {
slouken@5154
   991
        return 0;
slouken@5154
   992
    }
slouken@5154
   993
    return renderer->RenderDrawPoints(renderer, points, count);
slouken@5154
   994
}
slouken@5154
   995
slouken@5154
   996
int
slouken@5154
   997
SDL_RenderDrawLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
slouken@5154
   998
{
slouken@5154
   999
    SDL_Point points[2];
slouken@5154
  1000
slouken@5154
  1001
    points[0].x = x1;
slouken@5154
  1002
    points[0].y = y1;
slouken@5154
  1003
    points[1].x = x2;
slouken@5154
  1004
    points[1].y = y2;
slouken@5154
  1005
    return SDL_RenderDrawLines(renderer, points, 2);
slouken@5154
  1006
}
slouken@5154
  1007
slouken@5154
  1008
int
slouken@5154
  1009
SDL_RenderDrawLines(SDL_Renderer * renderer,
slouken@5154
  1010
                    const SDL_Point * points, int count)
slouken@5154
  1011
{
slouken@5154
  1012
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1013
slouken@5154
  1014
    if (!points) {
slouken@5154
  1015
        SDL_SetError("SDL_RenderDrawLines(): Passed NULL points");
slouken@5154
  1016
        return -1;
slouken@5154
  1017
    }
slouken@5154
  1018
    if (count < 2) {
slouken@5154
  1019
        return 0;
slouken@5154
  1020
    }
slouken@5154
  1021
    return renderer->RenderDrawLines(renderer, points, count);
slouken@5154
  1022
}
slouken@5154
  1023
slouken@5154
  1024
int
slouken@5154
  1025
SDL_RenderDrawRect(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@5154
  1026
{
slouken@5154
  1027
    SDL_Rect full_rect;
slouken@5154
  1028
    SDL_Point points[5];
slouken@5154
  1029
slouken@5154
  1030
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1031
slouken@5154
  1032
    /* If 'rect' == NULL, then outline the whole surface */
slouken@5154
  1033
    if (!rect) {
slouken@5154
  1034
        SDL_Window *window = renderer->window;
slouken@5154
  1035
slouken@5154
  1036
        full_rect.x = 0;
slouken@5154
  1037
        full_rect.y = 0;
slouken@5154
  1038
        SDL_GetWindowSize(window, &full_rect.w, &full_rect.h);
slouken@5154
  1039
        rect = &full_rect;
slouken@5154
  1040
    }
slouken@5154
  1041
slouken@5154
  1042
    points[0].x = rect->x;
slouken@5154
  1043
    points[0].y = rect->y;
slouken@5154
  1044
    points[1].x = rect->x+rect->w-1;
slouken@5154
  1045
    points[1].y = rect->y;
slouken@5154
  1046
    points[2].x = rect->x+rect->w-1;
slouken@5154
  1047
    points[2].y = rect->y+rect->h-1;
slouken@5154
  1048
    points[3].x = rect->x;
slouken@5154
  1049
    points[3].y = rect->y+rect->h-1;
slouken@5154
  1050
    points[4].x = rect->x;
slouken@5154
  1051
    points[4].y = rect->y;
slouken@5154
  1052
    return SDL_RenderDrawLines(renderer, points, 5);
slouken@5154
  1053
}
slouken@5154
  1054
slouken@5154
  1055
int
slouken@5154
  1056
SDL_RenderDrawRects(SDL_Renderer * renderer,
slouken@5154
  1057
                    const SDL_Rect ** rects, int count)
slouken@5154
  1058
{
slouken@5154
  1059
    int i;
slouken@5154
  1060
slouken@5154
  1061
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1062
slouken@5154
  1063
    if (!rects) {
slouken@5154
  1064
        SDL_SetError("SDL_RenderDrawRects(): Passed NULL rects");
slouken@5154
  1065
        return -1;
slouken@5154
  1066
    }
slouken@5154
  1067
    if (count < 1) {
slouken@5154
  1068
        return 0;
slouken@5154
  1069
    }
slouken@5154
  1070
slouken@5154
  1071
    /* Check for NULL rect, which means fill entire window */
slouken@5154
  1072
    for (i = 0; i < count; ++i) {
slouken@5154
  1073
        if (SDL_RenderDrawRect(renderer, rects[i]) < 0) {
slouken@5154
  1074
            return -1;
slouken@5154
  1075
        }
slouken@5154
  1076
    }
slouken@5154
  1077
    return 0;
slouken@5154
  1078
}
slouken@5154
  1079
slouken@5154
  1080
int
slouken@5154
  1081
SDL_RenderFillRect(SDL_Renderer * renderer, const SDL_Rect * rect)
slouken@5154
  1082
{
slouken@5154
  1083
    return SDL_RenderFillRects(renderer, &rect, 1);
slouken@5154
  1084
}
slouken@5154
  1085
slouken@5154
  1086
int
slouken@5154
  1087
SDL_RenderFillRects(SDL_Renderer * renderer,
slouken@5154
  1088
                    const SDL_Rect ** rects, int count)
slouken@5154
  1089
{
slouken@5154
  1090
    int i;
slouken@5154
  1091
slouken@5154
  1092
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1093
slouken@5154
  1094
    if (!rects) {
slouken@5154
  1095
        SDL_SetError("SDL_RenderFillRects(): Passed NULL rects");
slouken@5154
  1096
        return -1;
slouken@5154
  1097
    }
slouken@5154
  1098
    if (count < 1) {
slouken@5154
  1099
        return 0;
slouken@5154
  1100
    }
slouken@5154
  1101
slouken@5154
  1102
    /* Check for NULL rect, which means fill entire window */
slouken@5154
  1103
    for (i = 0; i < count; ++i) {
slouken@5154
  1104
        if (rects[i] == NULL) {
slouken@5154
  1105
            SDL_Window *window = renderer->window;
slouken@5154
  1106
            SDL_Rect full_rect;
slouken@5154
  1107
            const SDL_Rect *rect;
slouken@5154
  1108
slouken@5154
  1109
            full_rect.x = 0;
slouken@5154
  1110
            full_rect.y = 0;
slouken@5154
  1111
            SDL_GetWindowSize(window, &full_rect.w, &full_rect.h);
slouken@5154
  1112
            rect = &full_rect;
slouken@5154
  1113
            return renderer->RenderFillRects(renderer, &rect, 1);
slouken@5154
  1114
        }
slouken@5154
  1115
    }
slouken@5154
  1116
    return renderer->RenderFillRects(renderer, rects, count);
slouken@5154
  1117
}
slouken@5154
  1118
slouken@5154
  1119
int
slouken@5154
  1120
SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5154
  1121
               const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@5154
  1122
{
slouken@5154
  1123
    SDL_Window *window;
slouken@5154
  1124
    SDL_Rect real_srcrect;
slouken@5154
  1125
    SDL_Rect real_dstrect;
slouken@5154
  1126
slouken@5154
  1127
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1128
    CHECK_TEXTURE_MAGIC(texture, -1);
slouken@5154
  1129
slouken@5154
  1130
    if (renderer != texture->renderer) {
slouken@5154
  1131
        SDL_SetError("Texture was not created with this renderer");
slouken@5154
  1132
        return -1;
slouken@5154
  1133
    }
slouken@5154
  1134
    window = renderer->window;
slouken@5154
  1135
slouken@5154
  1136
    real_srcrect.x = 0;
slouken@5154
  1137
    real_srcrect.y = 0;
slouken@5154
  1138
    real_srcrect.w = texture->w;
slouken@5154
  1139
    real_srcrect.h = texture->h;
slouken@5154
  1140
    if (srcrect) {
slouken@5154
  1141
        if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {
slouken@5154
  1142
            return 0;
slouken@5154
  1143
        }
slouken@5154
  1144
    }
slouken@5154
  1145
slouken@5154
  1146
    real_dstrect.x = 0;
slouken@5154
  1147
    real_dstrect.y = 0;
slouken@5154
  1148
    SDL_GetWindowSize(window, &real_dstrect.w, &real_dstrect.h);
slouken@5154
  1149
    if (dstrect) {
slouken@5154
  1150
        if (!SDL_IntersectRect(dstrect, &real_dstrect, &real_dstrect)) {
slouken@5154
  1151
            return 0;
slouken@5154
  1152
        }
slouken@5154
  1153
        /* Clip srcrect by the same amount as dstrect was clipped */
slouken@5154
  1154
        if (dstrect->w != real_dstrect.w) {
slouken@5154
  1155
            int deltax = (real_dstrect.x - dstrect->x);
slouken@5154
  1156
            int deltaw = (real_dstrect.w - dstrect->w);
slouken@5154
  1157
            real_srcrect.x += (deltax * real_srcrect.w) / dstrect->w;
slouken@5154
  1158
            real_srcrect.w += (deltaw * real_srcrect.w) / dstrect->w;
slouken@5154
  1159
        }
slouken@5154
  1160
        if (dstrect->h != real_dstrect.h) {
slouken@5154
  1161
            int deltay = (real_dstrect.y - dstrect->y);
slouken@5154
  1162
            int deltah = (real_dstrect.h - dstrect->h);
slouken@5154
  1163
            real_srcrect.y += (deltay * real_srcrect.h) / dstrect->h;
slouken@5154
  1164
            real_srcrect.h += (deltah * real_srcrect.h) / dstrect->h;
slouken@5154
  1165
        }
slouken@5154
  1166
    }
slouken@5154
  1167
slouken@5156
  1168
    if (texture->native) {
slouken@5156
  1169
        texture = texture->native;
slouken@5156
  1170
    }
slouken@5156
  1171
slouken@5154
  1172
    return renderer->RenderCopy(renderer, texture, &real_srcrect,
slouken@5154
  1173
                                &real_dstrect);
slouken@5154
  1174
}
slouken@5154
  1175
slouken@5154
  1176
int
slouken@5154
  1177
SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@5154
  1178
                     Uint32 format, void * pixels, int pitch)
slouken@5154
  1179
{
slouken@5154
  1180
    SDL_Window *window;
slouken@5154
  1181
    SDL_Rect real_rect;
slouken@5154
  1182
slouken@5154
  1183
    CHECK_RENDERER_MAGIC(renderer, -1);
slouken@5154
  1184
slouken@5154
  1185
    if (!renderer->RenderReadPixels) {
slouken@5154
  1186
        SDL_Unsupported();
slouken@5154
  1187
        return -1;
slouken@5154
  1188
    }
slouken@5154
  1189
    window = renderer->window;
slouken@5154
  1190
slouken@5154
  1191
    if (!format) {
slouken@5154
  1192
        format = SDL_GetWindowPixelFormat(window);
slouken@5154
  1193
    }
slouken@5154
  1194
slouken@5154
  1195
    real_rect.x = 0;
slouken@5154
  1196
    real_rect.y = 0;
slouken@5154
  1197
    SDL_GetWindowSize(window, &real_rect.w, &real_rect.h);
slouken@5154
  1198
    if (rect) {
slouken@5154
  1199
        if (!SDL_IntersectRect(rect, &real_rect, &real_rect)) {
slouken@5154
  1200
            return 0;
slouken@5154
  1201
        }
slouken@5154
  1202
        if (real_rect.y > rect->y) {
slouken@5154
  1203
            pixels = (Uint8 *)pixels + pitch * (real_rect.y - rect->y);
slouken@5154
  1204
        }
slouken@5154
  1205
        if (real_rect.x > rect->x) {
slouken@5154
  1206
            int bpp = SDL_BYTESPERPIXEL(SDL_GetWindowPixelFormat(window));
slouken@5154
  1207
            pixels = (Uint8 *)pixels + bpp * (real_rect.x - rect->x);
slouken@5154
  1208
        }
slouken@5154
  1209
    }
slouken@5154
  1210
slouken@5154
  1211
    return renderer->RenderReadPixels(renderer, &real_rect,
slouken@5154
  1212
                                      format, pixels, pitch);
slouken@5154
  1213
}
slouken@5154
  1214
slouken@5154
  1215
void
slouken@5154
  1216
SDL_RenderPresent(SDL_Renderer * renderer)
slouken@5154
  1217
{
slouken@5154
  1218
    CHECK_RENDERER_MAGIC(renderer, );
slouken@5154
  1219
slouken@5154
  1220
    renderer->RenderPresent(renderer);
slouken@5154
  1221
}
slouken@5154
  1222
slouken@5154
  1223
void
slouken@5154
  1224
SDL_DestroyTexture(SDL_Texture * texture)
slouken@5154
  1225
{
slouken@5154
  1226
    SDL_Renderer *renderer;
slouken@5154
  1227
slouken@5154
  1228
    CHECK_TEXTURE_MAGIC(texture, );
slouken@5154
  1229
    texture->magic = NULL;
slouken@5154
  1230
slouken@5154
  1231
    renderer = texture->renderer;
slouken@5154
  1232
    if (texture->next) {
slouken@5154
  1233
        texture->next->prev = texture->prev;
slouken@5154
  1234
    }
slouken@5154
  1235
    if (texture->prev) {
slouken@5154
  1236
        texture->prev->next = texture->next;
slouken@5154
  1237
    } else {
slouken@5154
  1238
        renderer->textures = texture->next;
slouken@5154
  1239
    }
slouken@5154
  1240
slouken@5156
  1241
    if (texture->native) {
slouken@5156
  1242
        SDL_DestroyTexture(texture->native);
slouken@5156
  1243
    }
slouken@5156
  1244
    if (texture->yuv) {
slouken@5156
  1245
        SDL_SW_DestroyYUVTexture(texture->yuv);
slouken@5156
  1246
    }
slouken@5156
  1247
    if (texture->pixels) {
slouken@5156
  1248
        SDL_free(texture->pixels);
slouken@5156
  1249
    }
slouken@5156
  1250
slouken@5154
  1251
    renderer->DestroyTexture(renderer, texture);
slouken@5154
  1252
    SDL_free(texture);
slouken@5154
  1253
}
slouken@5154
  1254
slouken@5154
  1255
void
slouken@5154
  1256
SDL_DestroyRenderer(SDL_Renderer * renderer)
slouken@5154
  1257
{
slouken@5154
  1258
    CHECK_RENDERER_MAGIC(renderer, );
slouken@5154
  1259
slouken@5154
  1260
    SDL_DelEventWatch(SDL_RendererEventWatch, renderer);
slouken@5154
  1261
slouken@5154
  1262
    /* Free existing textures for this renderer */
slouken@5154
  1263
    while (renderer->textures) {
slouken@5154
  1264
        SDL_DestroyTexture(renderer->textures);
slouken@5154
  1265
    }
slouken@5154
  1266
slouken@5154
  1267
    /* It's no longer magical... */
slouken@5154
  1268
    renderer->magic = NULL;
slouken@5154
  1269
slouken@5154
  1270
    /* Free the renderer instance */
slouken@5154
  1271
    renderer->DestroyRenderer(renderer);
slouken@5154
  1272
}
slouken@5154
  1273
slouken@5154
  1274
/* vi: set ts=4 sw=4 expandtab: */