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