src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 24 Sep 2018 11:49:25 -0700
changeset 12201 8bdc4d340419
parent 11877 2a25e8690229
child 12503 806492103856
permissions -rw-r--r--
Fixed whitespace
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
slouken@0
     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@0
     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@0
    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@0
    20
*/
icculus@8093
    21
#include "../SDL_internal.h"
slouken@0
    22
slouken@0
    23
/* General (mostly internal) pixel/color manipulation routines for SDL */
slouken@0
    24
slouken@0
    25
#include "SDL_endian.h"
slouken@0
    26
#include "SDL_video.h"
slouken@0
    27
#include "SDL_sysvideo.h"
slouken@0
    28
#include "SDL_blit.h"
slouken@0
    29
#include "SDL_pixels_c.h"
slouken@0
    30
#include "SDL_RLEaccel_c.h"
slouken@0
    31
slouken@3555
    32
slouken@5439
    33
/* Lookup tables to expand partial bytes to the full 0..255 range */
slouken@5439
    34
slouken@5439
    35
static Uint8 lookup_0[] = {
slouken@5439
    36
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
slouken@5439
    37
};
slouken@5439
    38
slouken@5439
    39
static Uint8 lookup_1[] = {
slouken@5439
    40
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 255
slouken@5439
    41
};
slouken@5439
    42
slouken@5439
    43
static Uint8 lookup_2[] = {
slouken@5439
    44
0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 170, 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 214, 218, 222, 226, 230, 234, 238, 242, 246, 250, 255
slouken@5439
    45
};
slouken@5439
    46
slouken@5439
    47
static Uint8 lookup_3[] = {
slouken@5439
    48
0, 8, 16, 24, 32, 41, 49, 57, 65, 74, 82, 90, 98, 106, 115, 123, 131, 139, 148, 156, 164, 172, 180, 189, 197, 205, 213, 222, 230, 238, 246, 255
slouken@5439
    49
};
slouken@5439
    50
slouken@5439
    51
static Uint8 lookup_4[] = {
slouken@5439
    52
0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
slouken@5439
    53
};
slouken@5439
    54
slouken@5439
    55
static Uint8 lookup_5[] = {
slouken@5439
    56
0, 36, 72, 109, 145, 182, 218, 255
slouken@5439
    57
};
slouken@5439
    58
slouken@5439
    59
static Uint8 lookup_6[] = {
slouken@5439
    60
0, 85, 170, 255
slouken@5439
    61
};
slouken@5439
    62
slouken@5439
    63
static Uint8 lookup_7[] = {
slouken@5439
    64
0, 255
slouken@5439
    65
};
slouken@5439
    66
slouken@5439
    67
static Uint8 lookup_8[] = {
slouken@5439
    68
255
slouken@5439
    69
};
slouken@5439
    70
slouken@5439
    71
Uint8* SDL_expand_byte[9] = {
slouken@5439
    72
    lookup_0,
slouken@5439
    73
    lookup_1,
slouken@5439
    74
    lookup_2,
slouken@5439
    75
    lookup_3,
slouken@5439
    76
    lookup_4,
slouken@5439
    77
    lookup_5,
slouken@5439
    78
    lookup_6,
slouken@5439
    79
    lookup_7,
slouken@5439
    80
    lookup_8
slouken@5439
    81
};
slouken@5439
    82
slouken@0
    83
/* Helper functions */
slouken@1895
    84
slouken@4982
    85
const char*
slouken@4982
    86
SDL_GetPixelFormatName(Uint32 format)
slouken@4982
    87
{
slouken@4982
    88
    switch (format) {
slouken@4982
    89
#define CASE(X) case X: return #X;
slouken@4982
    90
    CASE(SDL_PIXELFORMAT_INDEX1LSB)
slouken@4982
    91
    CASE(SDL_PIXELFORMAT_INDEX1MSB)
slouken@4982
    92
    CASE(SDL_PIXELFORMAT_INDEX4LSB)
slouken@4982
    93
    CASE(SDL_PIXELFORMAT_INDEX4MSB)
slouken@4982
    94
    CASE(SDL_PIXELFORMAT_INDEX8)
slouken@4982
    95
    CASE(SDL_PIXELFORMAT_RGB332)
slouken@4982
    96
    CASE(SDL_PIXELFORMAT_RGB444)
slouken@4982
    97
    CASE(SDL_PIXELFORMAT_RGB555)
slouken@4982
    98
    CASE(SDL_PIXELFORMAT_BGR555)
slouken@4982
    99
    CASE(SDL_PIXELFORMAT_ARGB4444)
slouken@4982
   100
    CASE(SDL_PIXELFORMAT_RGBA4444)
slouken@4982
   101
    CASE(SDL_PIXELFORMAT_ABGR4444)
slouken@4982
   102
    CASE(SDL_PIXELFORMAT_BGRA4444)
slouken@4982
   103
    CASE(SDL_PIXELFORMAT_ARGB1555)
slouken@4982
   104
    CASE(SDL_PIXELFORMAT_RGBA5551)
slouken@4982
   105
    CASE(SDL_PIXELFORMAT_ABGR1555)
slouken@4982
   106
    CASE(SDL_PIXELFORMAT_BGRA5551)
slouken@4982
   107
    CASE(SDL_PIXELFORMAT_RGB565)
slouken@4982
   108
    CASE(SDL_PIXELFORMAT_BGR565)
slouken@4982
   109
    CASE(SDL_PIXELFORMAT_RGB24)
slouken@4982
   110
    CASE(SDL_PIXELFORMAT_BGR24)
slouken@4982
   111
    CASE(SDL_PIXELFORMAT_RGB888)
slouken@6074
   112
    CASE(SDL_PIXELFORMAT_RGBX8888)
slouken@4982
   113
    CASE(SDL_PIXELFORMAT_BGR888)
slouken@6074
   114
    CASE(SDL_PIXELFORMAT_BGRX8888)
slouken@4982
   115
    CASE(SDL_PIXELFORMAT_ARGB8888)
slouken@4982
   116
    CASE(SDL_PIXELFORMAT_RGBA8888)
slouken@4982
   117
    CASE(SDL_PIXELFORMAT_ABGR8888)
slouken@4982
   118
    CASE(SDL_PIXELFORMAT_BGRA8888)
slouken@4982
   119
    CASE(SDL_PIXELFORMAT_ARGB2101010)
slouken@4982
   120
    CASE(SDL_PIXELFORMAT_YV12)
slouken@4982
   121
    CASE(SDL_PIXELFORMAT_IYUV)
slouken@4982
   122
    CASE(SDL_PIXELFORMAT_YUY2)
slouken@4982
   123
    CASE(SDL_PIXELFORMAT_UYVY)
slouken@4982
   124
    CASE(SDL_PIXELFORMAT_YVYU)
slouken@9046
   125
    CASE(SDL_PIXELFORMAT_NV12)
slouken@9046
   126
    CASE(SDL_PIXELFORMAT_NV21)
slouken@4982
   127
#undef CASE
slouken@4982
   128
    default:
slouken@4982
   129
        return "SDL_PIXELFORMAT_UNKNOWN";
slouken@4982
   130
    }
slouken@4982
   131
}
slouken@4982
   132
slouken@1895
   133
SDL_bool
slouken@1895
   134
SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask,
slouken@1895
   135
                           Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
slouken@1895
   136
{
slouken@1895
   137
    Uint32 masks[4];
slouken@1895
   138
slouken@5432
   139
    /* This function doesn't work with FourCC pixel formats */
slouken@5432
   140
    if (SDL_ISPIXELFORMAT_FOURCC(format)) {
slouken@5433
   141
        SDL_SetError("FOURCC pixel formats are not supported");
slouken@5432
   142
        return SDL_FALSE;
slouken@5432
   143
    }
slouken@7191
   144
slouken@1895
   145
    /* Initialize the values here */
slouken@3284
   146
    if (SDL_BYTESPERPIXEL(format) <= 2) {
slouken@3284
   147
        *bpp = SDL_BITSPERPIXEL(format);
slouken@3284
   148
    } else {
slouken@1895
   149
        *bpp = SDL_BYTESPERPIXEL(format) * 8;
slouken@1895
   150
    }
slouken@1895
   151
    *Rmask = *Gmask = *Bmask = *Amask = 0;
slouken@1895
   152
slouken@3557
   153
    if (format == SDL_PIXELFORMAT_RGB24) {
slouken@3557
   154
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@3557
   155
        *Rmask = 0x00FF0000;
slouken@3557
   156
        *Gmask = 0x0000FF00;
slouken@3557
   157
        *Bmask = 0x000000FF;
slouken@3557
   158
#else
slouken@3557
   159
        *Rmask = 0x000000FF;
slouken@3557
   160
        *Gmask = 0x0000FF00;
slouken@3557
   161
        *Bmask = 0x00FF0000;
slouken@3557
   162
#endif
slouken@3557
   163
        return SDL_TRUE;
slouken@3557
   164
    }
slouken@3557
   165
slouken@3557
   166
    if (format == SDL_PIXELFORMAT_BGR24) {
slouken@3557
   167
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@3557
   168
        *Rmask = 0x000000FF;
slouken@3557
   169
        *Gmask = 0x0000FF00;
slouken@3557
   170
        *Bmask = 0x00FF0000;
slouken@3557
   171
#else
slouken@3557
   172
        *Rmask = 0x00FF0000;
slouken@3557
   173
        *Gmask = 0x0000FF00;
slouken@3557
   174
        *Bmask = 0x000000FF;
slouken@3557
   175
#endif
slouken@3557
   176
        return SDL_TRUE;
slouken@3557
   177
    }
slouken@3557
   178
slouken@1965
   179
    if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 &&
slouken@1965
   180
        SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 &&
slouken@1965
   181
        SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) {
slouken@1895
   182
        /* Not a format that uses masks */
slouken@1895
   183
        return SDL_TRUE;
slouken@1895
   184
    }
slouken@1895
   185
slouken@1895
   186
    switch (SDL_PIXELLAYOUT(format)) {
slouken@1965
   187
    case SDL_PACKEDLAYOUT_332:
slouken@1895
   188
        masks[0] = 0x00000000;
slouken@1895
   189
        masks[1] = 0x000000E0;
slouken@1895
   190
        masks[2] = 0x0000001C;
slouken@1895
   191
        masks[3] = 0x00000003;
slouken@1895
   192
        break;
slouken@1965
   193
    case SDL_PACKEDLAYOUT_4444:
slouken@1895
   194
        masks[0] = 0x0000F000;
slouken@1895
   195
        masks[1] = 0x00000F00;
slouken@1895
   196
        masks[2] = 0x000000F0;
slouken@1895
   197
        masks[3] = 0x0000000F;
slouken@1895
   198
        break;
slouken@1965
   199
    case SDL_PACKEDLAYOUT_1555:
slouken@1895
   200
        masks[0] = 0x00008000;
slouken@1895
   201
        masks[1] = 0x00007C00;
slouken@1895
   202
        masks[2] = 0x000003E0;
slouken@1895
   203
        masks[3] = 0x0000001F;
slouken@1895
   204
        break;
lestat@3163
   205
    case SDL_PACKEDLAYOUT_5551:
lestat@3163
   206
        masks[0] = 0x0000F800;
lestat@3163
   207
        masks[1] = 0x000007C0;
lestat@3163
   208
        masks[2] = 0x0000003E;
lestat@3163
   209
        masks[3] = 0x00000001;
lestat@3163
   210
        break;
slouken@1965
   211
    case SDL_PACKEDLAYOUT_565:
slouken@1895
   212
        masks[0] = 0x00000000;
slouken@1895
   213
        masks[1] = 0x0000F800;
slouken@1895
   214
        masks[2] = 0x000007E0;
slouken@1895
   215
        masks[3] = 0x0000001F;
slouken@1895
   216
        break;
slouken@1965
   217
    case SDL_PACKEDLAYOUT_8888:
slouken@1895
   218
        masks[0] = 0xFF000000;
slouken@1895
   219
        masks[1] = 0x00FF0000;
slouken@1895
   220
        masks[2] = 0x0000FF00;
slouken@1895
   221
        masks[3] = 0x000000FF;
slouken@1895
   222
        break;
slouken@1965
   223
    case SDL_PACKEDLAYOUT_2101010:
slouken@1895
   224
        masks[0] = 0xC0000000;
slouken@1895
   225
        masks[1] = 0x3FF00000;
slouken@1895
   226
        masks[2] = 0x000FFC00;
slouken@1895
   227
        masks[3] = 0x000003FF;
slouken@1895
   228
        break;
lestat@3163
   229
    case SDL_PACKEDLAYOUT_1010102:
lestat@3163
   230
        masks[0] = 0xFFC00000;
lestat@3163
   231
        masks[1] = 0x003FF000;
lestat@3163
   232
        masks[2] = 0x00000FFC;
lestat@3163
   233
        masks[3] = 0x00000003;
lestat@3163
   234
        break;
slouken@1895
   235
    default:
slouken@3484
   236
        SDL_SetError("Unknown pixel format");
slouken@1895
   237
        return SDL_FALSE;
slouken@1895
   238
    }
slouken@1895
   239
slouken@1895
   240
    switch (SDL_PIXELORDER(format)) {
slouken@1965
   241
    case SDL_PACKEDORDER_XRGB:
slouken@1895
   242
        *Rmask = masks[1];
slouken@1895
   243
        *Gmask = masks[2];
slouken@1895
   244
        *Bmask = masks[3];
slouken@1895
   245
        break;
slouken@1965
   246
    case SDL_PACKEDORDER_RGBX:
slouken@1895
   247
        *Rmask = masks[0];
slouken@1895
   248
        *Gmask = masks[1];
slouken@1895
   249
        *Bmask = masks[2];
slouken@1895
   250
        break;
slouken@1965
   251
    case SDL_PACKEDORDER_ARGB:
slouken@1895
   252
        *Amask = masks[0];
slouken@1895
   253
        *Rmask = masks[1];
slouken@1895
   254
        *Gmask = masks[2];
slouken@1895
   255
        *Bmask = masks[3];
slouken@1895
   256
        break;
slouken@1965
   257
    case SDL_PACKEDORDER_RGBA:
slouken@1895
   258
        *Rmask = masks[0];
slouken@1895
   259
        *Gmask = masks[1];
slouken@1895
   260
        *Bmask = masks[2];
slouken@1895
   261
        *Amask = masks[3];
slouken@1895
   262
        break;
slouken@1965
   263
    case SDL_PACKEDORDER_XBGR:
slouken@1895
   264
        *Bmask = masks[1];
slouken@1895
   265
        *Gmask = masks[2];
slouken@1895
   266
        *Rmask = masks[3];
slouken@1895
   267
        break;
slouken@1965
   268
    case SDL_PACKEDORDER_BGRX:
slouken@1895
   269
        *Bmask = masks[0];
slouken@1895
   270
        *Gmask = masks[1];
slouken@1895
   271
        *Rmask = masks[2];
slouken@1895
   272
        break;
slouken@1965
   273
    case SDL_PACKEDORDER_BGRA:
slouken@1895
   274
        *Bmask = masks[0];
slouken@1895
   275
        *Gmask = masks[1];
slouken@1895
   276
        *Rmask = masks[2];
slouken@1895
   277
        *Amask = masks[3];
slouken@1895
   278
        break;
slouken@1965
   279
    case SDL_PACKEDORDER_ABGR:
slouken@1895
   280
        *Amask = masks[0];
slouken@1895
   281
        *Bmask = masks[1];
slouken@1895
   282
        *Gmask = masks[2];
slouken@1895
   283
        *Rmask = masks[3];
slouken@1895
   284
        break;
slouken@1895
   285
    default:
slouken@3484
   286
        SDL_SetError("Unknown pixel format");
slouken@1895
   287
        return SDL_FALSE;
slouken@1895
   288
    }
slouken@1895
   289
    return SDL_TRUE;
slouken@1895
   290
}
slouken@1895
   291
slouken@1895
   292
Uint32
slouken@1895
   293
SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
slouken@1895
   294
                           Uint32 Amask)
slouken@1895
   295
{
slouken@1895
   296
    switch (bpp) {
slouken@5437
   297
    case 1:
slouken@5438
   298
        /* SDL defaults to MSB ordering */
slouken@5438
   299
        return SDL_PIXELFORMAT_INDEX1MSB;
slouken@5437
   300
    case 4:
slouken@5438
   301
        /* SDL defaults to MSB ordering */
slouken@5438
   302
        return SDL_PIXELFORMAT_INDEX4MSB;
slouken@1895
   303
    case 8:
slouken@5350
   304
        if (Rmask == 0) {
slouken@1965
   305
            return SDL_PIXELFORMAT_INDEX8;
slouken@5350
   306
        }
slouken@5350
   307
        if (Rmask == 0xE0 &&
slouken@5350
   308
            Gmask == 0x1C &&
slouken@5350
   309
            Bmask == 0x03 &&
slouken@5350
   310
            Amask == 0x00) {
slouken@5352
   311
            return SDL_PIXELFORMAT_RGB332;
slouken@1895
   312
        }
slouken@1895
   313
        break;
slouken@1895
   314
    case 12:
slouken@5350
   315
        if (Rmask == 0) {
slouken@5352
   316
            return SDL_PIXELFORMAT_RGB444;
slouken@5350
   317
        }
slouken@5350
   318
        if (Rmask == 0x0F00 &&
slouken@5350
   319
            Gmask == 0x00F0 &&
slouken@5350
   320
            Bmask == 0x000F &&
slouken@5350
   321
            Amask == 0x0000) {
slouken@5352
   322
            return SDL_PIXELFORMAT_RGB444;
slouken@1895
   323
        }
slouken@1895
   324
        break;
slouken@1895
   325
    case 15:
slouken@5288
   326
        if (Rmask == 0) {
slouken@5288
   327
            return SDL_PIXELFORMAT_RGB555;
slouken@5288
   328
        }
slouken@12201
   329
    /* fallthrough */
slouken@5350
   330
    case 16:
slouken@5350
   331
        if (Rmask == 0) {
slouken@5350
   332
            return SDL_PIXELFORMAT_RGB565;
slouken@5181
   333
        }
slouken@5350
   334
        if (Rmask == 0x7C00 &&
slouken@5350
   335
            Gmask == 0x03E0 &&
slouken@5350
   336
            Bmask == 0x001F &&
slouken@5350
   337
            Amask == 0x0000) {
slouken@5352
   338
            return SDL_PIXELFORMAT_RGB555;
slouken@1895
   339
        }
slouken@5350
   340
        if (Rmask == 0x001F &&
slouken@5350
   341
            Gmask == 0x03E0 &&
slouken@5350
   342
            Bmask == 0x7C00 &&
slouken@5350
   343
            Amask == 0x0000) {
slouken@5352
   344
            return SDL_PIXELFORMAT_BGR555;
slouken@5350
   345
        }
slouken@5350
   346
        if (Rmask == 0x0F00 &&
slouken@5350
   347
            Gmask == 0x00F0 &&
slouken@5350
   348
            Bmask == 0x000F &&
slouken@5350
   349
            Amask == 0xF000) {
slouken@5352
   350
            return SDL_PIXELFORMAT_ARGB4444;
slouken@5350
   351
        }
slouken@5350
   352
        if (Rmask == 0xF000 &&
slouken@5350
   353
            Gmask == 0x0F00 &&
slouken@5350
   354
            Bmask == 0x00F0 &&
slouken@5350
   355
            Amask == 0x000F) {
slouken@5352
   356
            return SDL_PIXELFORMAT_RGBA4444;
slouken@5350
   357
        }
slouken@5350
   358
        if (Rmask == 0x000F &&
slouken@5350
   359
            Gmask == 0x00F0 &&
slouken@5350
   360
            Bmask == 0x0F00 &&
slouken@5350
   361
            Amask == 0xF000) {
slouken@5352
   362
            return SDL_PIXELFORMAT_ABGR4444;
slouken@5350
   363
        }
slouken@5350
   364
        if (Rmask == 0x00F0 &&
slouken@5350
   365
            Gmask == 0x0F00 &&
slouken@5350
   366
            Bmask == 0xF000 &&
slouken@5350
   367
            Amask == 0x000F) {
slouken@5352
   368
            return SDL_PIXELFORMAT_BGRA4444;
slouken@5350
   369
        }
slouken@5350
   370
        if (Rmask == 0x7C00 &&
slouken@5350
   371
            Gmask == 0x03E0 &&
slouken@5350
   372
            Bmask == 0x001F &&
slouken@5350
   373
            Amask == 0x8000) {
slouken@5352
   374
            return SDL_PIXELFORMAT_ARGB1555;
slouken@5350
   375
        }
slouken@5350
   376
        if (Rmask == 0xF800 &&
slouken@5350
   377
            Gmask == 0x07C0 &&
slouken@5350
   378
            Bmask == 0x003E &&
slouken@5350
   379
            Amask == 0x0001) {
slouken@5352
   380
            return SDL_PIXELFORMAT_RGBA5551;
slouken@5350
   381
        }
slouken@5350
   382
        if (Rmask == 0x001F &&
slouken@5350
   383
            Gmask == 0x03E0 &&
slouken@5350
   384
            Bmask == 0x7C00 &&
slouken@5350
   385
            Amask == 0x8000) {
slouken@5352
   386
            return SDL_PIXELFORMAT_ABGR1555;
slouken@5350
   387
        }
slouken@5350
   388
        if (Rmask == 0x003E &&
slouken@5350
   389
            Gmask == 0x07C0 &&
slouken@5350
   390
            Bmask == 0xF800 &&
slouken@5350
   391
            Amask == 0x0001) {
slouken@5352
   392
            return SDL_PIXELFORMAT_BGRA5551;
slouken@5350
   393
        }
slouken@5350
   394
        if (Rmask == 0xF800 &&
slouken@5350
   395
            Gmask == 0x07E0 &&
slouken@5350
   396
            Bmask == 0x001F &&
slouken@5350
   397
            Amask == 0x0000) {
slouken@5352
   398
            return SDL_PIXELFORMAT_RGB565;
slouken@5350
   399
        }
slouken@5350
   400
        if (Rmask == 0x001F &&
slouken@5350
   401
            Gmask == 0x07E0 &&
slouken@5350
   402
            Bmask == 0xF800 &&
slouken@5350
   403
            Amask == 0x0000) {
slouken@5352
   404
            return SDL_PIXELFORMAT_BGR565;
slouken@1895
   405
        }
slouken@11250
   406
        if (Rmask == 0x003F &&
slouken@11250
   407
            Gmask == 0x07C0 &&
slouken@11250
   408
            Bmask == 0xF800 &&
slouken@11250
   409
            Amask == 0x0000) {
slouken@11250
   410
            /* Technically this would be BGR556, but Witek says this works in bug 3158 */
slouken@11250
   411
            return SDL_PIXELFORMAT_RGB565;
slouken@11250
   412
        }
slouken@1895
   413
        break;
lestat@3182
   414
    case 24:
lestat@3182
   415
        switch (Rmask) {
slouken@5288
   416
        case 0:
lestat@3182
   417
        case 0x00FF0000:
slouken@3597
   418
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@3597
   419
            return SDL_PIXELFORMAT_RGB24;
slouken@3597
   420
#else
slouken@3597
   421
            return SDL_PIXELFORMAT_BGR24;
slouken@3597
   422
#endif
lestat@3182
   423
        case 0x000000FF:
slouken@3597
   424
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@3597
   425
            return SDL_PIXELFORMAT_BGR24;
slouken@3597
   426
#else
slouken@3597
   427
            return SDL_PIXELFORMAT_RGB24;
slouken@3597
   428
#endif
lestat@3182
   429
        }
slouken@1895
   430
    case 32:
slouken@5350
   431
        if (Rmask == 0) {
slouken@5350
   432
            return SDL_PIXELFORMAT_RGB888;
slouken@5350
   433
        }
slouken@5350
   434
        if (Rmask == 0x00FF0000 &&
slouken@5350
   435
            Gmask == 0x0000FF00 &&
slouken@5350
   436
            Bmask == 0x000000FF &&
slouken@5350
   437
            Amask == 0x00000000) {
slouken@5352
   438
            return SDL_PIXELFORMAT_RGB888;
slouken@5350
   439
        }
slouken@6074
   440
        if (Rmask == 0xFF000000 &&
slouken@6074
   441
            Gmask == 0x00FF0000 &&
slouken@6074
   442
            Bmask == 0x0000FF00 &&
slouken@6074
   443
            Amask == 0x00000000) {
slouken@6074
   444
            return SDL_PIXELFORMAT_RGBX8888;
slouken@6074
   445
        }
slouken@5350
   446
        if (Rmask == 0x000000FF &&
slouken@5350
   447
            Gmask == 0x0000FF00 &&
slouken@5350
   448
            Bmask == 0x00FF0000 &&
slouken@5350
   449
            Amask == 0x00000000) {
slouken@5352
   450
            return SDL_PIXELFORMAT_BGR888;
slouken@5350
   451
        }
slouken@6074
   452
        if (Rmask == 0x0000FF00 &&
slouken@6074
   453
            Gmask == 0x00FF0000 &&
slouken@6074
   454
            Bmask == 0xFF000000 &&
slouken@6074
   455
            Amask == 0x00000000) {
slouken@6074
   456
            return SDL_PIXELFORMAT_BGRX8888;
slouken@6074
   457
        }
slouken@5350
   458
        if (Rmask == 0x00FF0000 &&
slouken@5350
   459
            Gmask == 0x0000FF00 &&
slouken@5350
   460
            Bmask == 0x000000FF &&
slouken@5350
   461
            Amask == 0xFF000000) {
slouken@5352
   462
            return SDL_PIXELFORMAT_ARGB8888;
slouken@5350
   463
        }
slouken@5350
   464
        if (Rmask == 0xFF000000 &&
slouken@5350
   465
            Gmask == 0x00FF0000 &&
slouken@5350
   466
            Bmask == 0x0000FF00 &&
slouken@5350
   467
            Amask == 0x000000FF) {
slouken@5352
   468
            return SDL_PIXELFORMAT_RGBA8888;
slouken@5350
   469
        }
slouken@5350
   470
        if (Rmask == 0x000000FF &&
slouken@5350
   471
            Gmask == 0x0000FF00 &&
slouken@5350
   472
            Bmask == 0x00FF0000 &&
slouken@5350
   473
            Amask == 0xFF000000) {
slouken@5352
   474
            return SDL_PIXELFORMAT_ABGR8888;
slouken@5350
   475
        }
slouken@5350
   476
        if (Rmask == 0x0000FF00 &&
slouken@5350
   477
            Gmask == 0x00FF0000 &&
slouken@5350
   478
            Bmask == 0xFF000000 &&
slouken@5350
   479
            Amask == 0x000000FF) {
slouken@5352
   480
            return SDL_PIXELFORMAT_BGRA8888;
slouken@5350
   481
        }
slouken@5350
   482
        if (Rmask == 0x3FF00000 &&
slouken@5350
   483
            Gmask == 0x000FFC00 &&
slouken@5350
   484
            Bmask == 0x000003FF &&
slouken@5350
   485
            Amask == 0xC0000000) {
slouken@5352
   486
            return SDL_PIXELFORMAT_ARGB2101010;
slouken@1895
   487
        }
slouken@1895
   488
    }
slouken@1965
   489
    return SDL_PIXELFORMAT_UNKNOWN;
slouken@1895
   490
}
slouken@1895
   491
slouken@5288
   492
static SDL_PixelFormat *formats;
icculus@11877
   493
static SDL_SpinLock formats_lock = 0;
slouken@1895
   494
slouken@5288
   495
SDL_PixelFormat *
slouken@5288
   496
SDL_AllocFormat(Uint32 pixel_format)
slouken@1895
   497
{
slouken@5288
   498
    SDL_PixelFormat *format;
slouken@1895
   499
icculus@11877
   500
    SDL_AtomicLock(&formats_lock);
icculus@11877
   501
slouken@5288
   502
    /* Look it up in our list of previously allocated formats */
slouken@5288
   503
    for (format = formats; format; format = format->next) {
slouken@5288
   504
        if (pixel_format == format->format) {
slouken@5288
   505
            ++format->refcount;
icculus@11877
   506
            SDL_AtomicUnlock(&formats_lock);
slouken@5288
   507
            return format;
slouken@1895
   508
        }
slouken@1895
   509
    }
slouken@1895
   510
slouken@5288
   511
    /* Allocate an empty pixel format structure, and initialize it */
slouken@2967
   512
    format = SDL_malloc(sizeof(*format));
slouken@1895
   513
    if (format == NULL) {
icculus@11877
   514
        SDL_AtomicUnlock(&formats_lock);
slouken@1895
   515
        SDL_OutOfMemory();
slouken@5433
   516
        return NULL;
slouken@1895
   517
    }
slouken@5433
   518
    if (SDL_InitFormat(format, pixel_format) < 0) {
icculus@11877
   519
        SDL_AtomicUnlock(&formats_lock);
slouken@5433
   520
        SDL_free(format);
aschiffler@7142
   521
        SDL_InvalidParamError("format");
slouken@5433
   522
        return NULL;
slouken@5433
   523
    }
slouken@0
   524
slouken@5288
   525
    if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
slouken@5288
   526
        /* Cache the RGB formats */
slouken@5288
   527
        format->next = formats;
slouken@5288
   528
        formats = format;
slouken@5288
   529
    }
icculus@11877
   530
icculus@11877
   531
    SDL_AtomicUnlock(&formats_lock);
icculus@11877
   532
slouken@5288
   533
    return format;
slouken@2967
   534
}
slouken@2967
   535
slouken@5288
   536
int
slouken@5288
   537
SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
slouken@2967
   538
{
slouken@5432
   539
    int bpp;
slouken@5432
   540
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@5432
   541
    Uint32 mask;
slouken@5432
   542
slouken@5432
   543
    if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
slouken@5432
   544
                                    &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@5432
   545
        return -1;
slouken@5432
   546
    }
slouken@5432
   547
slouken@2967
   548
    /* Set up the format */
slouken@2967
   549
    SDL_zerop(format);
slouken@5288
   550
    format->format = pixel_format;
slouken@5432
   551
    format->BitsPerPixel = bpp;
slouken@5432
   552
    format->BytesPerPixel = (bpp + 7) / 8;
slouken@5431
   553
slouken@5432
   554
    format->Rmask = Rmask;
slouken@5432
   555
    format->Rshift = 0;
slouken@5432
   556
    format->Rloss = 8;
slouken@5432
   557
    if (Rmask) {
slouken@5432
   558
        for (mask = Rmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   559
            ++format->Rshift;
slouken@5432
   560
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   561
            --format->Rloss;
slouken@5432
   562
    }
slouken@5431
   563
slouken@5432
   564
    format->Gmask = Gmask;
slouken@5432
   565
    format->Gshift = 0;
slouken@5432
   566
    format->Gloss = 8;
slouken@5432
   567
    if (Gmask) {
slouken@5432
   568
        for (mask = Gmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   569
            ++format->Gshift;
slouken@5432
   570
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   571
            --format->Gloss;
slouken@1895
   572
    }
slouken@5432
   573
slouken@5432
   574
    format->Bmask = Bmask;
slouken@5432
   575
    format->Bshift = 0;
slouken@5432
   576
    format->Bloss = 8;
slouken@5432
   577
    if (Bmask) {
slouken@5432
   578
        for (mask = Bmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   579
            ++format->Bshift;
slouken@5432
   580
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   581
            --format->Bloss;
slouken@5432
   582
    }
slouken@5432
   583
slouken@5432
   584
    format->Amask = Amask;
slouken@5432
   585
    format->Ashift = 0;
slouken@5432
   586
    format->Aloss = 8;
slouken@5432
   587
    if (Amask) {
slouken@5432
   588
        for (mask = Amask; !(mask & 0x01); mask >>= 1)
slouken@5432
   589
            ++format->Ashift;
slouken@5432
   590
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   591
            --format->Aloss;
slouken@5432
   592
    }
slouken@5432
   593
slouken@1895
   594
    format->palette = NULL;
slouken@5288
   595
    format->refcount = 1;
slouken@5288
   596
    format->next = NULL;
slouken@1057
   597
slouken@5288
   598
    return 0;
slouken@0
   599
}
slouken@0
   600
slouken@1895
   601
void
slouken@5288
   602
SDL_FreeFormat(SDL_PixelFormat *format)
slouken@0
   603
{
slouken@5288
   604
    SDL_PixelFormat *prev;
slouken@1895
   605
slouken@1895
   606
    if (!format) {
aschiffler@7142
   607
        SDL_InvalidParamError("format");
slouken@1895
   608
        return;
slouken@1895
   609
    }
icculus@11877
   610
icculus@11877
   611
    SDL_AtomicLock(&formats_lock);
icculus@11877
   612
slouken@5288
   613
    if (--format->refcount > 0) {
icculus@11877
   614
        SDL_AtomicUnlock(&formats_lock);
slouken@5288
   615
        return;
slouken@5288
   616
    }
slouken@5288
   617
slouken@5288
   618
    /* Remove this format from our list */
slouken@5288
   619
    if (format == formats) {
slouken@5288
   620
        formats = format->next;
slouken@5288
   621
    } else if (formats) {
slouken@5288
   622
        for (prev = formats; prev->next; prev = prev->next) {
slouken@5288
   623
            if (prev->next == format) {
slouken@5288
   624
                prev->next = format->next;
slouken@5288
   625
                break;
slouken@5288
   626
            }
slouken@5288
   627
        }
slouken@5288
   628
    }
slouken@5288
   629
icculus@11877
   630
    SDL_AtomicUnlock(&formats_lock);
icculus@11877
   631
slouken@5288
   632
    if (format->palette) {
slouken@5288
   633
        SDL_FreePalette(format->palette);
slouken@5288
   634
    }
slouken@1895
   635
    SDL_free(format);
slouken@0
   636
}
slouken@1895
   637
slouken@5288
   638
SDL_Palette *
slouken@5288
   639
SDL_AllocPalette(int ncolors)
slouken@5288
   640
{
slouken@5288
   641
    SDL_Palette *palette;
slouken@7191
   642
aschiffler@7142
   643
    /* Input validation */
aschiffler@7142
   644
    if (ncolors < 1) {
aschiffler@7142
   645
      SDL_InvalidParamError("ncolors");
aschiffler@7142
   646
      return NULL;
aschiffler@7142
   647
    }
slouken@5288
   648
slouken@5288
   649
    palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
slouken@5288
   650
    if (!palette) {
slouken@5288
   651
        SDL_OutOfMemory();
slouken@5288
   652
        return NULL;
slouken@5288
   653
    }
slouken@5288
   654
    palette->colors =
slouken@5288
   655
        (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
slouken@5288
   656
    if (!palette->colors) {
slouken@5288
   657
        SDL_free(palette);
slouken@5288
   658
        return NULL;
slouken@5288
   659
    }
slouken@5288
   660
    palette->ncolors = ncolors;
slouken@5288
   661
    palette->version = 1;
slouken@5288
   662
    palette->refcount = 1;
slouken@5288
   663
slouken@5288
   664
    SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
slouken@5288
   665
slouken@5288
   666
    return palette;
slouken@5288
   667
}
slouken@5288
   668
slouken@5288
   669
int
slouken@5288
   670
SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
slouken@5288
   671
{
slouken@5288
   672
    if (!format) {
icculus@7037
   673
        return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
slouken@5288
   674
    }
slouken@5288
   675
icculus@11496
   676
    if (palette && palette->ncolors > (1 << format->BitsPerPixel)) {
icculus@7037
   677
        return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
slouken@5288
   678
    }
slouken@5288
   679
slouken@5288
   680
    if (format->palette == palette) {
slouken@5288
   681
        return 0;
slouken@5288
   682
    }
slouken@5288
   683
slouken@5288
   684
    if (format->palette) {
slouken@5288
   685
        SDL_FreePalette(format->palette);
slouken@5288
   686
    }
slouken@5288
   687
slouken@5288
   688
    format->palette = palette;
slouken@5288
   689
slouken@5288
   690
    if (format->palette) {
slouken@5288
   691
        ++format->palette->refcount;
slouken@5288
   692
    }
slouken@5295
   693
slouken@5295
   694
    return 0;
slouken@5288
   695
}
slouken@5288
   696
slouken@5288
   697
int
slouken@5288
   698
SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
slouken@5288
   699
                     int firstcolor, int ncolors)
slouken@5288
   700
{
slouken@5288
   701
    int status = 0;
slouken@5288
   702
slouken@5288
   703
    /* Verify the parameters */
slouken@5288
   704
    if (!palette) {
slouken@5288
   705
        return -1;
slouken@5288
   706
    }
slouken@5288
   707
    if (ncolors > (palette->ncolors - firstcolor)) {
slouken@5288
   708
        ncolors = (palette->ncolors - firstcolor);
slouken@5288
   709
        status = -1;
slouken@5288
   710
    }
slouken@5288
   711
slouken@5288
   712
    if (colors != (palette->colors + firstcolor)) {
slouken@5288
   713
        SDL_memcpy(palette->colors + firstcolor, colors,
slouken@5288
   714
                   ncolors * sizeof(*colors));
slouken@5288
   715
    }
slouken@5288
   716
    ++palette->version;
slouken@5288
   717
    if (!palette->version) {
slouken@5288
   718
        palette->version = 1;
slouken@5288
   719
    }
slouken@5288
   720
slouken@5288
   721
    return status;
slouken@5288
   722
}
slouken@5288
   723
slouken@5288
   724
void
slouken@5288
   725
SDL_FreePalette(SDL_Palette * palette)
slouken@5288
   726
{
slouken@5288
   727
    if (!palette) {
aschiffler@7142
   728
        SDL_InvalidParamError("palette");
slouken@5288
   729
        return;
slouken@5288
   730
    }
slouken@5288
   731
    if (--palette->refcount > 0) {
slouken@5288
   732
        return;
slouken@5288
   733
    }
slouken@7719
   734
    SDL_free(palette->colors);
slouken@5288
   735
    SDL_free(palette);
slouken@5288
   736
}
slouken@5288
   737
slouken@0
   738
/*
slouken@0
   739
 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
slouken@0
   740
 */
slouken@1895
   741
void
slouken@1895
   742
SDL_DitherColors(SDL_Color * colors, int bpp)
slouken@0
   743
{
slouken@1895
   744
    int i;
slouken@1895
   745
    if (bpp != 8)
slouken@1895
   746
        return;                 /* only 8bpp supported right now */
slouken@0
   747
slouken@1895
   748
    for (i = 0; i < 256; i++) {
slouken@1895
   749
        int r, g, b;
slouken@1895
   750
        /* map each bit field to the full [0, 255] interval,
slouken@1895
   751
           so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
slouken@1895
   752
        r = i & 0xe0;
slouken@1895
   753
        r |= r >> 3 | r >> 6;
slouken@1895
   754
        colors[i].r = r;
slouken@1895
   755
        g = (i << 3) & 0xe0;
slouken@1895
   756
        g |= g >> 3 | g >> 6;
slouken@1895
   757
        colors[i].g = g;
slouken@1895
   758
        b = i & 0x3;
slouken@1895
   759
        b |= b << 2;
slouken@1895
   760
        b |= b << 4;
slouken@1895
   761
        colors[i].b = b;
slouken@7024
   762
        colors[i].a = SDL_ALPHA_OPAQUE;
slouken@1895
   763
    }
slouken@0
   764
}
slouken@1895
   765
slouken@7191
   766
/*
slouken@0
   767
 * Match an RGB value to a particular palette index
slouken@0
   768
 */
slouken@1895
   769
Uint8
slouken@7023
   770
SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@0
   771
{
slouken@1895
   772
    /* Do colorspace distance matching */
slouken@1895
   773
    unsigned int smallest;
slouken@1895
   774
    unsigned int distance;
slouken@7023
   775
    int rd, gd, bd, ad;
slouken@1895
   776
    int i;
slouken@1895
   777
    Uint8 pixel = 0;
slouken@1895
   778
slouken@1895
   779
    smallest = ~0;
slouken@1895
   780
    for (i = 0; i < pal->ncolors; ++i) {
slouken@1895
   781
        rd = pal->colors[i].r - r;
slouken@1895
   782
        gd = pal->colors[i].g - g;
slouken@1895
   783
        bd = pal->colors[i].b - b;
slouken@7024
   784
        ad = pal->colors[i].a - a;
slouken@7023
   785
        distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
slouken@1895
   786
        if (distance < smallest) {
slouken@1895
   787
            pixel = i;
slouken@1895
   788
            if (distance == 0) {        /* Perfect match! */
slouken@1895
   789
                break;
slouken@1895
   790
            }
slouken@1895
   791
            smallest = distance;
slouken@1895
   792
        }
slouken@1895
   793
    }
slouken@1895
   794
    return (pixel);
slouken@0
   795
}
slouken@0
   796
slouken@0
   797
/* Find the opaque pixel value corresponding to an RGB triple */
slouken@1895
   798
Uint32
slouken@2275
   799
SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
slouken@0
   800
{
slouken@1895
   801
    if (format->palette == NULL) {
slouken@1895
   802
        return (r >> format->Rloss) << format->Rshift
slouken@1895
   803
            | (g >> format->Gloss) << format->Gshift
slouken@1895
   804
            | (b >> format->Bloss) << format->Bshift | format->Amask;
slouken@1895
   805
    } else {
slouken@7023
   806
        return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
slouken@1895
   807
    }
slouken@0
   808
}
slouken@0
   809
slouken@0
   810
/* Find the pixel value corresponding to an RGBA quadruple */
slouken@1895
   811
Uint32
slouken@2275
   812
SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
slouken@2275
   813
            Uint8 a)
slouken@0
   814
{
slouken@1895
   815
    if (format->palette == NULL) {
slouken@1895
   816
        return (r >> format->Rloss) << format->Rshift
slouken@1895
   817
            | (g >> format->Gloss) << format->Gshift
slouken@1895
   818
            | (b >> format->Bloss) << format->Bshift
slouken@1895
   819
            | ((a >> format->Aloss) << format->Ashift & format->Amask);
slouken@1895
   820
    } else {
slouken@7023
   821
        return SDL_FindColor(format->palette, r, g, b, a);
slouken@1895
   822
    }
slouken@0
   823
}
slouken@0
   824
slouken@1895
   825
void
slouken@2275
   826
SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
slouken@2275
   827
           Uint8 * b)
slouken@2275
   828
{
slouken@2275
   829
    if (format->palette == NULL) {
slouken@2275
   830
        unsigned v;
slouken@2275
   831
        v = (pixel & format->Rmask) >> format->Rshift;
slouken@5439
   832
        *r = SDL_expand_byte[format->Rloss][v];
slouken@2275
   833
        v = (pixel & format->Gmask) >> format->Gshift;
slouken@5439
   834
        *g = SDL_expand_byte[format->Gloss][v];
slouken@2275
   835
        v = (pixel & format->Bmask) >> format->Bshift;
slouken@5439
   836
        *b = SDL_expand_byte[format->Bloss][v];
slouken@2275
   837
    } else {
slouken@5447
   838
        if (pixel < (unsigned)format->palette->ncolors) {
slouken@5436
   839
            *r = format->palette->colors[pixel].r;
slouken@5436
   840
            *g = format->palette->colors[pixel].g;
slouken@5436
   841
            *b = format->palette->colors[pixel].b;
slouken@5436
   842
        } else {
slouken@5436
   843
            *r = *g = *b = 0;
slouken@5436
   844
        }
slouken@2275
   845
    }
slouken@2275
   846
}
slouken@2275
   847
slouken@2275
   848
void
slouken@2275
   849
SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
slouken@1895
   850
            Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
slouken@0
   851
{
slouken@2275
   852
    if (format->palette == NULL) {
slouken@1895
   853
        unsigned v;
slouken@2275
   854
        v = (pixel & format->Rmask) >> format->Rshift;
slouken@5439
   855
        *r = SDL_expand_byte[format->Rloss][v];
slouken@2275
   856
        v = (pixel & format->Gmask) >> format->Gshift;
slouken@5439
   857
        *g = SDL_expand_byte[format->Gloss][v];
slouken@2275
   858
        v = (pixel & format->Bmask) >> format->Bshift;
slouken@5439
   859
        *b = SDL_expand_byte[format->Bloss][v];
slouken@5439
   860
        v = (pixel & format->Amask) >> format->Ashift;
slouken@5439
   861
        *a = SDL_expand_byte[format->Aloss][v];
slouken@1895
   862
    } else {
slouken@5447
   863
        if (pixel < (unsigned)format->palette->ncolors) {
slouken@5436
   864
            *r = format->palette->colors[pixel].r;
slouken@5436
   865
            *g = format->palette->colors[pixel].g;
slouken@5436
   866
            *b = format->palette->colors[pixel].b;
slouken@7024
   867
            *a = format->palette->colors[pixel].a;
slouken@5436
   868
        } else {
slouken@5436
   869
            *r = *g = *b = *a = 0;
slouken@5436
   870
        }
slouken@1895
   871
    }
slouken@0
   872
}
slouken@0
   873
slouken@0
   874
/* Map from Palette to Palette */
slouken@1895
   875
static Uint8 *
slouken@1895
   876
Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
slouken@0
   877
{
slouken@1895
   878
    Uint8 *map;
slouken@1895
   879
    int i;
slouken@0
   880
slouken@1895
   881
    if (identical) {
slouken@1895
   882
        if (src->ncolors <= dst->ncolors) {
slouken@1895
   883
            /* If an identical palette, no need to map */
slouken@1895
   884
            if (src == dst
slouken@1895
   885
                ||
slouken@1895
   886
                (SDL_memcmp
slouken@1895
   887
                 (src->colors, dst->colors,
slouken@1895
   888
                  src->ncolors * sizeof(SDL_Color)) == 0)) {
slouken@1895
   889
                *identical = 1;
slouken@1895
   890
                return (NULL);
slouken@1895
   891
            }
slouken@1895
   892
        }
slouken@1895
   893
        *identical = 0;
slouken@1895
   894
    }
slouken@1895
   895
    map = (Uint8 *) SDL_malloc(src->ncolors);
slouken@1895
   896
    if (map == NULL) {
slouken@1895
   897
        SDL_OutOfMemory();
slouken@1895
   898
        return (NULL);
slouken@1895
   899
    }
slouken@1895
   900
    for (i = 0; i < src->ncolors; ++i) {
slouken@1895
   901
        map[i] = SDL_FindColor(dst,
slouken@1895
   902
                               src->colors[i].r, src->colors[i].g,
slouken@7024
   903
                               src->colors[i].b, src->colors[i].a);
slouken@1895
   904
    }
slouken@1895
   905
    return (map);
slouken@0
   906
}
slouken@0
   907
slouken@1895
   908
/* Map from Palette to BitField */
slouken@1895
   909
static Uint8 *
slouken@2267
   910
Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
slouken@2267
   911
        SDL_PixelFormat * dst)
slouken@0
   912
{
slouken@1895
   913
    Uint8 *map;
slouken@1895
   914
    int i;
slouken@1895
   915
    int bpp;
slouken@1895
   916
    SDL_Palette *pal = src->palette;
slouken@0
   917
slouken@1895
   918
    bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
slouken@1895
   919
    map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
slouken@1895
   920
    if (map == NULL) {
slouken@1895
   921
        SDL_OutOfMemory();
slouken@1895
   922
        return (NULL);
slouken@1895
   923
    }
slouken@0
   924
slouken@1895
   925
    /* We memory copy to the pixel map so the endianness is preserved */
slouken@1895
   926
    for (i = 0; i < pal->ncolors; ++i) {
slouken@2267
   927
        Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
slouken@2267
   928
        Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
slouken@2267
   929
        Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
slouken@7024
   930
        Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
slouken@2257
   931
        ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
slouken@1895
   932
    }
slouken@1895
   933
    return (map);
slouken@1895
   934
}
slouken@0
   935
slouken@1895
   936
/* Map from BitField to Dithered-Palette to Palette */
slouken@1895
   937
static Uint8 *
slouken@1895
   938
MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
slouken@1895
   939
{
slouken@1895
   940
    /* Generate a 256 color dither palette */
slouken@1895
   941
    SDL_Palette dithered;
slouken@1895
   942
    SDL_Color colors[256];
slouken@1895
   943
    SDL_Palette *pal = dst->palette;
slouken@1895
   944
slouken@1895
   945
    dithered.ncolors = 256;
slouken@1895
   946
    SDL_DitherColors(colors, 8);
slouken@1895
   947
    dithered.colors = colors;
slouken@1895
   948
    return (Map1to1(&dithered, pal, identical));
slouken@0
   949
}
slouken@1895
   950
slouken@1895
   951
SDL_BlitMap *
slouken@1895
   952
SDL_AllocBlitMap(void)
slouken@0
   953
{
slouken@1895
   954
    SDL_BlitMap *map;
slouken@1895
   955
slouken@1895
   956
    /* Allocate the empty map */
slouken@1920
   957
    map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
slouken@1895
   958
    if (map == NULL) {
slouken@1895
   959
        SDL_OutOfMemory();
slouken@1895
   960
        return (NULL);
slouken@1895
   961
    }
slouken@2267
   962
    map->info.r = 0xFF;
slouken@2267
   963
    map->info.g = 0xFF;
slouken@2267
   964
    map->info.b = 0xFF;
slouken@2267
   965
    map->info.a = 0xFF;
slouken@1895
   966
slouken@1895
   967
    /* It's ready to go */
slouken@1895
   968
    return (map);
slouken@0
   969
}
slouken@1895
   970
slouken@1895
   971
void
slouken@1895
   972
SDL_InvalidateMap(SDL_BlitMap * map)
slouken@0
   973
{
slouken@1895
   974
    if (!map) {
slouken@1895
   975
        return;
slouken@1895
   976
    }
slouken@6222
   977
    if (map->dst) {
slouken@6222
   978
        /* Release our reference to the surface - see the note below */
slouken@6222
   979
        if (--map->dst->refcount <= 0) {
slouken@6222
   980
            SDL_FreeSurface(map->dst);
slouken@6222
   981
        }
slouken@6222
   982
    }
slouken@1895
   983
    map->dst = NULL;
slouken@6166
   984
    map->src_palette_version = 0;
slouken@6166
   985
    map->dst_palette_version = 0;
slouken@7719
   986
    SDL_free(map->info.table);
slouken@7719
   987
    map->info.table = NULL;
slouken@1895
   988
}
slouken@2735
   989
slouken@1895
   990
int
slouken@1895
   991
SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
slouken@1895
   992
{
slouken@1895
   993
    SDL_PixelFormat *srcfmt;
slouken@1895
   994
    SDL_PixelFormat *dstfmt;
slouken@1895
   995
    SDL_BlitMap *map;
slouken@0
   996
slouken@1895
   997
    /* Clear out any previous mapping */
slouken@1895
   998
    map = src->map;
slouken@1895
   999
    if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
slouken@1895
  1000
        SDL_UnRLESurface(src, 1);
slouken@1895
  1001
    }
slouken@1895
  1002
    SDL_InvalidateMap(map);
slouken@0
  1003
slouken@1895
  1004
    /* Figure out what kind of mapping we're doing */
slouken@1895
  1005
    map->identity = 0;
slouken@1895
  1006
    srcfmt = src->format;
slouken@1895
  1007
    dstfmt = dst->format;
slouken@5288
  1008
    if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
slouken@5288
  1009
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
  1010
            /* Palette --> Palette */
slouken@2267
  1011
            map->info.table =
slouken@1895
  1012
                Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
slouken@1895
  1013
            if (!map->identity) {
slouken@2267
  1014
                if (map->info.table == NULL) {
slouken@1895
  1015
                    return (-1);
slouken@1895
  1016
                }
slouken@1895
  1017
            }
slouken@1895
  1018
            if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
slouken@1895
  1019
                map->identity = 0;
slouken@5288
  1020
        } else {
slouken@1895
  1021
            /* Palette --> BitField */
slouken@2267
  1022
            map->info.table =
slouken@2267
  1023
                Map1toN(srcfmt, src->map->info.r, src->map->info.g,
slouken@2267
  1024
                        src->map->info.b, src->map->info.a, dstfmt);
slouken@2267
  1025
            if (map->info.table == NULL) {
slouken@1895
  1026
                return (-1);
slouken@1895
  1027
            }
slouken@1895
  1028
        }
slouken@5288
  1029
    } else {
slouken@5288
  1030
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
  1031
            /* BitField --> Palette */
slouken@2267
  1032
            map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
slouken@1895
  1033
            if (!map->identity) {
slouken@2267
  1034
                if (map->info.table == NULL) {
slouken@1895
  1035
                    return (-1);
slouken@1895
  1036
                }
slouken@1895
  1037
            }
slouken@1895
  1038
            map->identity = 0;  /* Don't optimize to copy */
slouken@5288
  1039
        } else {
slouken@1895
  1040
            /* BitField --> BitField */
slouken@5288
  1041
            if (srcfmt == dstfmt) {
slouken@1895
  1042
                map->identity = 1;
slouken@5288
  1043
            }
slouken@1895
  1044
        }
slouken@1895
  1045
    }
slouken@0
  1046
slouken@1895
  1047
    map->dst = dst;
slouken@5288
  1048
slouken@6222
  1049
    if (map->dst) {
slouken@6222
  1050
        /* Keep a reference to this surface so it doesn't get deleted
slouken@6222
  1051
           while we're still pointing at it.
slouken@6222
  1052
slouken@6222
  1053
           A better method would be for the destination surface to keep
slouken@7191
  1054
           track of surfaces that are mapped to it and automatically
slouken@6222
  1055
           invalidate them when it is freed, but this will do for now.
slouken@6222
  1056
        */
slouken@6222
  1057
        ++map->dst->refcount;
slouken@6222
  1058
    }
slouken@6222
  1059
slouken@5288
  1060
    if (dstfmt->palette) {
slouken@6166
  1061
        map->dst_palette_version = dstfmt->palette->version;
slouken@5288
  1062
    } else {
slouken@6166
  1063
        map->dst_palette_version = 0;
slouken@6166
  1064
    }
slouken@6166
  1065
slouken@6166
  1066
    if (srcfmt->palette) {
slouken@6166
  1067
        map->src_palette_version = srcfmt->palette->version;
slouken@6166
  1068
    } else {
slouken@6166
  1069
        map->src_palette_version = 0;
slouken@5288
  1070
    }
slouken@0
  1071
slouken@1895
  1072
    /* Choose your blitters wisely */
slouken@1895
  1073
    return (SDL_CalculateBlit(src));
slouken@0
  1074
}
slouken@1895
  1075
slouken@1895
  1076
void
slouken@1895
  1077
SDL_FreeBlitMap(SDL_BlitMap * map)
slouken@0
  1078
{
slouken@1895
  1079
    if (map) {
slouken@1895
  1080
        SDL_InvalidateMap(map);
slouken@1895
  1081
        SDL_free(map);
slouken@1895
  1082
    }
slouken@0
  1083
}
slouken@1895
  1084
slouken@5466
  1085
void
slouken@5466
  1086
SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
slouken@5466
  1087
{
slouken@5466
  1088
    int i;
slouken@7191
  1089
aschiffler@7151
  1090
    /* Input validation */
aschiffler@7151
  1091
    if (gamma < 0.0f ) {
aschiffler@7151
  1092
      SDL_InvalidParamError("gamma");
aschiffler@7151
  1093
      return;
aschiffler@7151
  1094
    }
aschiffler@7151
  1095
    if (ramp == NULL) {
aschiffler@7151
  1096
      SDL_InvalidParamError("ramp");
aschiffler@7151
  1097
      return;
aschiffler@7151
  1098
    }
slouken@5466
  1099
slouken@5466
  1100
    /* 0.0 gamma is all black */
aschiffler@7151
  1101
    if (gamma == 0.0f) {
icculus@9715
  1102
        SDL_memset(ramp, 0, 256 * sizeof(Uint16));
slouken@5466
  1103
        return;
slouken@5466
  1104
    } else if (gamma == 1.0f) {
slouken@5466
  1105
        /* 1.0 gamma is identity */
slouken@5466
  1106
        for (i = 0; i < 256; ++i) {
slouken@5466
  1107
            ramp[i] = (i << 8) | i;
slouken@5466
  1108
        }
slouken@5466
  1109
        return;
slouken@5466
  1110
    } else {
slouken@5466
  1111
        /* Calculate a real gamma ramp */
slouken@5466
  1112
        int value;
slouken@5466
  1113
        gamma = 1.0f / gamma;
slouken@5466
  1114
        for (i = 0; i < 256; ++i) {
slouken@5466
  1115
            value =
slouken@5466
  1116
                (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
slouken@5466
  1117
            if (value > 65535) {
slouken@5466
  1118
                value = 65535;
slouken@5466
  1119
            }
slouken@5466
  1120
            ramp[i] = (Uint16) value;
slouken@5466
  1121
        }
slouken@5466
  1122
    }
slouken@5466
  1123
}
slouken@5466
  1124
slouken@1895
  1125
/* vi: set ts=4 sw=4 expandtab: */