src/render/software/SDL_blendfillrect.c
author Sam Lantinga
Thu, 03 Feb 2011 02:45:29 -0800
changeset 5163 d72793305335
child 5184 d976b67150c5
permissions -rw-r--r--
Making the API simpler, moved the surface drawing functions to the software renderer.
slouken@5163
     1
/*
slouken@5163
     2
    SDL - Simple DirectMedia Layer
slouken@5163
     3
    Copyright (C) 1997-2010 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@5163
    24
#include "SDL_draw.h"
slouken@5163
    25
#include "SDL_blendfillrect.h"
slouken@5163
    26
slouken@5163
    27
slouken@5163
    28
static int
slouken@5163
    29
SDL_BlendFillRect_RGB555(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
    30
                         SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
    31
{
slouken@5163
    32
    unsigned inva = 0xff - a;
slouken@5163
    33
slouken@5163
    34
    switch (blendMode) {
slouken@5163
    35
    case SDL_BLENDMODE_BLEND:
slouken@5163
    36
        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB555);
slouken@5163
    37
        break;
slouken@5163
    38
    case SDL_BLENDMODE_ADD:
slouken@5163
    39
        FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB555);
slouken@5163
    40
        break;
slouken@5163
    41
    default:
slouken@5163
    42
        FILLRECT(Uint16, DRAW_SETPIXEL_RGB555);
slouken@5163
    43
        break;
slouken@5163
    44
    }
slouken@5163
    45
    return 0;
slouken@5163
    46
}
slouken@5163
    47
slouken@5163
    48
static int
slouken@5163
    49
SDL_BlendFillRect_RGB565(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
    50
                         SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
    51
{
slouken@5163
    52
    unsigned inva = 0xff - a;
slouken@5163
    53
slouken@5163
    54
    switch (blendMode) {
slouken@5163
    55
    case SDL_BLENDMODE_BLEND:
slouken@5163
    56
        FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB565);
slouken@5163
    57
        break;
slouken@5163
    58
    case SDL_BLENDMODE_ADD:
slouken@5163
    59
        FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB565);
slouken@5163
    60
        break;
slouken@5163
    61
    default:
slouken@5163
    62
        FILLRECT(Uint16, DRAW_SETPIXEL_RGB565);
slouken@5163
    63
        break;
slouken@5163
    64
    }
slouken@5163
    65
    return 0;
slouken@5163
    66
}
slouken@5163
    67
slouken@5163
    68
static int
slouken@5163
    69
SDL_BlendFillRect_RGB888(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
    70
                         SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
    71
{
slouken@5163
    72
    unsigned inva = 0xff - a;
slouken@5163
    73
slouken@5163
    74
    switch (blendMode) {
slouken@5163
    75
    case SDL_BLENDMODE_BLEND:
slouken@5163
    76
        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB888);
slouken@5163
    77
        break;
slouken@5163
    78
    case SDL_BLENDMODE_ADD:
slouken@5163
    79
        FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB888);
slouken@5163
    80
        break;
slouken@5163
    81
    default:
slouken@5163
    82
        FILLRECT(Uint32, DRAW_SETPIXEL_RGB888);
slouken@5163
    83
        break;
slouken@5163
    84
    }
slouken@5163
    85
    return 0;
slouken@5163
    86
}
slouken@5163
    87
slouken@5163
    88
static int
slouken@5163
    89
SDL_BlendFillRect_ARGB8888(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
    90
                           SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
    91
{
slouken@5163
    92
    unsigned inva = 0xff - a;
slouken@5163
    93
slouken@5163
    94
    switch (blendMode) {
slouken@5163
    95
    case SDL_BLENDMODE_BLEND:
slouken@5163
    96
        FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_ARGB8888);
slouken@5163
    97
        break;
slouken@5163
    98
    case SDL_BLENDMODE_ADD:
slouken@5163
    99
        FILLRECT(Uint32, DRAW_SETPIXEL_ADD_ARGB8888);
slouken@5163
   100
        break;
slouken@5163
   101
    default:
slouken@5163
   102
        FILLRECT(Uint32, DRAW_SETPIXEL_ARGB8888);
slouken@5163
   103
        break;
slouken@5163
   104
    }
slouken@5163
   105
    return 0;
slouken@5163
   106
}
slouken@5163
   107
slouken@5163
   108
static int
slouken@5163
   109
SDL_BlendFillRect_RGB(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   110
                      SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   111
{
slouken@5163
   112
    SDL_PixelFormat *fmt = dst->format;
slouken@5163
   113
    unsigned inva = 0xff - a;
slouken@5163
   114
slouken@5163
   115
    switch (fmt->BytesPerPixel) {
slouken@5163
   116
    case 2:
slouken@5163
   117
        switch (blendMode) {
slouken@5163
   118
        case SDL_BLENDMODE_BLEND:
slouken@5163
   119
            FILLRECT(Uint16, DRAW_SETPIXEL_BLEND_RGB);
slouken@5163
   120
            break;
slouken@5163
   121
        case SDL_BLENDMODE_ADD:
slouken@5163
   122
            FILLRECT(Uint16, DRAW_SETPIXEL_ADD_RGB);
slouken@5163
   123
            break;
slouken@5163
   124
        default:
slouken@5163
   125
            FILLRECT(Uint16, DRAW_SETPIXEL_RGB);
slouken@5163
   126
            break;
slouken@5163
   127
        }
slouken@5163
   128
        return 0;
slouken@5163
   129
    case 4:
slouken@5163
   130
        switch (blendMode) {
slouken@5163
   131
        case SDL_BLENDMODE_BLEND:
slouken@5163
   132
            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGB);
slouken@5163
   133
            break;
slouken@5163
   134
        case SDL_BLENDMODE_ADD:
slouken@5163
   135
            FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGB);
slouken@5163
   136
            break;
slouken@5163
   137
        default:
slouken@5163
   138
            FILLRECT(Uint32, DRAW_SETPIXEL_RGB);
slouken@5163
   139
            break;
slouken@5163
   140
        }
slouken@5163
   141
        return 0;
slouken@5163
   142
    default:
slouken@5163
   143
        SDL_Unsupported();
slouken@5163
   144
        return -1;
slouken@5163
   145
    }
slouken@5163
   146
}
slouken@5163
   147
slouken@5163
   148
static int
slouken@5163
   149
SDL_BlendFillRect_RGBA(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   150
                       SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   151
{
slouken@5163
   152
    SDL_PixelFormat *fmt = dst->format;
slouken@5163
   153
    unsigned inva = 0xff - a;
slouken@5163
   154
slouken@5163
   155
    switch (fmt->BytesPerPixel) {
slouken@5163
   156
    case 4:
slouken@5163
   157
        switch (blendMode) {
slouken@5163
   158
        case SDL_BLENDMODE_BLEND:
slouken@5163
   159
            FILLRECT(Uint32, DRAW_SETPIXEL_BLEND_RGBA);
slouken@5163
   160
            break;
slouken@5163
   161
        case SDL_BLENDMODE_ADD:
slouken@5163
   162
            FILLRECT(Uint32, DRAW_SETPIXEL_ADD_RGBA);
slouken@5163
   163
            break;
slouken@5163
   164
        default:
slouken@5163
   165
            FILLRECT(Uint32, DRAW_SETPIXEL_RGBA);
slouken@5163
   166
            break;
slouken@5163
   167
        }
slouken@5163
   168
        return 0;
slouken@5163
   169
    default:
slouken@5163
   170
        SDL_Unsupported();
slouken@5163
   171
        return -1;
slouken@5163
   172
    }
slouken@5163
   173
}
slouken@5163
   174
slouken@5163
   175
int
slouken@5163
   176
SDL_BlendFillRect(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   177
                  SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   178
{
slouken@5163
   179
    SDL_Rect clipped;
slouken@5163
   180
slouken@5163
   181
    if (!dst) {
slouken@5163
   182
        SDL_SetError("Passed NULL destination surface");
slouken@5163
   183
        return -1;
slouken@5163
   184
    }
slouken@5163
   185
slouken@5163
   186
    /* This function doesn't work on surfaces < 8 bpp */
slouken@5163
   187
    if (dst->format->BitsPerPixel < 8) {
slouken@5163
   188
        SDL_SetError("SDL_BlendFillRect(): Unsupported surface format");
slouken@5163
   189
        return -1;
slouken@5163
   190
    }
slouken@5163
   191
slouken@5163
   192
    /* If 'rect' == NULL, then fill the whole surface */
slouken@5163
   193
    if (rect) {
slouken@5163
   194
        /* Perform clipping */
slouken@5163
   195
        if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
slouken@5163
   196
            return 0;
slouken@5163
   197
        }
slouken@5163
   198
        rect = &clipped;
slouken@5163
   199
    } else {
slouken@5163
   200
        rect = &dst->clip_rect;
slouken@5163
   201
    }
slouken@5163
   202
slouken@5163
   203
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@5163
   204
        r = DRAW_MUL(r, a);
slouken@5163
   205
        g = DRAW_MUL(g, a);
slouken@5163
   206
        b = DRAW_MUL(b, a);
slouken@5163
   207
    }
slouken@5163
   208
slouken@5163
   209
    switch (dst->format->BitsPerPixel) {
slouken@5163
   210
    case 15:
slouken@5163
   211
        switch (dst->format->Rmask) {
slouken@5163
   212
        case 0x7C00:
slouken@5163
   213
            return SDL_BlendFillRect_RGB555(dst, rect, blendMode, r, g, b, a);
slouken@5163
   214
        }
slouken@5163
   215
        break;
slouken@5163
   216
    case 16:
slouken@5163
   217
        switch (dst->format->Rmask) {
slouken@5163
   218
        case 0xF800:
slouken@5163
   219
            return SDL_BlendFillRect_RGB565(dst, rect, blendMode, r, g, b, a);
slouken@5163
   220
        }
slouken@5163
   221
        break;
slouken@5163
   222
    case 32:
slouken@5163
   223
        switch (dst->format->Rmask) {
slouken@5163
   224
        case 0x00FF0000:
slouken@5163
   225
            if (!dst->format->Amask) {
slouken@5163
   226
                return SDL_BlendFillRect_RGB888(dst, rect, blendMode, r, g, b, a);
slouken@5163
   227
            } else {
slouken@5163
   228
                return SDL_BlendFillRect_ARGB8888(dst, rect, blendMode, r, g, b, a);
slouken@5163
   229
            }
slouken@5163
   230
            break;
slouken@5163
   231
        }
slouken@5163
   232
        break;
slouken@5163
   233
    default:
slouken@5163
   234
        break;
slouken@5163
   235
    }
slouken@5163
   236
slouken@5163
   237
    if (!dst->format->Amask) {
slouken@5163
   238
        return SDL_BlendFillRect_RGB(dst, rect, blendMode, r, g, b, a);
slouken@5163
   239
    } else {
slouken@5163
   240
        return SDL_BlendFillRect_RGBA(dst, rect, blendMode, r, g, b, a);
slouken@5163
   241
    }
slouken@5163
   242
}
slouken@5163
   243
slouken@5163
   244
int
slouken@5163
   245
SDL_BlendFillRects(SDL_Surface * dst, const SDL_Rect ** rects, int count,
slouken@5163
   246
                   SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@5163
   247
{
slouken@5163
   248
    SDL_Rect clipped;
slouken@5163
   249
    int i;
slouken@5163
   250
    int (*func)(SDL_Surface * dst, const SDL_Rect * rect,
slouken@5163
   251
                SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
slouken@5163
   252
    int status = 0;
slouken@5163
   253
slouken@5163
   254
    if (!dst) {
slouken@5163
   255
        SDL_SetError("Passed NULL destination surface");
slouken@5163
   256
        return -1;
slouken@5163
   257
    }
slouken@5163
   258
slouken@5163
   259
    /* This function doesn't work on surfaces < 8 bpp */
slouken@5163
   260
    if (dst->format->BitsPerPixel < 8) {
slouken@5163
   261
        SDL_SetError("SDL_BlendFillRects(): Unsupported surface format");
slouken@5163
   262
        return -1;
slouken@5163
   263
    }
slouken@5163
   264
slouken@5163
   265
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@5163
   266
        r = DRAW_MUL(r, a);
slouken@5163
   267
        g = DRAW_MUL(g, a);
slouken@5163
   268
        b = DRAW_MUL(b, a);
slouken@5163
   269
    }
slouken@5163
   270
slouken@5163
   271
    /* FIXME: Does this function pointer slow things down significantly? */
slouken@5163
   272
    switch (dst->format->BitsPerPixel) {
slouken@5163
   273
    case 15:
slouken@5163
   274
        switch (dst->format->Rmask) {
slouken@5163
   275
        case 0x7C00:
slouken@5163
   276
            func = SDL_BlendFillRect_RGB555;
slouken@5163
   277
        }
slouken@5163
   278
        break;
slouken@5163
   279
    case 16:
slouken@5163
   280
        switch (dst->format->Rmask) {
slouken@5163
   281
        case 0xF800:
slouken@5163
   282
            func = SDL_BlendFillRect_RGB565;
slouken@5163
   283
        }
slouken@5163
   284
        break;
slouken@5163
   285
    case 32:
slouken@5163
   286
        switch (dst->format->Rmask) {
slouken@5163
   287
        case 0x00FF0000:
slouken@5163
   288
            if (!dst->format->Amask) {
slouken@5163
   289
                func = SDL_BlendFillRect_RGB888;
slouken@5163
   290
            } else {
slouken@5163
   291
                func = SDL_BlendFillRect_ARGB8888;
slouken@5163
   292
            }
slouken@5163
   293
            break;
slouken@5163
   294
        }
slouken@5163
   295
        break;
slouken@5163
   296
    default:
slouken@5163
   297
        break;
slouken@5163
   298
    }
slouken@5163
   299
slouken@5163
   300
    if (!func) {
slouken@5163
   301
        if (!dst->format->Amask) {
slouken@5163
   302
            func = SDL_BlendFillRect_RGB;
slouken@5163
   303
        } else {
slouken@5163
   304
            func = SDL_BlendFillRect_RGBA;
slouken@5163
   305
        }
slouken@5163
   306
    }
slouken@5163
   307
slouken@5163
   308
    for (i = 0; i < count; ++i) {
slouken@5163
   309
        const SDL_Rect * rect = rects[i];
slouken@5163
   310
slouken@5163
   311
        /* If 'rect' == NULL, then fill the whole surface */
slouken@5163
   312
        if (rect) {
slouken@5163
   313
            /* Perform clipping */
slouken@5163
   314
            if (!SDL_IntersectRect(rect, &dst->clip_rect, &clipped)) {
slouken@5163
   315
                continue;
slouken@5163
   316
            }
slouken@5163
   317
            rect = &clipped;
slouken@5163
   318
        } else {
slouken@5163
   319
            rect = &dst->clip_rect;
slouken@5163
   320
        }
slouken@5163
   321
slouken@5163
   322
        status = func(dst, rect, blendMode, r, g, b, a);
slouken@5163
   323
    }
slouken@5163
   324
    return status;
slouken@5163
   325
}
slouken@5163
   326
slouken@5163
   327
/* vi: set ts=4 sw=4 expandtab: */