src/render/software/SDL_blendpoint.c
author Ryan C. Gordon
Mon, 23 Jan 2017 12:06:10 -0500
changeset 10837 c2f241c2f6ad
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
audio: Fix same bug as last commit, but for _mm_bslli_si128 vs _mm_slli_si128.
slouken@2901
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@2901
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@2901
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@2901
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@2901
    20
*/
icculus@8093
    21
#include "../../SDL_internal.h"
slouken@2901
    22
slouken@5226
    23
#if !SDL_RENDER_DISABLED
slouken@5226
    24
slouken@2901
    25
#include "SDL_draw.h"
slouken@5163
    26
#include "SDL_blendpoint.h"
slouken@5163
    27
slouken@2901
    28
slouken@2901
    29
static int
slouken@4929
    30
SDL_BlendPoint_RGB555(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
slouken@2901
    31
                      Uint8 g, Uint8 b, Uint8 a)
slouken@2901
    32
{
slouken@2901
    33
    unsigned inva = 0xff - a;
slouken@2901
    34
slouken@2901
    35
    switch (blendMode) {
slouken@2901
    36
    case SDL_BLENDMODE_BLEND:
slouken@2901
    37
        DRAW_SETPIXELXY_BLEND_RGB555(x, y);
slouken@2901
    38
        break;
slouken@2901
    39
    case SDL_BLENDMODE_ADD:
slouken@2901
    40
        DRAW_SETPIXELXY_ADD_RGB555(x, y);
slouken@2901
    41
        break;
slouken@5184
    42
    case SDL_BLENDMODE_MOD:
slouken@5184
    43
        DRAW_SETPIXELXY_MOD_RGB555(x, y);
slouken@5184
    44
        break;
slouken@2901
    45
    default:
slouken@2901
    46
        DRAW_SETPIXELXY_RGB555(x, y);
slouken@2901
    47
        break;
slouken@2901
    48
    }
slouken@2901
    49
    return 0;
slouken@2901
    50
}
slouken@2901
    51
slouken@2901
    52
static int
slouken@4929
    53
SDL_BlendPoint_RGB565(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
slouken@2901
    54
                      Uint8 g, Uint8 b, Uint8 a)
slouken@2901
    55
{
slouken@2901
    56
    unsigned inva = 0xff - a;
slouken@2901
    57
slouken@2901
    58
    switch (blendMode) {
slouken@2901
    59
    case SDL_BLENDMODE_BLEND:
slouken@2901
    60
        DRAW_SETPIXELXY_BLEND_RGB565(x, y);
slouken@2901
    61
        break;
slouken@2901
    62
    case SDL_BLENDMODE_ADD:
slouken@2901
    63
        DRAW_SETPIXELXY_ADD_RGB565(x, y);
slouken@2901
    64
        break;
slouken@5184
    65
    case SDL_BLENDMODE_MOD:
slouken@5184
    66
        DRAW_SETPIXELXY_MOD_RGB565(x, y);
slouken@5184
    67
        break;
slouken@2901
    68
    default:
slouken@2901
    69
        DRAW_SETPIXELXY_RGB565(x, y);
slouken@2901
    70
        break;
slouken@2901
    71
    }
slouken@2901
    72
    return 0;
slouken@2901
    73
}
slouken@2901
    74
slouken@2901
    75
static int
slouken@4929
    76
SDL_BlendPoint_RGB888(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
slouken@2901
    77
                      Uint8 g, Uint8 b, Uint8 a)
slouken@2901
    78
{
slouken@2901
    79
    unsigned inva = 0xff - a;
slouken@2901
    80
slouken@2901
    81
    switch (blendMode) {
slouken@2901
    82
    case SDL_BLENDMODE_BLEND:
slouken@2901
    83
        DRAW_SETPIXELXY_BLEND_RGB888(x, y);
slouken@2901
    84
        break;
slouken@2901
    85
    case SDL_BLENDMODE_ADD:
slouken@2901
    86
        DRAW_SETPIXELXY_ADD_RGB888(x, y);
slouken@2901
    87
        break;
slouken@5184
    88
    case SDL_BLENDMODE_MOD:
slouken@5184
    89
        DRAW_SETPIXELXY_MOD_RGB888(x, y);
slouken@5184
    90
        break;
slouken@2901
    91
    default:
slouken@2901
    92
        DRAW_SETPIXELXY_RGB888(x, y);
slouken@2901
    93
        break;
slouken@2901
    94
    }
slouken@2901
    95
    return 0;
slouken@2901
    96
}
slouken@2901
    97
slouken@2901
    98
static int
slouken@4929
    99
SDL_BlendPoint_ARGB8888(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode,
slouken@2901
   100
                        Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@2901
   101
{
slouken@2901
   102
    unsigned inva = 0xff - a;
slouken@2901
   103
slouken@2901
   104
    switch (blendMode) {
slouken@2901
   105
    case SDL_BLENDMODE_BLEND:
slouken@2901
   106
        DRAW_SETPIXELXY_BLEND_ARGB8888(x, y);
slouken@2901
   107
        break;
slouken@2901
   108
    case SDL_BLENDMODE_ADD:
slouken@2901
   109
        DRAW_SETPIXELXY_ADD_ARGB8888(x, y);
slouken@2901
   110
        break;
slouken@5184
   111
    case SDL_BLENDMODE_MOD:
slouken@5184
   112
        DRAW_SETPIXELXY_MOD_ARGB8888(x, y);
slouken@5184
   113
        break;
slouken@2901
   114
    default:
slouken@2901
   115
        DRAW_SETPIXELXY_ARGB8888(x, y);
slouken@2901
   116
        break;
slouken@2901
   117
    }
slouken@2901
   118
    return 0;
slouken@2901
   119
}
slouken@2901
   120
slouken@2901
   121
static int
slouken@4929
   122
SDL_BlendPoint_RGB(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
slouken@2901
   123
                   Uint8 g, Uint8 b, Uint8 a)
slouken@2901
   124
{
slouken@2901
   125
    SDL_PixelFormat *fmt = dst->format;
slouken@2901
   126
    unsigned inva = 0xff - a;
slouken@2901
   127
slouken@2901
   128
    switch (fmt->BytesPerPixel) {
slouken@2901
   129
    case 2:
slouken@2901
   130
        switch (blendMode) {
slouken@2901
   131
        case SDL_BLENDMODE_BLEND:
slouken@2901
   132
            DRAW_SETPIXELXY2_BLEND_RGB(x, y);
slouken@2901
   133
            break;
slouken@2901
   134
        case SDL_BLENDMODE_ADD:
slouken@2901
   135
            DRAW_SETPIXELXY2_ADD_RGB(x, y);
slouken@2901
   136
            break;
slouken@5184
   137
        case SDL_BLENDMODE_MOD:
slouken@5184
   138
            DRAW_SETPIXELXY2_MOD_RGB(x, y);
slouken@5184
   139
            break;
slouken@2901
   140
        default:
slouken@2901
   141
            DRAW_SETPIXELXY2_RGB(x, y);
slouken@2901
   142
            break;
slouken@2901
   143
        }
slouken@2901
   144
        return 0;
slouken@2901
   145
    case 4:
slouken@2901
   146
        switch (blendMode) {
slouken@2901
   147
        case SDL_BLENDMODE_BLEND:
slouken@2901
   148
            DRAW_SETPIXELXY4_BLEND_RGB(x, y);
slouken@2901
   149
            break;
slouken@2901
   150
        case SDL_BLENDMODE_ADD:
slouken@2901
   151
            DRAW_SETPIXELXY4_ADD_RGB(x, y);
slouken@2901
   152
            break;
slouken@5184
   153
        case SDL_BLENDMODE_MOD:
slouken@5184
   154
            DRAW_SETPIXELXY4_MOD_RGB(x, y);
slouken@5184
   155
            break;
slouken@2901
   156
        default:
slouken@2901
   157
            DRAW_SETPIXELXY4_RGB(x, y);
slouken@2901
   158
            break;
slouken@2901
   159
        }
slouken@2901
   160
        return 0;
slouken@2901
   161
    default:
icculus@7037
   162
        return SDL_Unsupported();
slouken@2901
   163
    }
slouken@2901
   164
}
slouken@2901
   165
slouken@2901
   166
static int
slouken@4929
   167
SDL_BlendPoint_RGBA(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
slouken@2901
   168
                    Uint8 g, Uint8 b, Uint8 a)
slouken@2901
   169
{
slouken@2901
   170
    SDL_PixelFormat *fmt = dst->format;
slouken@2901
   171
    unsigned inva = 0xff - a;
slouken@2901
   172
slouken@2901
   173
    switch (fmt->BytesPerPixel) {
slouken@2901
   174
    case 4:
slouken@2901
   175
        switch (blendMode) {
slouken@2901
   176
        case SDL_BLENDMODE_BLEND:
slouken@2901
   177
            DRAW_SETPIXELXY4_BLEND_RGBA(x, y);
slouken@2901
   178
            break;
slouken@2901
   179
        case SDL_BLENDMODE_ADD:
slouken@2901
   180
            DRAW_SETPIXELXY4_ADD_RGBA(x, y);
slouken@2901
   181
            break;
slouken@5184
   182
        case SDL_BLENDMODE_MOD:
slouken@5184
   183
            DRAW_SETPIXELXY4_MOD_RGBA(x, y);
slouken@5184
   184
            break;
slouken@2901
   185
        default:
slouken@2901
   186
            DRAW_SETPIXELXY4_RGBA(x, y);
slouken@2901
   187
            break;
slouken@2901
   188
        }
slouken@2901
   189
        return 0;
slouken@2901
   190
    default:
icculus@7037
   191
        return SDL_Unsupported();
slouken@2901
   192
    }
slouken@2901
   193
}
slouken@2901
   194
slouken@2901
   195
int
slouken@4929
   196
SDL_BlendPoint(SDL_Surface * dst, int x, int y, SDL_BlendMode blendMode, Uint8 r,
slouken@2901
   197
               Uint8 g, Uint8 b, Uint8 a)
slouken@2901
   198
{
slouken@3536
   199
    if (!dst) {
icculus@7037
   200
        return SDL_SetError("Passed NULL destination surface");
slouken@3536
   201
    }
slouken@2901
   202
slouken@2901
   203
    /* This function doesn't work on surfaces < 8 bpp */
slouken@2901
   204
    if (dst->format->BitsPerPixel < 8) {
icculus@7037
   205
        return SDL_SetError("SDL_BlendPoint(): Unsupported surface format");
slouken@2901
   206
    }
slouken@2901
   207
slouken@2901
   208
    /* Perform clipping */
slouken@2901
   209
    if (x < dst->clip_rect.x || y < dst->clip_rect.y ||
slouken@2901
   210
        x >= (dst->clip_rect.x + dst->clip_rect.w) ||
slouken@2901
   211
        y >= (dst->clip_rect.y + dst->clip_rect.h)) {
slouken@2901
   212
        return 0;
slouken@2901
   213
    }
slouken@2901
   214
slouken@3536
   215
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@2901
   216
        r = DRAW_MUL(r, a);
slouken@2901
   217
        g = DRAW_MUL(g, a);
slouken@2901
   218
        b = DRAW_MUL(b, a);
slouken@2901
   219
    }
slouken@2901
   220
slouken@3536
   221
    switch (dst->format->BitsPerPixel) {
slouken@2901
   222
    case 15:
slouken@3536
   223
        switch (dst->format->Rmask) {
slouken@2901
   224
        case 0x7C00:
slouken@2901
   225
            return SDL_BlendPoint_RGB555(dst, x, y, blendMode, r, g, b, a);
slouken@2901
   226
        }
slouken@2901
   227
        break;
slouken@2901
   228
    case 16:
slouken@3536
   229
        switch (dst->format->Rmask) {
slouken@2901
   230
        case 0xF800:
slouken@2901
   231
            return SDL_BlendPoint_RGB565(dst, x, y, blendMode, r, g, b, a);
slouken@2901
   232
        }
slouken@2901
   233
        break;
slouken@2901
   234
    case 32:
slouken@3536
   235
        switch (dst->format->Rmask) {
slouken@2901
   236
        case 0x00FF0000:
slouken@3536
   237
            if (!dst->format->Amask) {
slouken@10609
   238
                return SDL_BlendPoint_RGB888(dst, x, y, blendMode, r, g, b, a);
slouken@2901
   239
            } else {
slouken@10609
   240
                return SDL_BlendPoint_ARGB8888(dst, x, y, blendMode, r, g, b, a);
slouken@2901
   241
            }
slouken@10609
   242
            /* break; -Wunreachable-code-break */
slouken@2901
   243
        }
slouken@3536
   244
        break;
slouken@2901
   245
    default:
slouken@2901
   246
        break;
slouken@2901
   247
    }
slouken@2901
   248
slouken@3536
   249
    if (!dst->format->Amask) {
slouken@2901
   250
        return SDL_BlendPoint_RGB(dst, x, y, blendMode, r, g, b, a);
slouken@2901
   251
    } else {
slouken@2901
   252
        return SDL_BlendPoint_RGBA(dst, x, y, blendMode, r, g, b, a);
slouken@2901
   253
    }
slouken@2901
   254
}
slouken@2901
   255
slouken@3536
   256
int
slouken@3536
   257
SDL_BlendPoints(SDL_Surface * dst, const SDL_Point * points, int count,
slouken@4929
   258
                SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@3536
   259
{
slouken@3536
   260
    int minx, miny;
slouken@3536
   261
    int maxx, maxy;
slouken@3536
   262
    int i;
slouken@3536
   263
    int x, y;
slouken@3536
   264
    int (*func)(SDL_Surface * dst, int x, int y,
slouken@4929
   265
                SDL_BlendMode blendMode, Uint8 r, Uint8 g, Uint8 b, Uint8 a) = NULL;
slouken@3536
   266
    int status = 0;
slouken@3536
   267
slouken@3536
   268
    if (!dst) {
icculus@7037
   269
        return SDL_SetError("Passed NULL destination surface");
slouken@3536
   270
    }
slouken@3536
   271
slouken@3536
   272
    /* This function doesn't work on surfaces < 8 bpp */
slouken@3536
   273
    if (dst->format->BitsPerPixel < 8) {
icculus@7037
   274
        return SDL_SetError("SDL_BlendPoints(): Unsupported surface format");
slouken@3536
   275
    }
slouken@3536
   276
slouken@3536
   277
    if (blendMode == SDL_BLENDMODE_BLEND || blendMode == SDL_BLENDMODE_ADD) {
slouken@3536
   278
        r = DRAW_MUL(r, a);
slouken@3536
   279
        g = DRAW_MUL(g, a);
slouken@3536
   280
        b = DRAW_MUL(b, a);
slouken@3536
   281
    }
slouken@3536
   282
slouken@3536
   283
    /* FIXME: Does this function pointer slow things down significantly? */
slouken@3536
   284
    switch (dst->format->BitsPerPixel) {
slouken@3536
   285
    case 15:
slouken@3536
   286
        switch (dst->format->Rmask) {
slouken@3536
   287
        case 0x7C00:
slouken@3536
   288
            func = SDL_BlendPoint_RGB555;
slouken@3536
   289
            break;
slouken@3536
   290
        }
slouken@3536
   291
        break;
slouken@3536
   292
    case 16:
slouken@3536
   293
        switch (dst->format->Rmask) {
slouken@3536
   294
        case 0xF800:
slouken@3536
   295
            func = SDL_BlendPoint_RGB565;
slouken@3536
   296
            break;
slouken@3536
   297
        }
slouken@3536
   298
        break;
slouken@3536
   299
    case 32:
slouken@3536
   300
        switch (dst->format->Rmask) {
slouken@3536
   301
        case 0x00FF0000:
slouken@3536
   302
            if (!dst->format->Amask) {
slouken@3536
   303
                func = SDL_BlendPoint_RGB888;
slouken@3536
   304
            } else {
slouken@3536
   305
                func = SDL_BlendPoint_ARGB8888;
slouken@3536
   306
            }
slouken@3536
   307
            break;
slouken@3536
   308
        }
slouken@3536
   309
        break;
slouken@3536
   310
    default:
slouken@3536
   311
        break;
slouken@3536
   312
    }
slouken@3536
   313
slouken@3536
   314
    if (!func) {
slouken@3536
   315
        if (!dst->format->Amask) {
slouken@3536
   316
            func = SDL_BlendPoint_RGB;
slouken@3536
   317
        } else {
slouken@3536
   318
            func = SDL_BlendPoint_RGBA;
slouken@3536
   319
        }
slouken@3536
   320
    }
slouken@3536
   321
slouken@3536
   322
    minx = dst->clip_rect.x;
slouken@3536
   323
    maxx = dst->clip_rect.x + dst->clip_rect.w - 1;
slouken@3536
   324
    miny = dst->clip_rect.y;
slouken@3536
   325
    maxy = dst->clip_rect.y + dst->clip_rect.h - 1;
slouken@3536
   326
slouken@3536
   327
    for (i = 0; i < count; ++i) {
slouken@3536
   328
        x = points[i].x;
slouken@3536
   329
        y = points[i].y;
slouken@3536
   330
slouken@3536
   331
        if (x < minx || x > maxx || y < miny || y > maxy) {
slouken@3536
   332
            continue;
slouken@3536
   333
        }
slouken@3536
   334
        status = func(dst, x, y, blendMode, r, g, b, a);
slouken@3536
   335
    }
slouken@3536
   336
    return status;
slouken@3536
   337
}
slouken@3536
   338
slouken@5226
   339
#endif /* !SDL_RENDER_DISABLED */
slouken@5226
   340
slouken@2901
   341
/* vi: set ts=4 sw=4 expandtab: */