src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 30 Jan 2018 18:08:34 -0800
changeset 11839 971881e55d61
parent 11811 5d94cb6b24d3
child 11877 2a25e8690229
permissions -rw-r--r--
Fixed ISO C99 compatibility
SDL now builds with gcc 7.2 with the following command line options:
-Wall -pedantic-errors -Wno-deprecated-declarations -Wno-overlength-strings --std=c99
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@11491
   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;
slouken@1895
   493
slouken@5288
   494
SDL_PixelFormat *
slouken@5288
   495
SDL_AllocFormat(Uint32 pixel_format)
slouken@1895
   496
{
slouken@5288
   497
    SDL_PixelFormat *format;
slouken@1895
   498
slouken@5288
   499
    /* Look it up in our list of previously allocated formats */
slouken@5288
   500
    for (format = formats; format; format = format->next) {
slouken@5288
   501
        if (pixel_format == format->format) {
slouken@5288
   502
            ++format->refcount;
slouken@5288
   503
            return format;
slouken@1895
   504
        }
slouken@1895
   505
    }
slouken@1895
   506
slouken@5288
   507
    /* Allocate an empty pixel format structure, and initialize it */
slouken@2967
   508
    format = SDL_malloc(sizeof(*format));
slouken@1895
   509
    if (format == NULL) {
slouken@1895
   510
        SDL_OutOfMemory();
slouken@5433
   511
        return NULL;
slouken@1895
   512
    }
slouken@5433
   513
    if (SDL_InitFormat(format, pixel_format) < 0) {
slouken@5433
   514
        SDL_free(format);
aschiffler@7142
   515
        SDL_InvalidParamError("format");
slouken@5433
   516
        return NULL;
slouken@5433
   517
    }
slouken@0
   518
slouken@5288
   519
    if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
slouken@5288
   520
        /* Cache the RGB formats */
slouken@5288
   521
        format->next = formats;
slouken@5288
   522
        formats = format;
slouken@5288
   523
    }
slouken@5288
   524
    return format;
slouken@2967
   525
}
slouken@2967
   526
slouken@5288
   527
int
slouken@5288
   528
SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
slouken@2967
   529
{
slouken@5432
   530
    int bpp;
slouken@5432
   531
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@5432
   532
    Uint32 mask;
slouken@5432
   533
slouken@5432
   534
    if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
slouken@5432
   535
                                    &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@5432
   536
        return -1;
slouken@5432
   537
    }
slouken@5432
   538
slouken@2967
   539
    /* Set up the format */
slouken@2967
   540
    SDL_zerop(format);
slouken@5288
   541
    format->format = pixel_format;
slouken@5432
   542
    format->BitsPerPixel = bpp;
slouken@5432
   543
    format->BytesPerPixel = (bpp + 7) / 8;
slouken@5431
   544
slouken@5432
   545
    format->Rmask = Rmask;
slouken@5432
   546
    format->Rshift = 0;
slouken@5432
   547
    format->Rloss = 8;
slouken@5432
   548
    if (Rmask) {
slouken@5432
   549
        for (mask = Rmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   550
            ++format->Rshift;
slouken@5432
   551
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   552
            --format->Rloss;
slouken@5432
   553
    }
slouken@5431
   554
slouken@5432
   555
    format->Gmask = Gmask;
slouken@5432
   556
    format->Gshift = 0;
slouken@5432
   557
    format->Gloss = 8;
slouken@5432
   558
    if (Gmask) {
slouken@5432
   559
        for (mask = Gmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   560
            ++format->Gshift;
slouken@5432
   561
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   562
            --format->Gloss;
slouken@1895
   563
    }
slouken@5432
   564
slouken@5432
   565
    format->Bmask = Bmask;
slouken@5432
   566
    format->Bshift = 0;
slouken@5432
   567
    format->Bloss = 8;
slouken@5432
   568
    if (Bmask) {
slouken@5432
   569
        for (mask = Bmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   570
            ++format->Bshift;
slouken@5432
   571
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   572
            --format->Bloss;
slouken@5432
   573
    }
slouken@5432
   574
slouken@5432
   575
    format->Amask = Amask;
slouken@5432
   576
    format->Ashift = 0;
slouken@5432
   577
    format->Aloss = 8;
slouken@5432
   578
    if (Amask) {
slouken@5432
   579
        for (mask = Amask; !(mask & 0x01); mask >>= 1)
slouken@5432
   580
            ++format->Ashift;
slouken@5432
   581
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   582
            --format->Aloss;
slouken@5432
   583
    }
slouken@5432
   584
slouken@1895
   585
    format->palette = NULL;
slouken@5288
   586
    format->refcount = 1;
slouken@5288
   587
    format->next = NULL;
slouken@1057
   588
slouken@5288
   589
    return 0;
slouken@0
   590
}
slouken@0
   591
slouken@1895
   592
void
slouken@5288
   593
SDL_FreeFormat(SDL_PixelFormat *format)
slouken@0
   594
{
slouken@5288
   595
    SDL_PixelFormat *prev;
slouken@1895
   596
slouken@1895
   597
    if (!format) {
aschiffler@7142
   598
        SDL_InvalidParamError("format");
slouken@1895
   599
        return;
slouken@1895
   600
    }
slouken@5288
   601
    if (--format->refcount > 0) {
slouken@5288
   602
        return;
slouken@5288
   603
    }
slouken@5288
   604
slouken@5288
   605
    /* Remove this format from our list */
slouken@5288
   606
    if (format == formats) {
slouken@5288
   607
        formats = format->next;
slouken@5288
   608
    } else if (formats) {
slouken@5288
   609
        for (prev = formats; prev->next; prev = prev->next) {
slouken@5288
   610
            if (prev->next == format) {
slouken@5288
   611
                prev->next = format->next;
slouken@5288
   612
                break;
slouken@5288
   613
            }
slouken@5288
   614
        }
slouken@5288
   615
    }
slouken@5288
   616
slouken@5288
   617
    if (format->palette) {
slouken@5288
   618
        SDL_FreePalette(format->palette);
slouken@5288
   619
    }
slouken@1895
   620
    SDL_free(format);
slouken@0
   621
}
slouken@1895
   622
slouken@5288
   623
SDL_Palette *
slouken@5288
   624
SDL_AllocPalette(int ncolors)
slouken@5288
   625
{
slouken@5288
   626
    SDL_Palette *palette;
slouken@7191
   627
aschiffler@7142
   628
    /* Input validation */
aschiffler@7142
   629
    if (ncolors < 1) {
aschiffler@7142
   630
      SDL_InvalidParamError("ncolors");
aschiffler@7142
   631
      return NULL;
aschiffler@7142
   632
    }
slouken@5288
   633
slouken@5288
   634
    palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
slouken@5288
   635
    if (!palette) {
slouken@5288
   636
        SDL_OutOfMemory();
slouken@5288
   637
        return NULL;
slouken@5288
   638
    }
slouken@5288
   639
    palette->colors =
slouken@5288
   640
        (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
slouken@5288
   641
    if (!palette->colors) {
slouken@5288
   642
        SDL_free(palette);
slouken@5288
   643
        return NULL;
slouken@5288
   644
    }
slouken@5288
   645
    palette->ncolors = ncolors;
slouken@5288
   646
    palette->version = 1;
slouken@5288
   647
    palette->refcount = 1;
slouken@5288
   648
slouken@5288
   649
    SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
slouken@5288
   650
slouken@5288
   651
    return palette;
slouken@5288
   652
}
slouken@5288
   653
slouken@5288
   654
int
slouken@5288
   655
SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
slouken@5288
   656
{
slouken@5288
   657
    if (!format) {
icculus@7037
   658
        return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
slouken@5288
   659
    }
slouken@5288
   660
icculus@11496
   661
    if (palette && palette->ncolors > (1 << format->BitsPerPixel)) {
icculus@7037
   662
        return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
slouken@5288
   663
    }
slouken@5288
   664
slouken@5288
   665
    if (format->palette == palette) {
slouken@5288
   666
        return 0;
slouken@5288
   667
    }
slouken@5288
   668
slouken@5288
   669
    if (format->palette) {
slouken@5288
   670
        SDL_FreePalette(format->palette);
slouken@5288
   671
    }
slouken@5288
   672
slouken@5288
   673
    format->palette = palette;
slouken@5288
   674
slouken@5288
   675
    if (format->palette) {
slouken@5288
   676
        ++format->palette->refcount;
slouken@5288
   677
    }
slouken@5295
   678
slouken@5295
   679
    return 0;
slouken@5288
   680
}
slouken@5288
   681
slouken@5288
   682
int
slouken@5288
   683
SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
slouken@5288
   684
                     int firstcolor, int ncolors)
slouken@5288
   685
{
slouken@5288
   686
    int status = 0;
slouken@5288
   687
slouken@5288
   688
    /* Verify the parameters */
slouken@5288
   689
    if (!palette) {
slouken@5288
   690
        return -1;
slouken@5288
   691
    }
slouken@5288
   692
    if (ncolors > (palette->ncolors - firstcolor)) {
slouken@5288
   693
        ncolors = (palette->ncolors - firstcolor);
slouken@5288
   694
        status = -1;
slouken@5288
   695
    }
slouken@5288
   696
slouken@5288
   697
    if (colors != (palette->colors + firstcolor)) {
slouken@5288
   698
        SDL_memcpy(palette->colors + firstcolor, colors,
slouken@5288
   699
                   ncolors * sizeof(*colors));
slouken@5288
   700
    }
slouken@5288
   701
    ++palette->version;
slouken@5288
   702
    if (!palette->version) {
slouken@5288
   703
        palette->version = 1;
slouken@5288
   704
    }
slouken@5288
   705
slouken@5288
   706
    return status;
slouken@5288
   707
}
slouken@5288
   708
slouken@5288
   709
void
slouken@5288
   710
SDL_FreePalette(SDL_Palette * palette)
slouken@5288
   711
{
slouken@5288
   712
    if (!palette) {
aschiffler@7142
   713
        SDL_InvalidParamError("palette");
slouken@5288
   714
        return;
slouken@5288
   715
    }
slouken@5288
   716
    if (--palette->refcount > 0) {
slouken@5288
   717
        return;
slouken@5288
   718
    }
slouken@7719
   719
    SDL_free(palette->colors);
slouken@5288
   720
    SDL_free(palette);
slouken@5288
   721
}
slouken@5288
   722
slouken@0
   723
/*
slouken@0
   724
 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
slouken@0
   725
 */
slouken@1895
   726
void
slouken@1895
   727
SDL_DitherColors(SDL_Color * colors, int bpp)
slouken@0
   728
{
slouken@1895
   729
    int i;
slouken@1895
   730
    if (bpp != 8)
slouken@1895
   731
        return;                 /* only 8bpp supported right now */
slouken@0
   732
slouken@1895
   733
    for (i = 0; i < 256; i++) {
slouken@1895
   734
        int r, g, b;
slouken@1895
   735
        /* map each bit field to the full [0, 255] interval,
slouken@1895
   736
           so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
slouken@1895
   737
        r = i & 0xe0;
slouken@1895
   738
        r |= r >> 3 | r >> 6;
slouken@1895
   739
        colors[i].r = r;
slouken@1895
   740
        g = (i << 3) & 0xe0;
slouken@1895
   741
        g |= g >> 3 | g >> 6;
slouken@1895
   742
        colors[i].g = g;
slouken@1895
   743
        b = i & 0x3;
slouken@1895
   744
        b |= b << 2;
slouken@1895
   745
        b |= b << 4;
slouken@1895
   746
        colors[i].b = b;
slouken@7024
   747
        colors[i].a = SDL_ALPHA_OPAQUE;
slouken@1895
   748
    }
slouken@0
   749
}
slouken@1895
   750
slouken@7191
   751
/*
slouken@0
   752
 * Match an RGB value to a particular palette index
slouken@0
   753
 */
slouken@1895
   754
Uint8
slouken@7023
   755
SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@0
   756
{
slouken@1895
   757
    /* Do colorspace distance matching */
slouken@1895
   758
    unsigned int smallest;
slouken@1895
   759
    unsigned int distance;
slouken@7023
   760
    int rd, gd, bd, ad;
slouken@1895
   761
    int i;
slouken@1895
   762
    Uint8 pixel = 0;
slouken@1895
   763
slouken@1895
   764
    smallest = ~0;
slouken@1895
   765
    for (i = 0; i < pal->ncolors; ++i) {
slouken@1895
   766
        rd = pal->colors[i].r - r;
slouken@1895
   767
        gd = pal->colors[i].g - g;
slouken@1895
   768
        bd = pal->colors[i].b - b;
slouken@7024
   769
        ad = pal->colors[i].a - a;
slouken@7023
   770
        distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
slouken@1895
   771
        if (distance < smallest) {
slouken@1895
   772
            pixel = i;
slouken@1895
   773
            if (distance == 0) {        /* Perfect match! */
slouken@1895
   774
                break;
slouken@1895
   775
            }
slouken@1895
   776
            smallest = distance;
slouken@1895
   777
        }
slouken@1895
   778
    }
slouken@1895
   779
    return (pixel);
slouken@0
   780
}
slouken@0
   781
slouken@0
   782
/* Find the opaque pixel value corresponding to an RGB triple */
slouken@1895
   783
Uint32
slouken@2275
   784
SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
slouken@0
   785
{
slouken@1895
   786
    if (format->palette == NULL) {
slouken@1895
   787
        return (r >> format->Rloss) << format->Rshift
slouken@1895
   788
            | (g >> format->Gloss) << format->Gshift
slouken@1895
   789
            | (b >> format->Bloss) << format->Bshift | format->Amask;
slouken@1895
   790
    } else {
slouken@7023
   791
        return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
slouken@1895
   792
    }
slouken@0
   793
}
slouken@0
   794
slouken@0
   795
/* Find the pixel value corresponding to an RGBA quadruple */
slouken@1895
   796
Uint32
slouken@2275
   797
SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
slouken@2275
   798
            Uint8 a)
slouken@0
   799
{
slouken@1895
   800
    if (format->palette == NULL) {
slouken@1895
   801
        return (r >> format->Rloss) << format->Rshift
slouken@1895
   802
            | (g >> format->Gloss) << format->Gshift
slouken@1895
   803
            | (b >> format->Bloss) << format->Bshift
slouken@1895
   804
            | ((a >> format->Aloss) << format->Ashift & format->Amask);
slouken@1895
   805
    } else {
slouken@7023
   806
        return SDL_FindColor(format->palette, r, g, b, a);
slouken@1895
   807
    }
slouken@0
   808
}
slouken@0
   809
slouken@1895
   810
void
slouken@2275
   811
SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
slouken@2275
   812
           Uint8 * b)
slouken@2275
   813
{
slouken@2275
   814
    if (format->palette == NULL) {
slouken@2275
   815
        unsigned v;
slouken@2275
   816
        v = (pixel & format->Rmask) >> format->Rshift;
slouken@5439
   817
        *r = SDL_expand_byte[format->Rloss][v];
slouken@2275
   818
        v = (pixel & format->Gmask) >> format->Gshift;
slouken@5439
   819
        *g = SDL_expand_byte[format->Gloss][v];
slouken@2275
   820
        v = (pixel & format->Bmask) >> format->Bshift;
slouken@5439
   821
        *b = SDL_expand_byte[format->Bloss][v];
slouken@2275
   822
    } else {
slouken@5447
   823
        if (pixel < (unsigned)format->palette->ncolors) {
slouken@5436
   824
            *r = format->palette->colors[pixel].r;
slouken@5436
   825
            *g = format->palette->colors[pixel].g;
slouken@5436
   826
            *b = format->palette->colors[pixel].b;
slouken@5436
   827
        } else {
slouken@5436
   828
            *r = *g = *b = 0;
slouken@5436
   829
        }
slouken@2275
   830
    }
slouken@2275
   831
}
slouken@2275
   832
slouken@2275
   833
void
slouken@2275
   834
SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
slouken@1895
   835
            Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
slouken@0
   836
{
slouken@2275
   837
    if (format->palette == NULL) {
slouken@1895
   838
        unsigned v;
slouken@2275
   839
        v = (pixel & format->Rmask) >> format->Rshift;
slouken@5439
   840
        *r = SDL_expand_byte[format->Rloss][v];
slouken@2275
   841
        v = (pixel & format->Gmask) >> format->Gshift;
slouken@5439
   842
        *g = SDL_expand_byte[format->Gloss][v];
slouken@2275
   843
        v = (pixel & format->Bmask) >> format->Bshift;
slouken@5439
   844
        *b = SDL_expand_byte[format->Bloss][v];
slouken@5439
   845
        v = (pixel & format->Amask) >> format->Ashift;
slouken@5439
   846
        *a = SDL_expand_byte[format->Aloss][v];
slouken@1895
   847
    } else {
slouken@5447
   848
        if (pixel < (unsigned)format->palette->ncolors) {
slouken@5436
   849
            *r = format->palette->colors[pixel].r;
slouken@5436
   850
            *g = format->palette->colors[pixel].g;
slouken@5436
   851
            *b = format->palette->colors[pixel].b;
slouken@7024
   852
            *a = format->palette->colors[pixel].a;
slouken@5436
   853
        } else {
slouken@5436
   854
            *r = *g = *b = *a = 0;
slouken@5436
   855
        }
slouken@1895
   856
    }
slouken@0
   857
}
slouken@0
   858
slouken@0
   859
/* Map from Palette to Palette */
slouken@1895
   860
static Uint8 *
slouken@1895
   861
Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
slouken@0
   862
{
slouken@1895
   863
    Uint8 *map;
slouken@1895
   864
    int i;
slouken@0
   865
slouken@1895
   866
    if (identical) {
slouken@1895
   867
        if (src->ncolors <= dst->ncolors) {
slouken@1895
   868
            /* If an identical palette, no need to map */
slouken@1895
   869
            if (src == dst
slouken@1895
   870
                ||
slouken@1895
   871
                (SDL_memcmp
slouken@1895
   872
                 (src->colors, dst->colors,
slouken@1895
   873
                  src->ncolors * sizeof(SDL_Color)) == 0)) {
slouken@1895
   874
                *identical = 1;
slouken@1895
   875
                return (NULL);
slouken@1895
   876
            }
slouken@1895
   877
        }
slouken@1895
   878
        *identical = 0;
slouken@1895
   879
    }
slouken@1895
   880
    map = (Uint8 *) SDL_malloc(src->ncolors);
slouken@1895
   881
    if (map == NULL) {
slouken@1895
   882
        SDL_OutOfMemory();
slouken@1895
   883
        return (NULL);
slouken@1895
   884
    }
slouken@1895
   885
    for (i = 0; i < src->ncolors; ++i) {
slouken@1895
   886
        map[i] = SDL_FindColor(dst,
slouken@1895
   887
                               src->colors[i].r, src->colors[i].g,
slouken@7024
   888
                               src->colors[i].b, src->colors[i].a);
slouken@1895
   889
    }
slouken@1895
   890
    return (map);
slouken@0
   891
}
slouken@0
   892
slouken@1895
   893
/* Map from Palette to BitField */
slouken@1895
   894
static Uint8 *
slouken@2267
   895
Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
slouken@2267
   896
        SDL_PixelFormat * dst)
slouken@0
   897
{
slouken@1895
   898
    Uint8 *map;
slouken@1895
   899
    int i;
slouken@1895
   900
    int bpp;
slouken@1895
   901
    SDL_Palette *pal = src->palette;
slouken@0
   902
slouken@1895
   903
    bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
slouken@1895
   904
    map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
slouken@1895
   905
    if (map == NULL) {
slouken@1895
   906
        SDL_OutOfMemory();
slouken@1895
   907
        return (NULL);
slouken@1895
   908
    }
slouken@0
   909
slouken@1895
   910
    /* We memory copy to the pixel map so the endianness is preserved */
slouken@1895
   911
    for (i = 0; i < pal->ncolors; ++i) {
slouken@2267
   912
        Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
slouken@2267
   913
        Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
slouken@2267
   914
        Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
slouken@7024
   915
        Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
slouken@2257
   916
        ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
slouken@1895
   917
    }
slouken@1895
   918
    return (map);
slouken@1895
   919
}
slouken@0
   920
slouken@1895
   921
/* Map from BitField to Dithered-Palette to Palette */
slouken@1895
   922
static Uint8 *
slouken@1895
   923
MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
slouken@1895
   924
{
slouken@1895
   925
    /* Generate a 256 color dither palette */
slouken@1895
   926
    SDL_Palette dithered;
slouken@1895
   927
    SDL_Color colors[256];
slouken@1895
   928
    SDL_Palette *pal = dst->palette;
slouken@1895
   929
slouken@1895
   930
    dithered.ncolors = 256;
slouken@1895
   931
    SDL_DitherColors(colors, 8);
slouken@1895
   932
    dithered.colors = colors;
slouken@1895
   933
    return (Map1to1(&dithered, pal, identical));
slouken@0
   934
}
slouken@1895
   935
slouken@1895
   936
SDL_BlitMap *
slouken@1895
   937
SDL_AllocBlitMap(void)
slouken@0
   938
{
slouken@1895
   939
    SDL_BlitMap *map;
slouken@1895
   940
slouken@1895
   941
    /* Allocate the empty map */
slouken@1920
   942
    map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
slouken@1895
   943
    if (map == NULL) {
slouken@1895
   944
        SDL_OutOfMemory();
slouken@1895
   945
        return (NULL);
slouken@1895
   946
    }
slouken@2267
   947
    map->info.r = 0xFF;
slouken@2267
   948
    map->info.g = 0xFF;
slouken@2267
   949
    map->info.b = 0xFF;
slouken@2267
   950
    map->info.a = 0xFF;
slouken@1895
   951
slouken@1895
   952
    /* It's ready to go */
slouken@1895
   953
    return (map);
slouken@0
   954
}
slouken@1895
   955
slouken@1895
   956
void
slouken@1895
   957
SDL_InvalidateMap(SDL_BlitMap * map)
slouken@0
   958
{
slouken@1895
   959
    if (!map) {
slouken@1895
   960
        return;
slouken@1895
   961
    }
slouken@6222
   962
    if (map->dst) {
slouken@6222
   963
        /* Release our reference to the surface - see the note below */
slouken@6222
   964
        if (--map->dst->refcount <= 0) {
slouken@6222
   965
            SDL_FreeSurface(map->dst);
slouken@6222
   966
        }
slouken@6222
   967
    }
slouken@1895
   968
    map->dst = NULL;
slouken@6166
   969
    map->src_palette_version = 0;
slouken@6166
   970
    map->dst_palette_version = 0;
slouken@7719
   971
    SDL_free(map->info.table);
slouken@7719
   972
    map->info.table = NULL;
slouken@1895
   973
}
slouken@2735
   974
slouken@1895
   975
int
slouken@1895
   976
SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
slouken@1895
   977
{
slouken@1895
   978
    SDL_PixelFormat *srcfmt;
slouken@1895
   979
    SDL_PixelFormat *dstfmt;
slouken@1895
   980
    SDL_BlitMap *map;
slouken@0
   981
slouken@1895
   982
    /* Clear out any previous mapping */
slouken@1895
   983
    map = src->map;
slouken@1895
   984
    if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
slouken@1895
   985
        SDL_UnRLESurface(src, 1);
slouken@1895
   986
    }
slouken@1895
   987
    SDL_InvalidateMap(map);
slouken@0
   988
slouken@1895
   989
    /* Figure out what kind of mapping we're doing */
slouken@1895
   990
    map->identity = 0;
slouken@1895
   991
    srcfmt = src->format;
slouken@1895
   992
    dstfmt = dst->format;
slouken@5288
   993
    if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
slouken@5288
   994
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
   995
            /* Palette --> Palette */
slouken@2267
   996
            map->info.table =
slouken@1895
   997
                Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
slouken@1895
   998
            if (!map->identity) {
slouken@2267
   999
                if (map->info.table == NULL) {
slouken@1895
  1000
                    return (-1);
slouken@1895
  1001
                }
slouken@1895
  1002
            }
slouken@1895
  1003
            if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
slouken@1895
  1004
                map->identity = 0;
slouken@5288
  1005
        } else {
slouken@1895
  1006
            /* Palette --> BitField */
slouken@2267
  1007
            map->info.table =
slouken@2267
  1008
                Map1toN(srcfmt, src->map->info.r, src->map->info.g,
slouken@2267
  1009
                        src->map->info.b, src->map->info.a, dstfmt);
slouken@2267
  1010
            if (map->info.table == NULL) {
slouken@1895
  1011
                return (-1);
slouken@1895
  1012
            }
slouken@1895
  1013
        }
slouken@5288
  1014
    } else {
slouken@5288
  1015
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
  1016
            /* BitField --> Palette */
slouken@2267
  1017
            map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
slouken@1895
  1018
            if (!map->identity) {
slouken@2267
  1019
                if (map->info.table == NULL) {
slouken@1895
  1020
                    return (-1);
slouken@1895
  1021
                }
slouken@1895
  1022
            }
slouken@1895
  1023
            map->identity = 0;  /* Don't optimize to copy */
slouken@5288
  1024
        } else {
slouken@1895
  1025
            /* BitField --> BitField */
slouken@5288
  1026
            if (srcfmt == dstfmt) {
slouken@1895
  1027
                map->identity = 1;
slouken@5288
  1028
            }
slouken@1895
  1029
        }
slouken@1895
  1030
    }
slouken@0
  1031
slouken@1895
  1032
    map->dst = dst;
slouken@5288
  1033
slouken@6222
  1034
    if (map->dst) {
slouken@6222
  1035
        /* Keep a reference to this surface so it doesn't get deleted
slouken@6222
  1036
           while we're still pointing at it.
slouken@6222
  1037
slouken@6222
  1038
           A better method would be for the destination surface to keep
slouken@7191
  1039
           track of surfaces that are mapped to it and automatically
slouken@6222
  1040
           invalidate them when it is freed, but this will do for now.
slouken@6222
  1041
        */
slouken@6222
  1042
        ++map->dst->refcount;
slouken@6222
  1043
    }
slouken@6222
  1044
slouken@5288
  1045
    if (dstfmt->palette) {
slouken@6166
  1046
        map->dst_palette_version = dstfmt->palette->version;
slouken@5288
  1047
    } else {
slouken@6166
  1048
        map->dst_palette_version = 0;
slouken@6166
  1049
    }
slouken@6166
  1050
slouken@6166
  1051
    if (srcfmt->palette) {
slouken@6166
  1052
        map->src_palette_version = srcfmt->palette->version;
slouken@6166
  1053
    } else {
slouken@6166
  1054
        map->src_palette_version = 0;
slouken@5288
  1055
    }
slouken@0
  1056
slouken@1895
  1057
    /* Choose your blitters wisely */
slouken@1895
  1058
    return (SDL_CalculateBlit(src));
slouken@0
  1059
}
slouken@1895
  1060
slouken@1895
  1061
void
slouken@1895
  1062
SDL_FreeBlitMap(SDL_BlitMap * map)
slouken@0
  1063
{
slouken@1895
  1064
    if (map) {
slouken@1895
  1065
        SDL_InvalidateMap(map);
slouken@1895
  1066
        SDL_free(map);
slouken@1895
  1067
    }
slouken@0
  1068
}
slouken@1895
  1069
slouken@5466
  1070
void
slouken@5466
  1071
SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
slouken@5466
  1072
{
slouken@5466
  1073
    int i;
slouken@7191
  1074
aschiffler@7151
  1075
    /* Input validation */
aschiffler@7151
  1076
    if (gamma < 0.0f ) {
aschiffler@7151
  1077
      SDL_InvalidParamError("gamma");
aschiffler@7151
  1078
      return;
aschiffler@7151
  1079
    }
aschiffler@7151
  1080
    if (ramp == NULL) {
aschiffler@7151
  1081
      SDL_InvalidParamError("ramp");
aschiffler@7151
  1082
      return;
aschiffler@7151
  1083
    }
slouken@5466
  1084
slouken@5466
  1085
    /* 0.0 gamma is all black */
aschiffler@7151
  1086
    if (gamma == 0.0f) {
icculus@9715
  1087
        SDL_memset(ramp, 0, 256 * sizeof(Uint16));
slouken@5466
  1088
        return;
slouken@5466
  1089
    } else if (gamma == 1.0f) {
slouken@5466
  1090
        /* 1.0 gamma is identity */
slouken@5466
  1091
        for (i = 0; i < 256; ++i) {
slouken@5466
  1092
            ramp[i] = (i << 8) | i;
slouken@5466
  1093
        }
slouken@5466
  1094
        return;
slouken@5466
  1095
    } else {
slouken@5466
  1096
        /* Calculate a real gamma ramp */
slouken@5466
  1097
        int value;
slouken@5466
  1098
        gamma = 1.0f / gamma;
slouken@5466
  1099
        for (i = 0; i < 256; ++i) {
slouken@5466
  1100
            value =
slouken@5466
  1101
                (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
slouken@5466
  1102
            if (value > 65535) {
slouken@5466
  1103
                value = 65535;
slouken@5466
  1104
            }
slouken@5466
  1105
            ramp[i] = (Uint16) value;
slouken@5466
  1106
        }
slouken@5466
  1107
    }
slouken@5466
  1108
}
slouken@5466
  1109
slouken@1895
  1110
/* vi: set ts=4 sw=4 expandtab: */