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