src/render/software/SDL_renderer_sw.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 03 Feb 2011 02:45:29 -0800
changeset 5163 d72793305335
parent 5157 657543cc92f9
child 5166 4d39eeaad00b
permissions -rw-r--r--
Making the API simpler, moved the surface drawing functions to the software renderer.
slouken@1895
     1
/*
slouken@1895
     2
    SDL - Simple DirectMedia Layer
slouken@3697
     3
    Copyright (C) 1997-2010 Sam Lantinga
slouken@1895
     4
slouken@1895
     5
    This library is free software; you can redistribute it and/or
slouken@1895
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1895
     7
    License as published by the Free Software Foundation; either
slouken@1895
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1895
     9
slouken@1895
    10
    This library is distributed in the hope that it will be useful,
slouken@1895
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1895
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1895
    13
    Lesser General Public License for more details.
slouken@1895
    14
slouken@1895
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1895
    16
    License along with this library; if not, write to the Free Software
slouken@1895
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1895
    18
slouken@1895
    19
    Sam Lantinga
slouken@1895
    20
    slouken@libsdl.org
slouken@1895
    21
*/
slouken@1895
    22
#include "SDL_config.h"
slouken@1895
    23
slouken@5154
    24
#include "../SDL_sysrender.h"
slouken@5154
    25
#include "../../video/SDL_pixels_c.h"
slouken@1895
    26
slouken@5163
    27
#include "SDL_draw.h"
slouken@5163
    28
#include "SDL_blendfillrect.h"
slouken@5163
    29
#include "SDL_blendline.h"
slouken@5163
    30
#include "SDL_blendpoint.h"
slouken@5163
    31
#include "SDL_drawline.h"
slouken@5163
    32
#include "SDL_drawpoint.h"
slouken@5163
    33
slouken@1895
    34
slouken@1895
    35
/* SDL surface based renderer implementation */
slouken@1895
    36
slouken@1918
    37
static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@5147
    38
static void SW_WindowEvent(SDL_Renderer * renderer,
slouken@5147
    39
                           const SDL_WindowEvent *event);
slouken@1918
    40
static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1985
    41
static int SW_SetTextureColorMod(SDL_Renderer * renderer,
slouken@1985
    42
                                 SDL_Texture * texture);
slouken@1985
    43
static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
slouken@1985
    44
                                 SDL_Texture * texture);
slouken@5141
    45
static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@5141
    46
                                  SDL_Texture * texture);
slouken@1985
    47
static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    48
                            const SDL_Rect * rect, const void *pixels,
slouken@1985
    49
                            int pitch);
slouken@1918
    50
static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
    51
                          const SDL_Rect * rect, void **pixels, int *pitch);
slouken@1918
    52
static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@3596
    53
static int SW_RenderDrawPoints(SDL_Renderer * renderer,
slouken@3596
    54
                               const SDL_Point * points, int count);
slouken@3596
    55
static int SW_RenderDrawLines(SDL_Renderer * renderer,
slouken@3596
    56
                              const SDL_Point * points, int count);
slouken@3596
    57
static int SW_RenderFillRects(SDL_Renderer * renderer,
slouken@3596
    58
                              const SDL_Rect ** rects, int count);
slouken@1918
    59
static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    60
                         const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@3427
    61
static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
    62
                               Uint32 format, void * pixels, int pitch);
slouken@1918
    63
static void SW_RenderPresent(SDL_Renderer * renderer);
slouken@1918
    64
static void SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1918
    65
static void SW_DestroyRenderer(SDL_Renderer * renderer);
slouken@1895
    66
slouken@1895
    67
slouken@1918
    68
SDL_RenderDriver SW_RenderDriver = {
slouken@1918
    69
    SW_CreateRenderer,
slouken@1895
    70
    {
slouken@1895
    71
     "software",
slouken@5142
    72
     (SDL_RENDERER_PRESENTVSYNC),
slouken@5156
    73
     8,
slouken@1895
    74
     {
slouken@1965
    75
      SDL_PIXELFORMAT_RGB555,
slouken@1965
    76
      SDL_PIXELFORMAT_RGB565,
slouken@1965
    77
      SDL_PIXELFORMAT_RGB888,
slouken@1965
    78
      SDL_PIXELFORMAT_BGR888,
slouken@1965
    79
      SDL_PIXELFORMAT_ARGB8888,
slouken@1965
    80
      SDL_PIXELFORMAT_RGBA8888,
slouken@1965
    81
      SDL_PIXELFORMAT_ABGR8888,
slouken@5156
    82
      SDL_PIXELFORMAT_BGRA8888
slouken@5156
    83
     },
slouken@1895
    84
     0,
slouken@1895
    85
     0}
slouken@1895
    86
};
slouken@1895
    87
slouken@1895
    88
typedef struct
slouken@1895
    89
{
slouken@1907
    90
    Uint32 format;
slouken@1972
    91
    SDL_bool updateSize;
slouken@5142
    92
    SDL_Texture *texture;
slouken@1907
    93
    SDL_Surface surface;
slouken@1895
    94
    SDL_Renderer *renderer;
slouken@1918
    95
} SW_RenderData;
slouken@1895
    96
slouken@1907
    97
static SDL_Texture *
slouken@1907
    98
CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h)
slouken@1907
    99
{
slouken@1907
   100
    SDL_Texture *texture;
slouken@1907
   101
slouken@1920
   102
    texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
slouken@1907
   103
    if (!texture) {
slouken@1907
   104
        SDL_OutOfMemory();
slouken@1907
   105
        return NULL;
slouken@1907
   106
    }
slouken@1907
   107
slouken@1907
   108
    texture->format = format;
slouken@2222
   109
    texture->access = SDL_TEXTUREACCESS_STREAMING;
slouken@1907
   110
    texture->w = w;
slouken@1907
   111
    texture->h = h;
slouken@1907
   112
    texture->renderer = renderer;
slouken@1907
   113
slouken@1907
   114
    if (renderer->CreateTexture(renderer, texture) < 0) {
slouken@1907
   115
        SDL_free(texture);
slouken@1907
   116
        return NULL;
slouken@1907
   117
    }
slouken@1907
   118
    return texture;
slouken@1907
   119
}
slouken@1907
   120
slouken@1907
   121
static void
slouken@1907
   122
DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1907
   123
{
slouken@1907
   124
    renderer->DestroyTexture(renderer, texture);
slouken@1907
   125
    SDL_free(texture);
slouken@1907
   126
}
slouken@1907
   127
slouken@1895
   128
SDL_Renderer *
slouken@1918
   129
SW_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   130
{
slouken@1895
   131
    SDL_Renderer *renderer;
slouken@1918
   132
    SW_RenderData *data;
slouken@5154
   133
    int i;
slouken@5156
   134
    int w, h;
slouken@5154
   135
    Uint32 format;
slouken@1895
   136
    int bpp;
slouken@1895
   137
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@1907
   138
    Uint32 renderer_flags;
slouken@1929
   139
    const char *desired_driver;
slouken@1895
   140
slouken@5154
   141
    format = SDL_GetWindowPixelFormat(window);
slouken@1895
   142
    if (!SDL_PixelFormatEnumToMasks
slouken@5154
   143
        (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@1895
   144
        SDL_SetError("Unknown display format");
slouken@1895
   145
        return NULL;
slouken@1895
   146
    }
slouken@1895
   147
slouken@1895
   148
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   149
    if (!renderer) {
slouken@1895
   150
        SDL_OutOfMemory();
slouken@1895
   151
        return NULL;
slouken@1895
   152
    }
slouken@1895
   153
slouken@1920
   154
    data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   155
    if (!data) {
slouken@1918
   156
        SW_DestroyRenderer(renderer);
slouken@1895
   157
        SDL_OutOfMemory();
slouken@1895
   158
        return NULL;
slouken@1895
   159
    }
slouken@5147
   160
    renderer->WindowEvent = SW_WindowEvent;
slouken@5154
   161
    renderer->CreateTexture = SW_CreateTexture;
slouken@5154
   162
    renderer->SetTextureColorMod = SW_SetTextureColorMod;
slouken@5154
   163
    renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
slouken@5154
   164
    renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
slouken@5154
   165
    renderer->UpdateTexture = SW_UpdateTexture;
slouken@5154
   166
    renderer->LockTexture = SW_LockTexture;
slouken@5154
   167
    renderer->UnlockTexture = SW_UnlockTexture;
slouken@5154
   168
    renderer->DestroyTexture = SW_DestroyTexture;
slouken@3596
   169
    renderer->RenderDrawPoints = SW_RenderDrawPoints;
slouken@3596
   170
    renderer->RenderDrawLines = SW_RenderDrawLines;
slouken@3596
   171
    renderer->RenderFillRects = SW_RenderFillRects;
slouken@1918
   172
    renderer->RenderCopy = SW_RenderCopy;
slouken@3427
   173
    renderer->RenderReadPixels = SW_RenderReadPixels;
slouken@1918
   174
    renderer->RenderPresent = SW_RenderPresent;
slouken@1918
   175
    renderer->DestroyRenderer = SW_DestroyRenderer;
slouken@5154
   176
    renderer->info = SW_RenderDriver.info;
slouken@2227
   177
    renderer->info.flags = 0;
slouken@3685
   178
    renderer->window = window;
slouken@1895
   179
    renderer->driverdata = data;
slouken@1895
   180
slouken@5154
   181
    data->format = format;
slouken@1895
   182
slouken@1895
   183
    /* Find a render driver that we can use to display data */
slouken@5142
   184
    renderer_flags = 0;
slouken@1965
   185
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1965
   186
        renderer_flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   187
    }
slouken@1929
   188
    desired_driver = SDL_getenv("SDL_VIDEO_RENDERER_SWDRIVER");
slouken@5154
   189
    for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@5154
   190
        SDL_RendererInfo info;
slouken@5154
   191
        SDL_GetRenderDriverInfo(i, &info);
slouken@5154
   192
        if (SDL_strcmp(info.name, SW_RenderDriver.info.name) == 0) {
slouken@1929
   193
            continue;
slouken@1929
   194
        }
slouken@1929
   195
        if (desired_driver
slouken@5154
   196
            && SDL_strcasecmp(desired_driver, info.name) != 0) {
slouken@1929
   197
            continue;
slouken@1929
   198
        }
slouken@5154
   199
        data->renderer = SDL_CreateRenderer(window, i, renderer_flags);
slouken@1929
   200
        if (data->renderer) {
slouken@1929
   201
            break;
slouken@1895
   202
        }
slouken@1895
   203
    }
slouken@5154
   204
    if (i == SDL_GetNumRenderDrivers()) {
slouken@1918
   205
        SW_DestroyRenderer(renderer);
slouken@1895
   206
        SDL_SetError("Couldn't find display render driver");
slouken@1895
   207
        return NULL;
slouken@1895
   208
    }
slouken@1965
   209
    if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1965
   210
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   211
    }
slouken@1907
   212
slouken@1907
   213
    /* Create the textures we'll use for display */
slouken@5156
   214
    SDL_GetWindowSize(window, &w, &h);
slouken@5156
   215
    data->texture = CreateTexture(data->renderer, data->format, w, h);
slouken@5142
   216
    if (!data->texture) {
slouken@5142
   217
        SW_DestroyRenderer(renderer);
slouken@5142
   218
        return NULL;
slouken@1907
   219
    }
slouken@1907
   220
slouken@1907
   221
    /* Create a surface we'll use for rendering */
slouken@1907
   222
    data->surface.flags = SDL_PREALLOC;
slouken@1907
   223
    data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
slouken@1907
   224
    if (!data->surface.format) {
slouken@1918
   225
        SW_DestroyRenderer(renderer);
slouken@1907
   226
        return NULL;
slouken@1907
   227
    }
slouken@1907
   228
slouken@1895
   229
    return renderer;
slouken@1895
   230
}
slouken@1895
   231
slouken@5147
   232
static SDL_Texture *
slouken@1970
   233
SW_ActivateRenderer(SDL_Renderer * renderer)
slouken@1970
   234
{
slouken@1970
   235
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@3685
   236
    SDL_Window *window = renderer->window;
slouken@1970
   237
slouken@1972
   238
    if (data->updateSize) {
slouken@1972
   239
        /* Recreate the textures for the new window size */
slouken@5156
   240
        int w, h;
slouken@5142
   241
        if (data->texture) {
slouken@5142
   242
            DestroyTexture(data->renderer, data->texture);
slouken@1972
   243
        }
slouken@5156
   244
        SDL_GetWindowSize(window, &w, &h);
slouken@5156
   245
        data->texture = CreateTexture(data->renderer, data->format, w, h);
slouken@5147
   246
        if (data->texture) {
slouken@5147
   247
            data->updateSize = SDL_FALSE;
slouken@1972
   248
        }
slouken@1972
   249
    }
slouken@5147
   250
    return data->texture;
slouken@1970
   251
}
slouken@1970
   252
slouken@5147
   253
static void
slouken@5147
   254
SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
slouken@1970
   255
{
slouken@1970
   256
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@1970
   257
slouken@5147
   258
    if (event->event == SDL_WINDOWEVENT_RESIZED) {
slouken@5147
   259
        data->updateSize = SDL_TRUE;
slouken@1970
   260
    }
slouken@1970
   261
}
slouken@1970
   262
slouken@1970
   263
static int
slouken@1918
   264
SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   265
{
slouken@5156
   266
    int bpp;
slouken@5156
   267
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@1895
   268
slouken@5156
   269
    if (!SDL_PixelFormatEnumToMasks
slouken@5156
   270
        (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@5156
   271
        SDL_SetError("Unknown texture format");
slouken@5156
   272
        return -1;
slouken@5156
   273
    }
slouken@1895
   274
slouken@5156
   275
    texture->driverdata =
slouken@5156
   276
        SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
slouken@5156
   277
                             Bmask, Amask);
slouken@5156
   278
    SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
slouken@5156
   279
                           texture->b);
slouken@5156
   280
    SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
slouken@5156
   281
    SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
slouken@3053
   282
slouken@5156
   283
    if (texture->access == SDL_TEXTUREACCESS_STATIC) {
slouken@5156
   284
        SDL_SetSurfaceRLE(texture->driverdata, 1);
slouken@1895
   285
    }
slouken@1895
   286
slouken@1895
   287
    if (!texture->driverdata) {
slouken@1895
   288
        return -1;
slouken@1895
   289
    }
slouken@1895
   290
    return 0;
slouken@1895
   291
}
slouken@1895
   292
slouken@1895
   293
static int
slouken@1985
   294
SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   295
{
slouken@2267
   296
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@2267
   297
    return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
slouken@2267
   298
                                  texture->b);
slouken@1985
   299
}
slouken@1985
   300
slouken@1985
   301
static int
slouken@1985
   302
SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   303
{
slouken@2267
   304
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@2267
   305
    return SDL_SetSurfaceAlphaMod(surface, texture->a);
slouken@1985
   306
}
slouken@1985
   307
slouken@1985
   308
static int
slouken@1985
   309
SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   310
{
slouken@2267
   311
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@2267
   312
    return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
slouken@1985
   313
}
slouken@1985
   314
slouken@1985
   315
static int
slouken@1918
   316
SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
   317
                 const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
   318
{
slouken@5156
   319
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@5156
   320
    Uint8 *src, *dst;
slouken@5156
   321
    int row;
slouken@5156
   322
    size_t length;
slouken@1895
   323
slouken@5156
   324
    src = (Uint8 *) pixels;
slouken@5156
   325
    dst = (Uint8 *) surface->pixels +
slouken@5156
   326
                        rect->y * surface->pitch +
slouken@5156
   327
                        rect->x * surface->format->BytesPerPixel;
slouken@5156
   328
    length = rect->w * surface->format->BytesPerPixel;
slouken@5156
   329
    for (row = 0; row < rect->h; ++row) {
slouken@5156
   330
        SDL_memcpy(dst, src, length);
slouken@5156
   331
        src += pitch;
slouken@5156
   332
        dst += surface->pitch;
slouken@1895
   333
    }
slouken@5156
   334
    return 0;
slouken@1895
   335
}
slouken@1895
   336
slouken@1895
   337
static int
slouken@1918
   338
SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@5156
   339
               const SDL_Rect * rect, void **pixels, int *pitch)
slouken@1895
   340
{
slouken@5156
   341
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@1895
   342
slouken@5156
   343
    *pixels =
slouken@5156
   344
        (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
slouken@5156
   345
                  rect->x * surface->format->BytesPerPixel);
slouken@5156
   346
    *pitch = surface->pitch;
slouken@5156
   347
    return 0;
slouken@1895
   348
}
slouken@1895
   349
slouken@1895
   350
static void
slouken@1918
   351
SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   352
{
slouken@1895
   353
}
slouken@1895
   354
slouken@1895
   355
static int
slouken@3596
   356
SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3596
   357
                    int count)
slouken@2901
   358
{
slouken@2901
   359
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   360
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@2904
   361
    SDL_Rect rect;
slouken@3536
   362
    int i;
slouken@3536
   363
    int x, y;
slouken@3536
   364
    int status = 0;
slouken@2901
   365
slouken@5147
   366
    if (!texture) {
slouken@5147
   367
        return -1;
slouken@5147
   368
    }
slouken@5147
   369
slouken@3536
   370
    /* Get the smallest rectangle that contains everything */
slouken@3536
   371
    rect.x = 0;
slouken@3536
   372
    rect.y = 0;
slouken@3536
   373
    rect.w = texture->w;
slouken@3536
   374
    rect.h = texture->h;
slouken@3536
   375
    if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
slouken@3536
   376
        /* Nothing to draw */
slouken@3536
   377
        return 0;
slouken@2904
   378
    }
slouken@2904
   379
slouken@5156
   380
    if (data->renderer->LockTexture(data->renderer, texture, &rect,
slouken@2891
   381
                                    &data->surface.pixels,
slouken@2888
   382
                                    &data->surface.pitch) < 0) {
slouken@2888
   383
        return -1;
slouken@2888
   384
    }
slouken@2888
   385
slouken@3536
   386
    data->surface.clip_rect.w = data->surface.w = rect.w;
slouken@3536
   387
    data->surface.clip_rect.h = data->surface.h = rect.h;
slouken@2904
   388
slouken@3536
   389
    /* Draw the points! */
slouken@5140
   390
    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   391
        Uint32 color = SDL_MapRGBA(data->surface.format,
slouken@3536
   392
                                   renderer->r, renderer->g, renderer->b,
slouken@3536
   393
                                   renderer->a);
slouken@2888
   394
slouken@3536
   395
        for (i = 0; i < count; ++i) {
slouken@3536
   396
            x = points[i].x - rect.x;
slouken@3536
   397
            y = points[i].y - rect.y;
slouken@3536
   398
slouken@3536
   399
            status = SDL_DrawPoint(&data->surface, x, y, color);
slouken@3536
   400
        }
slouken@2888
   401
    } else {
slouken@3536
   402
        for (i = 0; i < count; ++i) {
slouken@3536
   403
            x = points[i].x - rect.x;
slouken@3536
   404
            y = points[i].y - rect.y;
slouken@3536
   405
slouken@3536
   406
            status = SDL_BlendPoint(&data->surface, x, y,
slouken@3536
   407
                                    renderer->blendMode,
slouken@3536
   408
                                    renderer->r, renderer->g, renderer->b,
slouken@3536
   409
                                    renderer->a);
slouken@3536
   410
        }
slouken@2888
   411
    }
slouken@2888
   412
slouken@3536
   413
    data->renderer->UnlockTexture(data->renderer, texture);
slouken@3536
   414
slouken@2888
   415
    return status;
slouken@2888
   416
}
slouken@2888
   417
slouken@2888
   418
static int
slouken@3596
   419
SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3596
   420
                   int count)
slouken@1895
   421
{
slouken@1918
   422
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   423
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@3536
   424
    SDL_Rect clip, rect;
slouken@3536
   425
    int i;
slouken@3536
   426
    int x1, y1, x2, y2;
slouken@3536
   427
    int status = 0;
slouken@3536
   428
slouken@5147
   429
    if (!texture) {
slouken@5147
   430
        return -1;
slouken@5147
   431
    }
slouken@5147
   432
slouken@3536
   433
    /* Get the smallest rectangle that contains everything */
slouken@3536
   434
    clip.x = 0;
slouken@3536
   435
    clip.y = 0;
slouken@3536
   436
    clip.w = texture->w;
slouken@3536
   437
    clip.h = texture->h;
slouken@3536
   438
    SDL_EnclosePoints(points, count, NULL, &rect);
slouken@3536
   439
    if (!SDL_IntersectRect(&rect, &clip, &rect)) {
slouken@3536
   440
        /* Nothing to draw */
slouken@3536
   441
        return 0;
slouken@3536
   442
    }
slouken@1895
   443
slouken@5156
   444
    if (data->renderer->LockTexture(data->renderer, texture, &rect,
slouken@3536
   445
                                    &data->surface.pixels,
slouken@2735
   446
                                    &data->surface.pitch) < 0) {
slouken@1907
   447
        return -1;
slouken@1907
   448
    }
slouken@2888
   449
slouken@3536
   450
    data->surface.clip_rect.w = data->surface.w = rect.w;
slouken@3536
   451
    data->surface.clip_rect.h = data->surface.h = rect.h;
slouken@1907
   452
slouken@3536
   453
    /* Draw the points! */
slouken@5140
   454
    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   455
        Uint32 color = SDL_MapRGBA(data->surface.format,
slouken@3536
   456
                                   renderer->r, renderer->g, renderer->b,
slouken@3536
   457
                                   renderer->a);
slouken@2888
   458
slouken@3536
   459
        for (i = 1; i < count; ++i) {
slouken@3536
   460
            x1 = points[i-1].x - rect.x;
slouken@3536
   461
            y1 = points[i-1].y - rect.y;
slouken@3536
   462
            x2 = points[i].x - rect.x;
slouken@3536
   463
            y2 = points[i].y - rect.y;
slouken@3536
   464
slouken@3536
   465
            status = SDL_DrawLine(&data->surface, x1, y1, x2, y2, color);
slouken@3536
   466
        }
slouken@2888
   467
    } else {
slouken@3536
   468
        for (i = 1; i < count; ++i) {
slouken@3536
   469
            x1 = points[i-1].x - rect.x;
slouken@3536
   470
            y1 = points[i-1].y - rect.y;
slouken@3536
   471
            x2 = points[i].x - rect.x;
slouken@3536
   472
            y2 = points[i].y - rect.y;
slouken@3536
   473
slouken@3536
   474
            status = SDL_BlendLine(&data->surface, x1, y1, x2, y2,
slouken@3536
   475
                                   renderer->blendMode,
slouken@3536
   476
                                   renderer->r, renderer->g, renderer->b,
slouken@3536
   477
                                   renderer->a);
slouken@3536
   478
        }
slouken@2888
   479
    }
slouken@1907
   480
slouken@3536
   481
    data->renderer->UnlockTexture(data->renderer, texture);
slouken@3536
   482
slouken@3536
   483
    return status;
slouken@3536
   484
}
slouken@3536
   485
slouken@3536
   486
static int
slouken@3596
   487
SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3596
   488
                   int count)
slouken@3536
   489
{
slouken@3536
   490
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   491
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@3536
   492
    SDL_Rect clip, rect;
slouken@3536
   493
    Uint32 color = 0;
slouken@3536
   494
    int i;
slouken@3536
   495
    int status = 0;
slouken@3536
   496
slouken@5147
   497
    if (!texture) {
slouken@5147
   498
        return -1;
slouken@5147
   499
    }
slouken@5147
   500
slouken@3536
   501
    clip.x = 0;
slouken@3536
   502
    clip.y = 0;
slouken@3536
   503
    clip.w = texture->w;
slouken@3536
   504
    clip.h = texture->h;
slouken@3536
   505
slouken@5140
   506
    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   507
        color = SDL_MapRGBA(data->surface.format,
slouken@3536
   508
                            renderer->r, renderer->g, renderer->b,
slouken@3536
   509
                            renderer->a);
slouken@3536
   510
    }
slouken@3536
   511
slouken@3536
   512
    for (i = 0; i < count; ++i) {
slouken@3536
   513
        if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
slouken@3536
   514
            /* Nothing to draw */
slouken@3536
   515
            continue;
slouken@3536
   516
        }
slouken@3536
   517
slouken@5156
   518
        if (data->renderer->LockTexture(data->renderer, texture, &rect,
slouken@3536
   519
                                        &data->surface.pixels,
slouken@3536
   520
                                        &data->surface.pitch) < 0) {
slouken@3536
   521
            return -1;
slouken@3536
   522
        }
slouken@3536
   523
slouken@3536
   524
        data->surface.clip_rect.w = data->surface.w = rect.w;
slouken@3536
   525
        data->surface.clip_rect.h = data->surface.h = rect.h;
slouken@3536
   526
slouken@5140
   527
        if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   528
            status = SDL_FillRect(&data->surface, NULL, color);
slouken@3536
   529
        } else {
slouken@3596
   530
            status = SDL_BlendFillRect(&data->surface, NULL,
slouken@3596
   531
                                       renderer->blendMode,
slouken@3596
   532
                                       renderer->r, renderer->g, renderer->b,
slouken@3596
   533
                                       renderer->a);
slouken@3536
   534
        }
slouken@3536
   535
slouken@3536
   536
        data->renderer->UnlockTexture(data->renderer, texture);
slouken@3536
   537
    }
slouken@1907
   538
    return status;
slouken@1895
   539
}
slouken@1895
   540
slouken@1895
   541
static int
slouken@1918
   542
SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
   543
              const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1895
   544
{
slouken@1918
   545
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5156
   546
    SDL_Surface *surface;
slouken@5156
   547
    SDL_Rect real_srcrect;
slouken@5156
   548
    SDL_Rect real_dstrect;
slouken@1907
   549
    int status;
slouken@1895
   550
slouken@5147
   551
    if (!SW_ActivateRenderer(renderer)) {
slouken@5147
   552
        return -1;
slouken@5147
   553
    }
slouken@5147
   554
slouken@5156
   555
    if (data->renderer->LockTexture(data->renderer, data->texture, dstrect,
slouken@5156
   556
                                    &data->surface.pixels,
slouken@2735
   557
                                    &data->surface.pitch) < 0) {
slouken@1907
   558
        return -1;
slouken@1907
   559
    }
slouken@1907
   560
slouken@5156
   561
    surface = (SDL_Surface *) texture->driverdata;
slouken@5156
   562
    real_srcrect = *srcrect;
slouken@1907
   563
slouken@5156
   564
    data->surface.w = dstrect->w;
slouken@5156
   565
    data->surface.h = dstrect->h;
slouken@5156
   566
    data->surface.clip_rect.w = dstrect->w;
slouken@5156
   567
    data->surface.clip_rect.h = dstrect->h;
slouken@5156
   568
    real_dstrect = data->surface.clip_rect;
slouken@1895
   569
slouken@5156
   570
    status = SDL_LowerBlit(surface, &real_srcrect, &data->surface, &real_dstrect);
slouken@5142
   571
    data->renderer->UnlockTexture(data->renderer, data->texture);
slouken@1907
   572
    return status;
slouken@1895
   573
}
slouken@1895
   574
slouken@3427
   575
static int
slouken@3427
   576
SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
   577
                    Uint32 format, void * pixels, int pitch)
slouken@3427
   578
{
slouken@3427
   579
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@3427
   580
slouken@5147
   581
    if (!SW_ActivateRenderer(renderer)) {
slouken@5147
   582
        return -1;
slouken@5147
   583
    }
slouken@5147
   584
slouken@5156
   585
    if (data->renderer->LockTexture(data->renderer, data->texture, rect,
slouken@5156
   586
                                    &data->surface.pixels,
slouken@3427
   587
                                    &data->surface.pitch) < 0) {
slouken@3427
   588
        return -1;
slouken@3427
   589
    }
slouken@3427
   590
slouken@3435
   591
    SDL_ConvertPixels(rect->w, rect->h,
slouken@3435
   592
                      data->format, data->surface.pixels, data->surface.pitch,
slouken@3435
   593
                      format, pixels, pitch);
slouken@3427
   594
slouken@5142
   595
    data->renderer->UnlockTexture(data->renderer, data->texture);
slouken@3427
   596
    return 0;
slouken@3427
   597
}
slouken@3427
   598
slouken@1895
   599
static void
slouken@1918
   600
SW_RenderPresent(SDL_Renderer * renderer)
slouken@1895
   601
{
slouken@1918
   602
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   603
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@5142
   604
    SDL_Rect rect;
slouken@1895
   605
slouken@5147
   606
    if (!texture) {
slouken@5147
   607
        return;
slouken@5147
   608
    }
slouken@5147
   609
slouken@1895
   610
    /* Send the data to the display */
slouken@5142
   611
    rect.x = 0;
slouken@5142
   612
    rect.y = 0;
slouken@5142
   613
    rect.w = texture->w;
slouken@5142
   614
    rect.h = texture->h;
slouken@5142
   615
    data->renderer->RenderCopy(data->renderer, texture, &rect, &rect);
slouken@1895
   616
    data->renderer->RenderPresent(data->renderer);
slouken@1895
   617
}
slouken@1895
   618
slouken@1895
   619
static void
slouken@1918
   620
SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   621
{
slouken@5156
   622
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@1895
   623
slouken@5156
   624
    SDL_FreeSurface(surface);
slouken@1895
   625
}
slouken@1895
   626
slouken@1895
   627
static void
slouken@1918
   628
SW_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
   629
{
slouken@1918
   630
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@3685
   631
    SDL_Window *window = renderer->window;
slouken@1895
   632
slouken@1895
   633
    if (data) {
slouken@5142
   634
        if (data->texture) {
slouken@5142
   635
            DestroyTexture(data->renderer, data->texture);
slouken@1895
   636
        }
slouken@1907
   637
        if (data->surface.format) {
slouken@1907
   638
            SDL_FreeFormat(data->surface.format);
slouken@1907
   639
        }
slouken@1907
   640
        if (data->renderer) {
slouken@1907
   641
            data->renderer->DestroyRenderer(data->renderer);
slouken@1907
   642
        }
slouken@1895
   643
        SDL_free(data);
slouken@1895
   644
    }
slouken@1895
   645
    SDL_free(renderer);
slouken@1895
   646
}
slouken@1895
   647
slouken@1895
   648
/* vi: set ts=4 sw=4 expandtab: */