src/render/software/SDL_renderer_sw.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 02 Feb 2011 14:34:54 -0800
changeset 5154 fb424691cfc7
parent 5149 src/video/SDL_renderer_sw.c@be02be2ea897
child 5156 307ccc9c135e
permissions -rw-r--r--
Moved the rendering code out to a separate directory in the hope that it can someday be completely decoupled from the rest of the library and be expanded to an awesome 2D on 3D library.
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@5154
    26
#include "../../video/SDL_yuv_sw_c.h"
slouken@1895
    27
slouken@1895
    28
slouken@1895
    29
/* SDL surface based renderer implementation */
slouken@1895
    30
slouken@1918
    31
static SDL_Renderer *SW_CreateRenderer(SDL_Window * window, Uint32 flags);
slouken@5147
    32
static void SW_WindowEvent(SDL_Renderer * renderer,
slouken@5147
    33
                           const SDL_WindowEvent *event);
slouken@1918
    34
static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@1918
    35
static int SW_QueryTexturePixels(SDL_Renderer * renderer,
slouken@1918
    36
                                 SDL_Texture * texture, void **pixels,
slouken@1918
    37
                                 int *pitch);
slouken@1985
    38
static int SW_SetTextureColorMod(SDL_Renderer * renderer,
slouken@1985
    39
                                 SDL_Texture * texture);
slouken@1985
    40
static int SW_SetTextureAlphaMod(SDL_Renderer * renderer,
slouken@1985
    41
                                 SDL_Texture * texture);
slouken@5141
    42
static int SW_SetTextureBlendMode(SDL_Renderer * renderer,
slouken@5141
    43
                                  SDL_Texture * texture);
slouken@1985
    44
static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    45
                            const SDL_Rect * rect, const void *pixels,
slouken@1985
    46
                            int pitch);
slouken@1918
    47
static int SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    48
                          const SDL_Rect * rect, int markDirty, void **pixels,
slouken@1985
    49
                          int *pitch);
slouken@1918
    50
static void SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
slouken@3596
    51
static int SW_RenderDrawPoints(SDL_Renderer * renderer,
slouken@3596
    52
                               const SDL_Point * points, int count);
slouken@3596
    53
static int SW_RenderDrawLines(SDL_Renderer * renderer,
slouken@3596
    54
                              const SDL_Point * points, int count);
slouken@3596
    55
static int SW_RenderFillRects(SDL_Renderer * renderer,
slouken@3596
    56
                              const SDL_Rect ** rects, int count);
slouken@1918
    57
static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
    58
                         const SDL_Rect * srcrect, const SDL_Rect * dstrect);
slouken@3427
    59
static int SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
    60
                               Uint32 format, void * pixels, int pitch);
slouken@3427
    61
static int SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
    62
                                Uint32 format, const 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@5149
    73
     13,
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@1965
    82
      SDL_PIXELFORMAT_BGRA8888,
slouken@2811
    83
      SDL_PIXELFORMAT_YV12,
slouken@2811
    84
      SDL_PIXELFORMAT_IYUV,
slouken@1965
    85
      SDL_PIXELFORMAT_YUY2,
slouken@2810
    86
      SDL_PIXELFORMAT_UYVY,
slouken@2810
    87
      SDL_PIXELFORMAT_YVYU},
slouken@1895
    88
     0,
slouken@1895
    89
     0}
slouken@1895
    90
};
slouken@1895
    91
slouken@1895
    92
typedef struct
slouken@1895
    93
{
slouken@1907
    94
    Uint32 format;
slouken@1972
    95
    SDL_bool updateSize;
slouken@5142
    96
    SDL_Texture *texture;
slouken@1907
    97
    SDL_Surface surface;
slouken@1895
    98
    SDL_Renderer *renderer;
slouken@1895
    99
    SDL_DirtyRectList dirty;
slouken@1918
   100
} SW_RenderData;
slouken@1895
   101
slouken@1907
   102
static SDL_Texture *
slouken@1907
   103
CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h)
slouken@1907
   104
{
slouken@1907
   105
    SDL_Texture *texture;
slouken@1907
   106
slouken@1920
   107
    texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
slouken@1907
   108
    if (!texture) {
slouken@1907
   109
        SDL_OutOfMemory();
slouken@1907
   110
        return NULL;
slouken@1907
   111
    }
slouken@1907
   112
slouken@1907
   113
    texture->format = format;
slouken@2222
   114
    texture->access = SDL_TEXTUREACCESS_STREAMING;
slouken@1907
   115
    texture->w = w;
slouken@1907
   116
    texture->h = h;
slouken@1907
   117
    texture->renderer = renderer;
slouken@1907
   118
slouken@1907
   119
    if (renderer->CreateTexture(renderer, texture) < 0) {
slouken@1907
   120
        SDL_free(texture);
slouken@1907
   121
        return NULL;
slouken@1907
   122
    }
slouken@1907
   123
    return texture;
slouken@1907
   124
}
slouken@1907
   125
slouken@1907
   126
static void
slouken@1907
   127
DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1907
   128
{
slouken@1907
   129
    renderer->DestroyTexture(renderer, texture);
slouken@1907
   130
    SDL_free(texture);
slouken@1907
   131
}
slouken@1907
   132
slouken@1895
   133
SDL_Renderer *
slouken@1918
   134
SW_CreateRenderer(SDL_Window * window, Uint32 flags)
slouken@1895
   135
{
slouken@1895
   136
    SDL_Renderer *renderer;
slouken@1918
   137
    SW_RenderData *data;
slouken@5154
   138
    int i;
slouken@5154
   139
    Uint32 format;
slouken@1895
   140
    int bpp;
slouken@1895
   141
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@1907
   142
    Uint32 renderer_flags;
slouken@1929
   143
    const char *desired_driver;
slouken@1895
   144
slouken@5154
   145
    format = SDL_GetWindowPixelFormat(window);
slouken@1895
   146
    if (!SDL_PixelFormatEnumToMasks
slouken@5154
   147
        (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@1895
   148
        SDL_SetError("Unknown display format");
slouken@1895
   149
        return NULL;
slouken@1895
   150
    }
slouken@1895
   151
slouken@1895
   152
    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
slouken@1895
   153
    if (!renderer) {
slouken@1895
   154
        SDL_OutOfMemory();
slouken@1895
   155
        return NULL;
slouken@1895
   156
    }
slouken@1895
   157
slouken@1920
   158
    data = (SW_RenderData *) SDL_calloc(1, sizeof(*data));
slouken@1895
   159
    if (!data) {
slouken@1918
   160
        SW_DestroyRenderer(renderer);
slouken@1895
   161
        SDL_OutOfMemory();
slouken@1895
   162
        return NULL;
slouken@1895
   163
    }
slouken@5147
   164
    renderer->WindowEvent = SW_WindowEvent;
slouken@5154
   165
    renderer->CreateTexture = SW_CreateTexture;
slouken@5154
   166
    renderer->QueryTexturePixels = SW_QueryTexturePixels;
slouken@5154
   167
    renderer->SetTextureColorMod = SW_SetTextureColorMod;
slouken@5154
   168
    renderer->SetTextureAlphaMod = SW_SetTextureAlphaMod;
slouken@5154
   169
    renderer->SetTextureBlendMode = SW_SetTextureBlendMode;
slouken@5154
   170
    renderer->UpdateTexture = SW_UpdateTexture;
slouken@5154
   171
    renderer->LockTexture = SW_LockTexture;
slouken@5154
   172
    renderer->UnlockTexture = SW_UnlockTexture;
slouken@5154
   173
    renderer->DestroyTexture = SW_DestroyTexture;
slouken@3596
   174
    renderer->RenderDrawPoints = SW_RenderDrawPoints;
slouken@3596
   175
    renderer->RenderDrawLines = SW_RenderDrawLines;
slouken@3596
   176
    renderer->RenderFillRects = SW_RenderFillRects;
slouken@1918
   177
    renderer->RenderCopy = SW_RenderCopy;
slouken@3427
   178
    renderer->RenderReadPixels = SW_RenderReadPixels;
slouken@3427
   179
    renderer->RenderWritePixels = SW_RenderWritePixels;
slouken@1918
   180
    renderer->RenderPresent = SW_RenderPresent;
slouken@1918
   181
    renderer->DestroyRenderer = SW_DestroyRenderer;
slouken@5154
   182
    renderer->info = SW_RenderDriver.info;
slouken@2227
   183
    renderer->info.flags = 0;
slouken@3685
   184
    renderer->window = window;
slouken@1895
   185
    renderer->driverdata = data;
slouken@1895
   186
slouken@5154
   187
    data->format = format;
slouken@1895
   188
slouken@1895
   189
    /* Find a render driver that we can use to display data */
slouken@5142
   190
    renderer_flags = 0;
slouken@1965
   191
    if (flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1965
   192
        renderer_flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   193
    }
slouken@1929
   194
    desired_driver = SDL_getenv("SDL_VIDEO_RENDERER_SWDRIVER");
slouken@5154
   195
    for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
slouken@5154
   196
        SDL_RendererInfo info;
slouken@5154
   197
        SDL_GetRenderDriverInfo(i, &info);
slouken@5154
   198
        if (SDL_strcmp(info.name, SW_RenderDriver.info.name) == 0) {
slouken@1929
   199
            continue;
slouken@1929
   200
        }
slouken@1929
   201
        if (desired_driver
slouken@5154
   202
            && SDL_strcasecmp(desired_driver, info.name) != 0) {
slouken@1929
   203
            continue;
slouken@1929
   204
        }
slouken@5154
   205
        data->renderer = SDL_CreateRenderer(window, i, renderer_flags);
slouken@1929
   206
        if (data->renderer) {
slouken@1929
   207
            break;
slouken@1895
   208
        }
slouken@1895
   209
    }
slouken@5154
   210
    if (i == SDL_GetNumRenderDrivers()) {
slouken@1918
   211
        SW_DestroyRenderer(renderer);
slouken@1895
   212
        SDL_SetError("Couldn't find display render driver");
slouken@1895
   213
        return NULL;
slouken@1895
   214
    }
slouken@1965
   215
    if (data->renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
slouken@1965
   216
        renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
slouken@1907
   217
    }
slouken@1907
   218
slouken@1907
   219
    /* Create the textures we'll use for display */
slouken@5142
   220
    data->texture =
slouken@5142
   221
        CreateTexture(data->renderer, data->format, window->w, window->h);
slouken@5142
   222
    if (!data->texture) {
slouken@5142
   223
        SW_DestroyRenderer(renderer);
slouken@5142
   224
        return NULL;
slouken@1907
   225
    }
slouken@1907
   226
slouken@1907
   227
    /* Create a surface we'll use for rendering */
slouken@1907
   228
    data->surface.flags = SDL_PREALLOC;
slouken@1907
   229
    data->surface.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask);
slouken@1907
   230
    if (!data->surface.format) {
slouken@1918
   231
        SW_DestroyRenderer(renderer);
slouken@1907
   232
        return NULL;
slouken@1907
   233
    }
slouken@1907
   234
slouken@1895
   235
    return renderer;
slouken@1895
   236
}
slouken@1895
   237
slouken@5147
   238
static SDL_Texture *
slouken@1970
   239
SW_ActivateRenderer(SDL_Renderer * renderer)
slouken@1970
   240
{
slouken@1970
   241
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@3685
   242
    SDL_Window *window = renderer->window;
slouken@1970
   243
slouken@1972
   244
    if (data->updateSize) {
slouken@1972
   245
        /* Recreate the textures for the new window size */
slouken@5142
   246
        if (data->texture) {
slouken@5142
   247
            DestroyTexture(data->renderer, data->texture);
slouken@1972
   248
        }
slouken@5142
   249
        data->texture = CreateTexture(data->renderer, data->format,
slouken@5142
   250
                                      window->w, window->h);
slouken@5147
   251
        if (data->texture) {
slouken@5147
   252
            data->updateSize = SDL_FALSE;
slouken@1972
   253
        }
slouken@1972
   254
    }
slouken@5147
   255
    return data->texture;
slouken@1970
   256
}
slouken@1970
   257
slouken@5147
   258
static void
slouken@5147
   259
SW_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
slouken@1970
   260
{
slouken@1970
   261
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@1970
   262
slouken@5147
   263
    if (event->event == SDL_WINDOWEVENT_RESIZED) {
slouken@5147
   264
        data->updateSize = SDL_TRUE;
slouken@1970
   265
    }
slouken@1970
   266
}
slouken@1970
   267
slouken@1970
   268
static int
slouken@1918
   269
SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   270
{
slouken@1895
   271
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@2786
   272
        texture->driverdata =
slouken@2786
   273
            SDL_SW_CreateYUVTexture(texture->format, texture->w, texture->h);
slouken@1895
   274
    } else {
slouken@1895
   275
        int bpp;
slouken@1895
   276
        Uint32 Rmask, Gmask, Bmask, Amask;
slouken@1895
   277
slouken@1895
   278
        if (!SDL_PixelFormatEnumToMasks
slouken@1895
   279
            (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@1895
   280
            SDL_SetError("Unknown texture format");
slouken@1895
   281
            return -1;
slouken@1895
   282
        }
slouken@1895
   283
slouken@1895
   284
        texture->driverdata =
slouken@1895
   285
            SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask,
slouken@1895
   286
                                 Bmask, Amask);
slouken@3053
   287
        SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g,
slouken@3053
   288
                               texture->b);
slouken@3053
   289
        SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a);
slouken@3053
   290
        SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode);
slouken@3053
   291
slouken@2802
   292
        if (texture->access == SDL_TEXTUREACCESS_STATIC) {
slouken@2802
   293
            SDL_SetSurfaceRLE(texture->driverdata, 1);
slouken@2802
   294
        }
slouken@1895
   295
    }
slouken@1895
   296
slouken@1895
   297
    if (!texture->driverdata) {
slouken@1895
   298
        return -1;
slouken@1895
   299
    }
slouken@1895
   300
    return 0;
slouken@1895
   301
}
slouken@1895
   302
slouken@1895
   303
static int
slouken@1918
   304
SW_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
   305
                      void **pixels, int *pitch)
slouken@1895
   306
{
slouken@1895
   307
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@2735
   308
        return SDL_SW_QueryYUVTexturePixels((SDL_SW_YUVTexture *)
slouken@2735
   309
                                            texture->driverdata, pixels,
slouken@2735
   310
                                            pitch);
slouken@1895
   311
    } else {
slouken@1895
   312
        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@1895
   313
slouken@1895
   314
        *pixels = surface->pixels;
slouken@1895
   315
        *pitch = surface->pitch;
slouken@1895
   316
        return 0;
slouken@1895
   317
    }
slouken@1895
   318
}
slouken@1895
   319
slouken@1895
   320
static int
slouken@1985
   321
SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   322
{
slouken@2267
   323
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@2267
   324
    return SDL_SetSurfaceColorMod(surface, texture->r, texture->g,
slouken@2267
   325
                                  texture->b);
slouken@1985
   326
}
slouken@1985
   327
slouken@1985
   328
static int
slouken@1985
   329
SW_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   330
{
slouken@2267
   331
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@2267
   332
    return SDL_SetSurfaceAlphaMod(surface, texture->a);
slouken@1985
   333
}
slouken@1985
   334
slouken@1985
   335
static int
slouken@1985
   336
SW_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1985
   337
{
slouken@2267
   338
    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@2267
   339
    return SDL_SetSurfaceBlendMode(surface, texture->blendMode);
slouken@1985
   340
}
slouken@1985
   341
slouken@1985
   342
static int
slouken@1918
   343
SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
   344
                 const SDL_Rect * rect, const void *pixels, int pitch)
slouken@1895
   345
{
slouken@1895
   346
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@2735
   347
        return SDL_SW_UpdateYUVTexture((SDL_SW_YUVTexture *)
slouken@2735
   348
                                       texture->driverdata, rect, pixels,
slouken@2735
   349
                                       pitch);
slouken@1895
   350
    } else {
slouken@1895
   351
        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@1895
   352
        Uint8 *src, *dst;
slouken@1895
   353
        int row;
slouken@1895
   354
        size_t length;
slouken@1895
   355
slouken@1895
   356
        src = (Uint8 *) pixels;
slouken@1895
   357
        dst =
slouken@1895
   358
            (Uint8 *) surface->pixels + rect->y * surface->pitch +
slouken@1895
   359
            rect->x * surface->format->BytesPerPixel;
slouken@1895
   360
        length = rect->w * surface->format->BytesPerPixel;
slouken@1895
   361
        for (row = 0; row < rect->h; ++row) {
slouken@1895
   362
            SDL_memcpy(dst, src, length);
slouken@1895
   363
            src += pitch;
slouken@1895
   364
            dst += surface->pitch;
slouken@1895
   365
        }
slouken@1895
   366
        return 0;
slouken@1895
   367
    }
slouken@1895
   368
}
slouken@1895
   369
slouken@1895
   370
static int
slouken@1918
   371
SW_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1918
   372
               const SDL_Rect * rect, int markDirty, void **pixels,
slouken@1918
   373
               int *pitch)
slouken@1895
   374
{
slouken@1895
   375
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@2735
   376
        return SDL_SW_LockYUVTexture((SDL_SW_YUVTexture *)
slouken@2735
   377
                                     texture->driverdata, rect, markDirty,
slouken@2735
   378
                                     pixels, pitch);
slouken@1895
   379
    } else {
slouken@1895
   380
        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@1895
   381
slouken@1895
   382
        *pixels =
slouken@1895
   383
            (void *) ((Uint8 *) surface->pixels + rect->y * surface->pitch +
slouken@1895
   384
                      rect->x * surface->format->BytesPerPixel);
slouken@1895
   385
        *pitch = surface->pitch;
slouken@1895
   386
        return 0;
slouken@1895
   387
    }
slouken@1895
   388
}
slouken@1895
   389
slouken@1895
   390
static void
slouken@1918
   391
SW_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   392
{
slouken@1895
   393
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@1895
   394
        SDL_SW_UnlockYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
slouken@1895
   395
    }
slouken@1895
   396
}
slouken@1895
   397
slouken@1895
   398
static int
slouken@3596
   399
SW_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3596
   400
                    int count)
slouken@2901
   401
{
slouken@2901
   402
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   403
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@2904
   404
    SDL_Rect rect;
slouken@3536
   405
    int i;
slouken@3536
   406
    int x, y;
slouken@3536
   407
    int status = 0;
slouken@2901
   408
slouken@5147
   409
    if (!texture) {
slouken@5147
   410
        return -1;
slouken@5147
   411
    }
slouken@5147
   412
slouken@3536
   413
    /* Get the smallest rectangle that contains everything */
slouken@3536
   414
    rect.x = 0;
slouken@3536
   415
    rect.y = 0;
slouken@3536
   416
    rect.w = texture->w;
slouken@3536
   417
    rect.h = texture->h;
slouken@3536
   418
    if (!SDL_EnclosePoints(points, count, &rect, &rect)) {
slouken@3536
   419
        /* Nothing to draw */
slouken@3536
   420
        return 0;
slouken@2904
   421
    }
slouken@2904
   422
slouken@3536
   423
    if (data->renderer->LockTexture(data->renderer, texture, &rect, 1,
slouken@2891
   424
                                    &data->surface.pixels,
slouken@2888
   425
                                    &data->surface.pitch) < 0) {
slouken@2888
   426
        return -1;
slouken@2888
   427
    }
slouken@2888
   428
slouken@3536
   429
    data->surface.clip_rect.w = data->surface.w = rect.w;
slouken@3536
   430
    data->surface.clip_rect.h = data->surface.h = rect.h;
slouken@2904
   431
slouken@3536
   432
    /* Draw the points! */
slouken@5140
   433
    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   434
        Uint32 color = SDL_MapRGBA(data->surface.format,
slouken@3536
   435
                                   renderer->r, renderer->g, renderer->b,
slouken@3536
   436
                                   renderer->a);
slouken@2888
   437
slouken@3536
   438
        for (i = 0; i < count; ++i) {
slouken@3536
   439
            x = points[i].x - rect.x;
slouken@3536
   440
            y = points[i].y - rect.y;
slouken@3536
   441
slouken@3536
   442
            status = SDL_DrawPoint(&data->surface, x, y, color);
slouken@3536
   443
        }
slouken@2888
   444
    } else {
slouken@3536
   445
        for (i = 0; i < count; ++i) {
slouken@3536
   446
            x = points[i].x - rect.x;
slouken@3536
   447
            y = points[i].y - rect.y;
slouken@3536
   448
slouken@3536
   449
            status = SDL_BlendPoint(&data->surface, x, y,
slouken@3536
   450
                                    renderer->blendMode,
slouken@3536
   451
                                    renderer->r, renderer->g, renderer->b,
slouken@3536
   452
                                    renderer->a);
slouken@3536
   453
        }
slouken@2888
   454
    }
slouken@2888
   455
slouken@3536
   456
    data->renderer->UnlockTexture(data->renderer, texture);
slouken@3536
   457
slouken@2888
   458
    return status;
slouken@2888
   459
}
slouken@2888
   460
slouken@2888
   461
static int
slouken@3596
   462
SW_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points,
slouken@3596
   463
                   int count)
slouken@1895
   464
{
slouken@1918
   465
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   466
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@3536
   467
    SDL_Rect clip, rect;
slouken@3536
   468
    int i;
slouken@3536
   469
    int x1, y1, x2, y2;
slouken@3536
   470
    int status = 0;
slouken@3536
   471
slouken@5147
   472
    if (!texture) {
slouken@5147
   473
        return -1;
slouken@5147
   474
    }
slouken@5147
   475
slouken@3536
   476
    /* Get the smallest rectangle that contains everything */
slouken@3536
   477
    clip.x = 0;
slouken@3536
   478
    clip.y = 0;
slouken@3536
   479
    clip.w = texture->w;
slouken@3536
   480
    clip.h = texture->h;
slouken@3536
   481
    SDL_EnclosePoints(points, count, NULL, &rect);
slouken@3536
   482
    if (!SDL_IntersectRect(&rect, &clip, &rect)) {
slouken@3536
   483
        /* Nothing to draw */
slouken@3536
   484
        return 0;
slouken@3536
   485
    }
slouken@1895
   486
slouken@3536
   487
    if (data->renderer->LockTexture(data->renderer, texture, &rect, 1,
slouken@3536
   488
                                    &data->surface.pixels,
slouken@2735
   489
                                    &data->surface.pitch) < 0) {
slouken@1907
   490
        return -1;
slouken@1907
   491
    }
slouken@2888
   492
slouken@3536
   493
    data->surface.clip_rect.w = data->surface.w = rect.w;
slouken@3536
   494
    data->surface.clip_rect.h = data->surface.h = rect.h;
slouken@1907
   495
slouken@3536
   496
    /* Draw the points! */
slouken@5140
   497
    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   498
        Uint32 color = SDL_MapRGBA(data->surface.format,
slouken@3536
   499
                                   renderer->r, renderer->g, renderer->b,
slouken@3536
   500
                                   renderer->a);
slouken@2888
   501
slouken@3536
   502
        for (i = 1; i < count; ++i) {
slouken@3536
   503
            x1 = points[i-1].x - rect.x;
slouken@3536
   504
            y1 = points[i-1].y - rect.y;
slouken@3536
   505
            x2 = points[i].x - rect.x;
slouken@3536
   506
            y2 = points[i].y - rect.y;
slouken@3536
   507
slouken@3536
   508
            status = SDL_DrawLine(&data->surface, x1, y1, x2, y2, color);
slouken@3536
   509
        }
slouken@2888
   510
    } else {
slouken@3536
   511
        for (i = 1; i < count; ++i) {
slouken@3536
   512
            x1 = points[i-1].x - rect.x;
slouken@3536
   513
            y1 = points[i-1].y - rect.y;
slouken@3536
   514
            x2 = points[i].x - rect.x;
slouken@3536
   515
            y2 = points[i].y - rect.y;
slouken@3536
   516
slouken@3536
   517
            status = SDL_BlendLine(&data->surface, x1, y1, x2, y2,
slouken@3536
   518
                                   renderer->blendMode,
slouken@3536
   519
                                   renderer->r, renderer->g, renderer->b,
slouken@3536
   520
                                   renderer->a);
slouken@3536
   521
        }
slouken@2888
   522
    }
slouken@1907
   523
slouken@3536
   524
    data->renderer->UnlockTexture(data->renderer, texture);
slouken@3536
   525
slouken@3536
   526
    return status;
slouken@3536
   527
}
slouken@3536
   528
slouken@3536
   529
static int
slouken@3596
   530
SW_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
slouken@3596
   531
                   int count)
slouken@3536
   532
{
slouken@3536
   533
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   534
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@3536
   535
    SDL_Rect clip, rect;
slouken@3536
   536
    Uint32 color = 0;
slouken@3536
   537
    int i;
slouken@3536
   538
    int status = 0;
slouken@3536
   539
slouken@5147
   540
    if (!texture) {
slouken@5147
   541
        return -1;
slouken@5147
   542
    }
slouken@5147
   543
slouken@3536
   544
    clip.x = 0;
slouken@3536
   545
    clip.y = 0;
slouken@3536
   546
    clip.w = texture->w;
slouken@3536
   547
    clip.h = texture->h;
slouken@3536
   548
slouken@5140
   549
    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   550
        color = SDL_MapRGBA(data->surface.format,
slouken@3536
   551
                            renderer->r, renderer->g, renderer->b,
slouken@3536
   552
                            renderer->a);
slouken@3536
   553
    }
slouken@3536
   554
slouken@3536
   555
    for (i = 0; i < count; ++i) {
slouken@3536
   556
        if (!SDL_IntersectRect(rects[i], &clip, &rect)) {
slouken@3536
   557
            /* Nothing to draw */
slouken@3536
   558
            continue;
slouken@3536
   559
        }
slouken@3536
   560
slouken@3536
   561
        if (data->renderer->LockTexture(data->renderer, texture, &rect, 1,
slouken@3536
   562
                                        &data->surface.pixels,
slouken@3536
   563
                                        &data->surface.pitch) < 0) {
slouken@3536
   564
            return -1;
slouken@3536
   565
        }
slouken@3536
   566
slouken@3536
   567
        data->surface.clip_rect.w = data->surface.w = rect.w;
slouken@3536
   568
        data->surface.clip_rect.h = data->surface.h = rect.h;
slouken@3536
   569
slouken@5140
   570
        if (renderer->blendMode == SDL_BLENDMODE_NONE) {
slouken@3536
   571
            status = SDL_FillRect(&data->surface, NULL, color);
slouken@3536
   572
        } else {
slouken@3596
   573
            status = SDL_BlendFillRect(&data->surface, NULL,
slouken@3596
   574
                                       renderer->blendMode,
slouken@3596
   575
                                       renderer->r, renderer->g, renderer->b,
slouken@3596
   576
                                       renderer->a);
slouken@3536
   577
        }
slouken@3536
   578
slouken@3536
   579
        data->renderer->UnlockTexture(data->renderer, texture);
slouken@3536
   580
    }
slouken@1907
   581
    return status;
slouken@1895
   582
}
slouken@1895
   583
slouken@1895
   584
static int
slouken@1918
   585
SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
slouken@1985
   586
              const SDL_Rect * srcrect, const SDL_Rect * dstrect)
slouken@1895
   587
{
slouken@1918
   588
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@1907
   589
    int status;
slouken@1895
   590
slouken@5147
   591
    if (!SW_ActivateRenderer(renderer)) {
slouken@5147
   592
        return -1;
slouken@5147
   593
    }
slouken@5147
   594
slouken@5142
   595
    if (data->renderer->LockTexture(data->renderer, data->texture,
slouken@2735
   596
                                    dstrect, 1, &data->surface.pixels,
slouken@2735
   597
                                    &data->surface.pitch) < 0) {
slouken@1907
   598
        return -1;
slouken@1907
   599
    }
slouken@1907
   600
slouken@1895
   601
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@1907
   602
        status =
slouken@1907
   603
            SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
slouken@1907
   604
                                srcrect, data->format, dstrect->w, dstrect->h,
slouken@1907
   605
                                data->surface.pixels, data->surface.pitch);
slouken@1895
   606
    } else {
slouken@1895
   607
        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@2267
   608
        SDL_Rect real_srcrect = *srcrect;
slouken@2267
   609
        SDL_Rect real_dstrect;
slouken@1907
   610
slouken@2267
   611
        data->surface.w = dstrect->w;
slouken@2267
   612
        data->surface.h = dstrect->h;
slouken@2267
   613
        data->surface.clip_rect.w = dstrect->w;
slouken@2267
   614
        data->surface.clip_rect.h = dstrect->h;
slouken@2267
   615
        real_dstrect = data->surface.clip_rect;
slouken@1895
   616
slouken@2267
   617
        status =
slouken@2267
   618
            SDL_LowerBlit(surface, &real_srcrect, &data->surface,
slouken@2267
   619
                          &real_dstrect);
slouken@1895
   620
    }
slouken@5142
   621
    data->renderer->UnlockTexture(data->renderer, data->texture);
slouken@1907
   622
    return status;
slouken@1895
   623
}
slouken@1895
   624
slouken@3427
   625
static int
slouken@3427
   626
SW_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
   627
                    Uint32 format, void * pixels, int pitch)
slouken@3427
   628
{
slouken@3427
   629
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@3427
   630
slouken@5147
   631
    if (!SW_ActivateRenderer(renderer)) {
slouken@5147
   632
        return -1;
slouken@5147
   633
    }
slouken@5147
   634
slouken@5142
   635
    if (data->renderer->LockTexture(data->renderer, data->texture,
slouken@3427
   636
                                    rect, 0, &data->surface.pixels,
slouken@3427
   637
                                    &data->surface.pitch) < 0) {
slouken@3427
   638
        return -1;
slouken@3427
   639
    }
slouken@3427
   640
slouken@3435
   641
    SDL_ConvertPixels(rect->w, rect->h,
slouken@3435
   642
                      data->format, data->surface.pixels, data->surface.pitch,
slouken@3435
   643
                      format, pixels, pitch);
slouken@3427
   644
slouken@5142
   645
    data->renderer->UnlockTexture(data->renderer, data->texture);
slouken@3427
   646
    return 0;
slouken@3427
   647
}
slouken@3427
   648
slouken@3427
   649
static int
slouken@3427
   650
SW_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
slouken@3435
   651
                     Uint32 format, const void * pixels, int pitch)
slouken@3427
   652
{
slouken@3427
   653
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@3427
   654
slouken@5147
   655
    if (!SW_ActivateRenderer(renderer)) {
slouken@5147
   656
        return -1;
slouken@5147
   657
    }
slouken@5147
   658
slouken@5142
   659
    if (data->renderer->LockTexture(data->renderer, data->texture,
slouken@3427
   660
                                    rect, 1, &data->surface.pixels,
slouken@3427
   661
                                    &data->surface.pitch) < 0) {
slouken@3427
   662
        return -1;
slouken@3427
   663
    }
slouken@3427
   664
slouken@3435
   665
    SDL_ConvertPixels(rect->w, rect->h, format, pixels, pitch,
slouken@3435
   666
                      data->format, data->surface.pixels, data->surface.pitch);
slouken@3427
   667
slouken@5142
   668
    data->renderer->UnlockTexture(data->renderer, data->texture);
slouken@3427
   669
    return 0;
slouken@3427
   670
}
slouken@3427
   671
slouken@1895
   672
static void
slouken@1918
   673
SW_RenderPresent(SDL_Renderer * renderer)
slouken@1895
   674
{
slouken@1918
   675
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@5147
   676
    SDL_Texture *texture = SW_ActivateRenderer(renderer);
slouken@5142
   677
    SDL_Rect rect;
slouken@1895
   678
slouken@5147
   679
    if (!texture) {
slouken@5147
   680
        return;
slouken@5147
   681
    }
slouken@5147
   682
slouken@1895
   683
    /* Send the data to the display */
slouken@5142
   684
    rect.x = 0;
slouken@5142
   685
    rect.y = 0;
slouken@5142
   686
    rect.w = texture->w;
slouken@5142
   687
    rect.h = texture->h;
slouken@5142
   688
    data->renderer->RenderCopy(data->renderer, texture, &rect, &rect);
slouken@1895
   689
    data->renderer->RenderPresent(data->renderer);
slouken@1895
   690
}
slouken@1895
   691
slouken@1895
   692
static void
slouken@1918
   693
SW_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
slouken@1895
   694
{
slouken@1895
   695
    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
slouken@1895
   696
        SDL_SW_DestroyYUVTexture((SDL_SW_YUVTexture *) texture->driverdata);
slouken@1895
   697
    } else {
slouken@1895
   698
        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
slouken@1895
   699
slouken@1895
   700
        SDL_FreeSurface(surface);
slouken@1895
   701
    }
slouken@1895
   702
}
slouken@1895
   703
slouken@1895
   704
static void
slouken@1918
   705
SW_DestroyRenderer(SDL_Renderer * renderer)
slouken@1895
   706
{
slouken@1918
   707
    SW_RenderData *data = (SW_RenderData *) renderer->driverdata;
slouken@3685
   708
    SDL_Window *window = renderer->window;
slouken@1895
   709
slouken@1895
   710
    if (data) {
slouken@5142
   711
        if (data->texture) {
slouken@5142
   712
            DestroyTexture(data->renderer, data->texture);
slouken@1895
   713
        }
slouken@1907
   714
        if (data->surface.format) {
slouken@1907
   715
            SDL_FreeFormat(data->surface.format);
slouken@1907
   716
        }
slouken@1907
   717
        if (data->renderer) {
slouken@1907
   718
            data->renderer->DestroyRenderer(data->renderer);
slouken@1907
   719
        }
slouken@1895
   720
        SDL_FreeDirtyRects(&data->dirty);
slouken@1895
   721
        SDL_free(data);
slouken@1895
   722
    }
slouken@1895
   723
    SDL_free(renderer);
slouken@1895
   724
}
slouken@1895
   725
slouken@1895
   726
/* vi: set ts=4 sw=4 expandtab: */