src/render/software/SDL_blendfillrect.c
author Sam Lantinga
Tue, 15 Feb 2011 13:59:59 -0800
changeset 5297 1800dc39b74c
parent 5262 b530ef003506
child 5535 96594ac5fd1a
permissions -rw-r--r--
Changed the concept of a render clip rect to a render viewport.
The render viewport is automatically re-centered when the window changes size, so applications that don't care will not have to handle recalculating their rendering coordinates.

Fixed API for drawing and filling multiple rectangles - the parameter should be an array of rects, not an array of pointers to rects.

Fixed API for updating window rects for consistency with other APIs - the order is pointer to array followed by count in array.
slouken@5163
     1
/*
slouken@5163
     2
    SDL - Simple DirectMedia Layer
slouken@5262
     3
    Copyright (C) 1997-2011 Sam Lantinga
slouken@5163
     4
slouken@5163
     5
    This library is free software; you can redistribute it and/or
slouken@5163
     6
    modify it under the terms of the GNU Lesser General Public
slouken@5163
     7
    License as published by the Free Software Foundation; either
slouken@5163
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@5163
     9
slouken@5163
    10
    This library is distributed in the hope that it will be useful,
slouken@5163
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@5163
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@5163
    13
    Lesser General Public License for more details.
slouken@5163
    14
slouken@5163
    15
    You should have received a copy of the GNU Lesser General Public
slouken@5163
    16
    License along with this library; if not, write to the Free Software
slouken@5163
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@5163
    18
slouken@5163
    19
    Sam Lantinga
slouken@5163
    20
    slouken@libsdl.org
slouken@5163
    21
*/
slouken@5163
    22
#include "SDL_config.h"
slouken@5163
    23
slouken@5226
    24
#if !SDL_RENDER_DISABLED
slouken@5226
    25
slouken@5163
    26
#include "SDL_draw.h"
slouken@5163
    27
#include "SDL_blendfillrect.h"
slouken@5163
    28
slouken@5163
    29
slouken@5163
    30
static int
slouken@5163
    31
SDL_BlendFillRect_RGB555(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
    32
                         SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
    33
{
slouken@5163
    34
    unsigned inva = 0xff - a;
slouken@5163
    35
slouken@5163
    36
    switch (blendMode) {
slouken@5163
    37
    case SDL_BLENDMODE_BLEND:
slouken@5163
    38
        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB555);
slouken@5163
    39
        break;
slouken@5163
    40
    case SDL_BLENDMODE_ADD:
slouken@5163
    41
        FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB555);
slouken@5163
    42
        break;
slouken@5184
    43
    case SDL_BLENDMODE_MOD:
slouken@5184
    44
        FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB555);
slouken@5184
    45
        break;
slouken@5163
    46
    default:
slouken@5163
    47
        FILLRECT(Uint16, DRAW_SETPIXEL_RGB555);
slouken@5163
    48
        break;
slouken@5163
    49
    }
slouken@5163
    50
    return 0;
slouken@5163
    51
}
slouken@5163
    52
slouken@5163
    53
static int
slouken@5163
    54
SDL_BlendFillRect_RGB565(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
    55
                         SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
    56
{
slouken@5163
    57
    unsigned inva = 0xff - a;
slouken@5163
    58
slouken@5163
    59
    switch (blendMode) {
slouken@5163
    60
    case SDL_BLENDMODE_BLEND:
slouken@5163
    61
        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB565);
slouken@5163
    62
        break;
slouken@5163
    63
    case SDL_BLENDMODE_ADD:
slouken@5163
    64
        FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB565);
slouken@5163
    65
        break;
slouken@5184
    66
    case SDL_BLENDMODE_MOD:
slouken@5184
    67
        FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB565);
slouken@5184
    68
        break;
slouken@5163
    69
    default:
slouken@5163
    70
        FILLRECT(Uint16, DRAW_SETPIXEL_RGB565);
slouken@5163
    71
        break;
slouken@5163
    72
    }
slouken@5163
    73
    return 0;
slouken@5163
    74
}
slouken@5163
    75
slouken@5163
    76
static int
slouken@5163
    77
SDL_BlendFillRect_RGB888(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
    78
                         SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
    79
{
slouken@5163
    80
    unsigned inva = 0xff - a;
slouken@5163
    81
slouken@5163
    82
    switch (blendMode) {
slouken@5163
    83
    case SDL_BLENDMODE_BLEND:
slouken@5163
    84
        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB888);
slouken@5163
    85
        break;
slouken@5163
    86
    case SDL_BLENDMODE_ADD:
slouken@5163
    87
        FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB888);
slouken@5163
    88
        break;
slouken@5184
    89
    case SDL_BLENDMODE_MOD:
slouken@5184
    90
        FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB888);
slouken@5184
    91
        break;
slouken@5163
    92
    default:
slouken@5163
    93
        FILLRECT(Uint32, DRAW_SETPIXEL_RGB888);
slouken@5163
    94
        break;
slouken@5163
    95
    }
slouken@5163
    96
    return 0;
slouken@5163
    97
}
slouken@5163
    98
slouken@5163
    99
static int
slouken@5163
   100
SDL_BlendFillRect_ARGB8888(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   101
                           SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   102
{
slouken@5163
   103
    unsigned inva = 0xff - a;
slouken@5163
   104
slouken@5163
   105
    switch (blendMode) {
slouken@5163
   106
    case SDL_BLENDMODE_BLEND:
slouken@5163
   107
        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888);
slouken@5163
   108
        break;
slouken@5163
   109
    case SDL_BLENDMODE_ADD:
slouken@5163
   110
        FILLRECT(Uint32, DRAW_SETPIXEL_ADD_ARGB8888);
slouken@5163
   111
        break;
slouken@5184
   112
    case SDL_BLENDMODE_MOD:
slouken@5184
   113
        FILLRECT(Uint32, DRAW_SETPIXEL_MOD_ARGB8888);
slouken@5184
   114
        break;
slouken@5163
   115
    default:
slouken@5163
   116
        FILLRECT(Uint32, DRAW_SETPIXEL_ARGB8888);
slouken@5163
   117
        break;
slouken@5163
   118
    }
slouken@5163
   119
    return 0;
slouken@5163
   120
}
slouken@5163
   121
slouken@5163
   122
static int
slouken@5163
   123
SDL_BlendFillRect_RGB(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   124
                      SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   125
{
slouken@5163
   126
    SDL_PixelFormat *fmt = dst->format;
slouken@5163
   127
    unsigned inva = 0xff - a;
slouken@5163
   128
slouken@5163
   129
    switch (fmt->BytesPerPixel) {
slouken@5163
   130
    case 2:
slouken@5163
   131
        switch (blendMode) {
slouken@5163
   132
        case SDL_BLENDMODE_BLEND:
slouken@5163
   133
            FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB);
slouken@5163
   134
            break;
slouken@5163
   135
        case SDL_BLENDMODE_ADD:
slouken@5163
   136
            FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB);
slouken@5163
   137
            break;
slouken@5184
   138
        case SDL_BLENDMODE_MOD:
slouken@5184
   139
            FILLRECT(Uint16, DRAW_SETPIXEL_MOD_RGB);
slouken@5184
   140
            break;
slouken@5163
   141
        default:
slouken@5163
   142
            FILLRECT(Uint16, DRAW_SETPIXEL_RGB);
slouken@5163
   143
            break;
slouken@5163
   144
        }
slouken@5163
   145
        return 0;
slouken@5163
   146
    case 4:
slouken@5163
   147
        switch (blendMode) {
slouken@5163
   148
        case SDL_BLENDMODE_BLEND:
slouken@5163
   149
            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB);
slouken@5163
   150
            break;
slouken@5163
   151
        case SDL_BLENDMODE_ADD:
slouken@5163
   152
            FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB);
slouken@5163
   153
            break;
slouken@5184
   154
        case SDL_BLENDMODE_MOD:
slouken@5184
   155
            FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGB);
slouken@5184
   156
            break;
slouken@5163
   157
        default:
slouken@5163
   158
            FILLRECT(Uint32, DRAW_SETPIXEL_RGB);
slouken@5163
   159
            break;
slouken@5163
   160
        }
slouken@5163
   161
        return 0;
slouken@5163
   162
    default:
slouken@5163
   163
        SDL_Unsupported();
slouken@5163
   164
        return -1;
slouken@5163
   165
    }
slouken@5163
   166
}
slouken@5163
   167
slouken@5163
   168
static int
slouken@5163
   169
SDL_BlendFillRect_RGBA(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   170
                       SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   171
{
slouken@5163
   172
    SDL_PixelFormat *fmt = dst->format;
slouken@5163
   173
    unsigned inva = 0xff - a;
slouken@5163
   174
slouken@5163
   175
    switch (fmt->BytesPerPixel) {
slouken@5163
   176
    case 4:
slouken@5163
   177
        switch (blendMode) {
slouken@5163
   178
        case SDL_BLENDMODE_BLEND:
slouken@5163
   179
            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGBA);
slouken@5163
   180
            break;
slouken@5163
   181
        case SDL_BLENDMODE_ADD:
slouken@5163
   182
            FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGBA);
slouken@5163
   183
            break;
slouken@5184
   184
        case SDL_BLENDMODE_MOD:
slouken@5184
   185
            FILLRECT(Uint32, DRAW_SETPIXEL_MOD_RGBA);
slouken@5184
   186
            break;
slouken@5163
   187
        default:
slouken@5163
   188
            FILLRECT(Uint32, DRAW_SETPIXEL_RGBA);
slouken@5163
   189
            break;
slouken@5163
   190
        }
slouken@5163
   191
        return 0;
slouken@5163
   192
    default:
slouken@5163
   193
        SDL_Unsupported();
slouken@5163
   194
        return -1;
slouken@5163
   195
    }
slouken@5163
   196
}
slouken@5163
   197
slouken@5163
   198
int
slouken@5163
   199
SDL_BlendFillRect(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   200
                  SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   201
{
slouken@5163
   202
    SDL_Rect clipped;
slouken@5163
   203
slouken@5163
   204
    if (!dst) {
slouken@5163
   205
        SDL_SetError("Passed NULL destination surface");
slouken@5163
   206
        return -1;
slouken@5163
   207
    }
slouken@5163
   208
slouken@5163
   209
    /* This function doesn't work on surfaces < 8 bpp */
slouken@5163
   210
    if (dst->format->BitsPerPixel < 8) {
slouken@5163
   211
        SDL_SetError("SDL_BlendFillRect(): Unsupported surface format");
slouken@5163
   212
        return -1;
slouken@5163
   213
    }
slouken@5163
   214
slouken@5163
   215
    /* If 'rect' == NULL, then fill the whole surface */
slouken@5163
   216
    if (rect) {
slouken@5163
   217
        /* Perform clipping */
slouken@5163
   218
        if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
slouken@5163
   219
            return 0;
slouken@5163
   220
        }
slouken@5163
   221
        rect = &clipped;
slouken@5163
   222
    } else {
slouken@5163
   223
        rect = &dst->clip_rect;
slouken@5163
   224
    }
slouken@5163
   225
slouken@5163
   226
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@5163
   227
        r = DRAW_MUL(r, a);
slouken@5163
   228
        g = DRAW_MUL(g, a);
slouken@5163
   229
        b = DRAW_MUL(b, a);
slouken@5163
   230
    }
slouken@5163
   231
slouken@5163
   232
    switch (dst->format->BitsPerPixel) {
slouken@5163
   233
    case 15:
slouken@5163
   234
        switch (dst->format->Rmask) {
slouken@5163
   235
        case 0x7C00:
slouken@5163
   236
            return SDL_BlendFillRect_RGB555(dst, rect, blendMode, r, g, b, a);
slouken@5163
   237
        }
slouken@5163
   238
        break;
slouken@5163
   239
    case 16:
slouken@5163
   240
        switch (dst->format->Rmask) {
slouken@5163
   241
        case 0xF800:
slouken@5163
   242
            return SDL_BlendFillRect_RGB565(dst, rect, blendMode, r, g, b, a);
slouken@5163
   243
        }
slouken@5163
   244
        break;
slouken@5163
   245
    case 32:
slouken@5163
   246
        switch (dst->format->Rmask) {
slouken@5163
   247
        case 0x00FF0000:
slouken@5163
   248
            if (!dst->format->Amask) {
slouken@5163
   249
                return SDL_BlendFillRect_RGB888(dst, rect, blendMode, r, g, b, a);
slouken@5163
   250
            } else {
slouken@5163
   251
                return SDL_BlendFillRect_ARGB8888(dst, rect, blendMode, r, g, b, a);
slouken@5163
   252
            }
slouken@5163
   253
            break;
slouken@5163
   254
        }
slouken@5163
   255
        break;
slouken@5163
   256
    default:
slouken@5163
   257
        break;
slouken@5163
   258
    }
slouken@5163
   259
slouken@5163
   260
    if (!dst->format->Amask) {
slouken@5163
   261
        return SDL_BlendFillRect_RGB(dst, rect, blendMode, r, g, b, a);
slouken@5163
   262
    } else {
slouken@5163
   263
        return SDL_BlendFillRect_RGBA(dst, rect, blendMode, r, g, b, a);
slouken@5163
   264
    }
slouken@5163
   265
}
slouken@5163
   266
slouken@5163
   267
int
slouken@5297
   268
SDL_BlendFillRects(SDL_Surface * dst, const SDL_Rect * rects, int count,
slouken@5163
   269
                   SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   270
{
slouken@5297
   271
    SDL_Rect rect;
slouken@5163
   272
    int i;
slouken@5163
   273
    int (*func)(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   274
                SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
slouken@5163
   275
    int status = 0;
slouken@5163
   276
slouken@5163
   277
    if (!dst) {
slouken@5163
   278
        SDL_SetError("Passed NULL destination surface");
slouken@5163
   279
        return -1;
slouken@5163
   280
    }
slouken@5163
   281
slouken@5163
   282
    /* This function doesn't work on surfaces < 8 bpp */
slouken@5163
   283
    if (dst->format->BitsPerPixel < 8) {
slouken@5163
   284
        SDL_SetError("SDL_BlendFillRects(): Unsupported surface format");
slouken@5163
   285
        return -1;
slouken@5163
   286
    }
slouken@5163
   287
slouken@5163
   288
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@5163
   289
        r = DRAW_MUL(r, a);
slouken@5163
   290
        g = DRAW_MUL(g, a);
slouken@5163
   291
        b = DRAW_MUL(b, a);
slouken@5163
   292
    }
slouken@5163
   293
slouken@5163
   294
    /* FIXME: Does this function pointer slow things down significantly? */
slouken@5163
   295
    switch (dst->format->BitsPerPixel) {
slouken@5163
   296
    case 15:
slouken@5163
   297
        switch (dst->format->Rmask) {
slouken@5163
   298
        case 0x7C00:
slouken@5163
   299
            func = SDL_BlendFillRect_RGB555;
slouken@5163
   300
        }
slouken@5163
   301
        break;
slouken@5163
   302
    case 16:
slouken@5163
   303
        switch (dst->format->Rmask) {
slouken@5163
   304
        case 0xF800:
slouken@5163
   305
            func = SDL_BlendFillRect_RGB565;
slouken@5163
   306
        }
slouken@5163
   307
        break;
slouken@5163
   308
    case 32:
slouken@5163
   309
        switch (dst->format->Rmask) {
slouken@5163
   310
        case 0x00FF0000:
slouken@5163
   311
            if (!dst->format->Amask) {
slouken@5163
   312
                func = SDL_BlendFillRect_RGB888;
slouken@5163
   313
            } else {
slouken@5163
   314
                func = SDL_BlendFillRect_ARGB8888;
slouken@5163
   315
            }
slouken@5163
   316
            break;
slouken@5163
   317
        }
slouken@5163
   318
        break;
slouken@5163
   319
    default:
slouken@5163
   320
        break;
slouken@5163
   321
    }
slouken@5163
   322
slouken@5163
   323
    if (!func) {
slouken@5163
   324
        if (!dst->format->Amask) {
slouken@5163
   325
            func = SDL_BlendFillRect_RGB;
slouken@5163
   326
        } else {
slouken@5163
   327
            func = SDL_BlendFillRect_RGBA;
slouken@5163
   328
        }
slouken@5163
   329
    }
slouken@5163
   330
slouken@5163
   331
    for (i = 0; i < count; ++i) {
slouken@5297
   332
        /* Perform clipping */
slouken@5297
   333
        if (!SDL_IntersectRect(&rects[i], &dst->clip_rect, &rect)) {
slouken@5297
   334
            continue;
slouken@5163
   335
        }
slouken@5297
   336
        status = func(dst, &rect, blendMode, r, g, b, a);
slouken@5163
   337
    }
slouken@5163
   338
    return status;
slouken@5163
   339
}
slouken@5163
   340
slouken@5226
   341
#endif /* !SDL_RENDER_DISABLED */
slouken@5226
   342
slouken@5163
   343
/* vi: set ts=4 sw=4 expandtab: */