src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 01 Jan 2017 18:33:28 -0800
changeset 10737 3406a0f8b041
parent 9998 f67cf37e9cd4
child 11250 c9b15b9a04e3
permissions -rw-r--r--
Updated copyright for 2017
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 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@5350
   329
        /* Fall through to 16-bit checks */
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@1895
   406
        break;
lestat@3182
   407
    case 24:
lestat@3182
   408
        switch (Rmask) {
slouken@5288
   409
        case 0:
lestat@3182
   410
        case 0x00FF0000:
slouken@3597
   411
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@3597
   412
            return SDL_PIXELFORMAT_RGB24;
slouken@3597
   413
#else
slouken@3597
   414
            return SDL_PIXELFORMAT_BGR24;
slouken@3597
   415
#endif
lestat@3182
   416
        case 0x000000FF:
slouken@3597
   417
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
slouken@3597
   418
            return SDL_PIXELFORMAT_BGR24;
slouken@3597
   419
#else
slouken@3597
   420
            return SDL_PIXELFORMAT_RGB24;
slouken@3597
   421
#endif
lestat@3182
   422
        }
slouken@1895
   423
    case 32:
slouken@5350
   424
        if (Rmask == 0) {
slouken@5350
   425
            return SDL_PIXELFORMAT_RGB888;
slouken@5350
   426
        }
slouken@5350
   427
        if (Rmask == 0x00FF0000 &&
slouken@5350
   428
            Gmask == 0x0000FF00 &&
slouken@5350
   429
            Bmask == 0x000000FF &&
slouken@5350
   430
            Amask == 0x00000000) {
slouken@5352
   431
            return SDL_PIXELFORMAT_RGB888;
slouken@5350
   432
        }
slouken@6074
   433
        if (Rmask == 0xFF000000 &&
slouken@6074
   434
            Gmask == 0x00FF0000 &&
slouken@6074
   435
            Bmask == 0x0000FF00 &&
slouken@6074
   436
            Amask == 0x00000000) {
slouken@6074
   437
            return SDL_PIXELFORMAT_RGBX8888;
slouken@6074
   438
        }
slouken@5350
   439
        if (Rmask == 0x000000FF &&
slouken@5350
   440
            Gmask == 0x0000FF00 &&
slouken@5350
   441
            Bmask == 0x00FF0000 &&
slouken@5350
   442
            Amask == 0x00000000) {
slouken@5352
   443
            return SDL_PIXELFORMAT_BGR888;
slouken@5350
   444
        }
slouken@6074
   445
        if (Rmask == 0x0000FF00 &&
slouken@6074
   446
            Gmask == 0x00FF0000 &&
slouken@6074
   447
            Bmask == 0xFF000000 &&
slouken@6074
   448
            Amask == 0x00000000) {
slouken@6074
   449
            return SDL_PIXELFORMAT_BGRX8888;
slouken@6074
   450
        }
slouken@5350
   451
        if (Rmask == 0x00FF0000 &&
slouken@5350
   452
            Gmask == 0x0000FF00 &&
slouken@5350
   453
            Bmask == 0x000000FF &&
slouken@5350
   454
            Amask == 0xFF000000) {
slouken@5352
   455
            return SDL_PIXELFORMAT_ARGB8888;
slouken@5350
   456
        }
slouken@5350
   457
        if (Rmask == 0xFF000000 &&
slouken@5350
   458
            Gmask == 0x00FF0000 &&
slouken@5350
   459
            Bmask == 0x0000FF00 &&
slouken@5350
   460
            Amask == 0x000000FF) {
slouken@5352
   461
            return SDL_PIXELFORMAT_RGBA8888;
slouken@5350
   462
        }
slouken@5350
   463
        if (Rmask == 0x000000FF &&
slouken@5350
   464
            Gmask == 0x0000FF00 &&
slouken@5350
   465
            Bmask == 0x00FF0000 &&
slouken@5350
   466
            Amask == 0xFF000000) {
slouken@5352
   467
            return SDL_PIXELFORMAT_ABGR8888;
slouken@5350
   468
        }
slouken@5350
   469
        if (Rmask == 0x0000FF00 &&
slouken@5350
   470
            Gmask == 0x00FF0000 &&
slouken@5350
   471
            Bmask == 0xFF000000 &&
slouken@5350
   472
            Amask == 0x000000FF) {
slouken@5352
   473
            return SDL_PIXELFORMAT_BGRA8888;
slouken@5350
   474
        }
slouken@5350
   475
        if (Rmask == 0x3FF00000 &&
slouken@5350
   476
            Gmask == 0x000FFC00 &&
slouken@5350
   477
            Bmask == 0x000003FF &&
slouken@5350
   478
            Amask == 0xC0000000) {
slouken@5352
   479
            return SDL_PIXELFORMAT_ARGB2101010;
slouken@1895
   480
        }
slouken@1895
   481
    }
slouken@1965
   482
    return SDL_PIXELFORMAT_UNKNOWN;
slouken@1895
   483
}
slouken@1895
   484
slouken@5288
   485
static SDL_PixelFormat *formats;
slouken@1895
   486
slouken@5288
   487
SDL_PixelFormat *
slouken@5288
   488
SDL_AllocFormat(Uint32 pixel_format)
slouken@1895
   489
{
slouken@5288
   490
    SDL_PixelFormat *format;
slouken@1895
   491
slouken@5288
   492
    /* Look it up in our list of previously allocated formats */
slouken@5288
   493
    for (format = formats; format; format = format->next) {
slouken@5288
   494
        if (pixel_format == format->format) {
slouken@5288
   495
            ++format->refcount;
slouken@5288
   496
            return format;
slouken@1895
   497
        }
slouken@1895
   498
    }
slouken@1895
   499
slouken@5288
   500
    /* Allocate an empty pixel format structure, and initialize it */
slouken@2967
   501
    format = SDL_malloc(sizeof(*format));
slouken@1895
   502
    if (format == NULL) {
slouken@1895
   503
        SDL_OutOfMemory();
slouken@5433
   504
        return NULL;
slouken@1895
   505
    }
slouken@5433
   506
    if (SDL_InitFormat(format, pixel_format) < 0) {
slouken@5433
   507
        SDL_free(format);
aschiffler@7142
   508
        SDL_InvalidParamError("format");
slouken@5433
   509
        return NULL;
slouken@5433
   510
    }
slouken@0
   511
slouken@5288
   512
    if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
slouken@5288
   513
        /* Cache the RGB formats */
slouken@5288
   514
        format->next = formats;
slouken@5288
   515
        formats = format;
slouken@5288
   516
    }
slouken@5288
   517
    return format;
slouken@2967
   518
}
slouken@2967
   519
slouken@5288
   520
int
slouken@5288
   521
SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
slouken@2967
   522
{
slouken@5432
   523
    int bpp;
slouken@5432
   524
    Uint32 Rmask, Gmask, Bmask, Amask;
slouken@5432
   525
    Uint32 mask;
slouken@5432
   526
slouken@5432
   527
    if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
slouken@5432
   528
                                    &Rmask, &Gmask, &Bmask, &Amask)) {
slouken@5432
   529
        return -1;
slouken@5432
   530
    }
slouken@5432
   531
slouken@2967
   532
    /* Set up the format */
slouken@2967
   533
    SDL_zerop(format);
slouken@5288
   534
    format->format = pixel_format;
slouken@5432
   535
    format->BitsPerPixel = bpp;
slouken@5432
   536
    format->BytesPerPixel = (bpp + 7) / 8;
slouken@5431
   537
slouken@5432
   538
    format->Rmask = Rmask;
slouken@5432
   539
    format->Rshift = 0;
slouken@5432
   540
    format->Rloss = 8;
slouken@5432
   541
    if (Rmask) {
slouken@5432
   542
        for (mask = Rmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   543
            ++format->Rshift;
slouken@5432
   544
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   545
            --format->Rloss;
slouken@5432
   546
    }
slouken@5431
   547
slouken@5432
   548
    format->Gmask = Gmask;
slouken@5432
   549
    format->Gshift = 0;
slouken@5432
   550
    format->Gloss = 8;
slouken@5432
   551
    if (Gmask) {
slouken@5432
   552
        for (mask = Gmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   553
            ++format->Gshift;
slouken@5432
   554
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   555
            --format->Gloss;
slouken@1895
   556
    }
slouken@5432
   557
slouken@5432
   558
    format->Bmask = Bmask;
slouken@5432
   559
    format->Bshift = 0;
slouken@5432
   560
    format->Bloss = 8;
slouken@5432
   561
    if (Bmask) {
slouken@5432
   562
        for (mask = Bmask; !(mask & 0x01); mask >>= 1)
slouken@5432
   563
            ++format->Bshift;
slouken@5432
   564
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   565
            --format->Bloss;
slouken@5432
   566
    }
slouken@5432
   567
slouken@5432
   568
    format->Amask = Amask;
slouken@5432
   569
    format->Ashift = 0;
slouken@5432
   570
    format->Aloss = 8;
slouken@5432
   571
    if (Amask) {
slouken@5432
   572
        for (mask = Amask; !(mask & 0x01); mask >>= 1)
slouken@5432
   573
            ++format->Ashift;
slouken@5432
   574
        for (; (mask & 0x01); mask >>= 1)
slouken@5432
   575
            --format->Aloss;
slouken@5432
   576
    }
slouken@5432
   577
slouken@1895
   578
    format->palette = NULL;
slouken@5288
   579
    format->refcount = 1;
slouken@5288
   580
    format->next = NULL;
slouken@1057
   581
slouken@5288
   582
    return 0;
slouken@0
   583
}
slouken@0
   584
slouken@1895
   585
void
slouken@5288
   586
SDL_FreeFormat(SDL_PixelFormat *format)
slouken@0
   587
{
slouken@5288
   588
    SDL_PixelFormat *prev;
slouken@1895
   589
slouken@1895
   590
    if (!format) {
aschiffler@7142
   591
        SDL_InvalidParamError("format");
slouken@1895
   592
        return;
slouken@1895
   593
    }
slouken@5288
   594
    if (--format->refcount > 0) {
slouken@5288
   595
        return;
slouken@5288
   596
    }
slouken@5288
   597
slouken@5288
   598
    /* Remove this format from our list */
slouken@5288
   599
    if (format == formats) {
slouken@5288
   600
        formats = format->next;
slouken@5288
   601
    } else if (formats) {
slouken@5288
   602
        for (prev = formats; prev->next; prev = prev->next) {
slouken@5288
   603
            if (prev->next == format) {
slouken@5288
   604
                prev->next = format->next;
slouken@5288
   605
                break;
slouken@5288
   606
            }
slouken@5288
   607
        }
slouken@5288
   608
    }
slouken@5288
   609
slouken@5288
   610
    if (format->palette) {
slouken@5288
   611
        SDL_FreePalette(format->palette);
slouken@5288
   612
    }
slouken@1895
   613
    SDL_free(format);
slouken@0
   614
}
slouken@1895
   615
slouken@5288
   616
SDL_Palette *
slouken@5288
   617
SDL_AllocPalette(int ncolors)
slouken@5288
   618
{
slouken@5288
   619
    SDL_Palette *palette;
slouken@7191
   620
aschiffler@7142
   621
    /* Input validation */
aschiffler@7142
   622
    if (ncolors < 1) {
aschiffler@7142
   623
      SDL_InvalidParamError("ncolors");
aschiffler@7142
   624
      return NULL;
aschiffler@7142
   625
    }
slouken@5288
   626
slouken@5288
   627
    palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
slouken@5288
   628
    if (!palette) {
slouken@5288
   629
        SDL_OutOfMemory();
slouken@5288
   630
        return NULL;
slouken@5288
   631
    }
slouken@5288
   632
    palette->colors =
slouken@5288
   633
        (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
slouken@5288
   634
    if (!palette->colors) {
slouken@5288
   635
        SDL_free(palette);
slouken@5288
   636
        return NULL;
slouken@5288
   637
    }
slouken@5288
   638
    palette->ncolors = ncolors;
slouken@5288
   639
    palette->version = 1;
slouken@5288
   640
    palette->refcount = 1;
slouken@5288
   641
slouken@5288
   642
    SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
slouken@5288
   643
slouken@5288
   644
    return palette;
slouken@5288
   645
}
slouken@5288
   646
slouken@5288
   647
int
slouken@5288
   648
SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
slouken@5288
   649
{
slouken@5288
   650
    if (!format) {
icculus@7037
   651
        return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
slouken@5288
   652
    }
slouken@5288
   653
slouken@5288
   654
    if (palette && palette->ncolors != (1 << format->BitsPerPixel)) {
icculus@7037
   655
        return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
slouken@5288
   656
    }
slouken@5288
   657
slouken@5288
   658
    if (format->palette == palette) {
slouken@5288
   659
        return 0;
slouken@5288
   660
    }
slouken@5288
   661
slouken@5288
   662
    if (format->palette) {
slouken@5288
   663
        SDL_FreePalette(format->palette);
slouken@5288
   664
    }
slouken@5288
   665
slouken@5288
   666
    format->palette = palette;
slouken@5288
   667
slouken@5288
   668
    if (format->palette) {
slouken@5288
   669
        ++format->palette->refcount;
slouken@5288
   670
    }
slouken@5295
   671
slouken@5295
   672
    return 0;
slouken@5288
   673
}
slouken@5288
   674
slouken@5288
   675
int
slouken@5288
   676
SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
slouken@5288
   677
                     int firstcolor, int ncolors)
slouken@5288
   678
{
slouken@5288
   679
    int status = 0;
slouken@5288
   680
slouken@5288
   681
    /* Verify the parameters */
slouken@5288
   682
    if (!palette) {
slouken@5288
   683
        return -1;
slouken@5288
   684
    }
slouken@5288
   685
    if (ncolors > (palette->ncolors - firstcolor)) {
slouken@5288
   686
        ncolors = (palette->ncolors - firstcolor);
slouken@5288
   687
        status = -1;
slouken@5288
   688
    }
slouken@5288
   689
slouken@5288
   690
    if (colors != (palette->colors + firstcolor)) {
slouken@5288
   691
        SDL_memcpy(palette->colors + firstcolor, colors,
slouken@5288
   692
                   ncolors * sizeof(*colors));
slouken@5288
   693
    }
slouken@5288
   694
    ++palette->version;
slouken@5288
   695
    if (!palette->version) {
slouken@5288
   696
        palette->version = 1;
slouken@5288
   697
    }
slouken@5288
   698
slouken@5288
   699
    return status;
slouken@5288
   700
}
slouken@5288
   701
slouken@5288
   702
void
slouken@5288
   703
SDL_FreePalette(SDL_Palette * palette)
slouken@5288
   704
{
slouken@5288
   705
    if (!palette) {
aschiffler@7142
   706
        SDL_InvalidParamError("palette");
slouken@5288
   707
        return;
slouken@5288
   708
    }
slouken@5288
   709
    if (--palette->refcount > 0) {
slouken@5288
   710
        return;
slouken@5288
   711
    }
slouken@7719
   712
    SDL_free(palette->colors);
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@7191
   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@7719
   988
    SDL_free(map->info.table);
slouken@7719
   989
    map->info.table = NULL;
slouken@1895
   990
}
slouken@2735
   991
slouken@1895
   992
int
slouken@1895
   993
SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
slouken@1895
   994
{
slouken@1895
   995
    SDL_PixelFormat *srcfmt;
slouken@1895
   996
    SDL_PixelFormat *dstfmt;
slouken@1895
   997
    SDL_BlitMap *map;
slouken@0
   998
slouken@1895
   999
    /* Clear out any previous mapping */
slouken@1895
  1000
    map = src->map;
slouken@1895
  1001
    if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
slouken@1895
  1002
        SDL_UnRLESurface(src, 1);
slouken@1895
  1003
    }
slouken@1895
  1004
    SDL_InvalidateMap(map);
slouken@0
  1005
slouken@1895
  1006
    /* Figure out what kind of mapping we're doing */
slouken@1895
  1007
    map->identity = 0;
slouken@1895
  1008
    srcfmt = src->format;
slouken@1895
  1009
    dstfmt = dst->format;
slouken@5288
  1010
    if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
slouken@5288
  1011
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
  1012
            /* Palette --> Palette */
slouken@2267
  1013
            map->info.table =
slouken@1895
  1014
                Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
slouken@1895
  1015
            if (!map->identity) {
slouken@2267
  1016
                if (map->info.table == NULL) {
slouken@1895
  1017
                    return (-1);
slouken@1895
  1018
                }
slouken@1895
  1019
            }
slouken@1895
  1020
            if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
slouken@1895
  1021
                map->identity = 0;
slouken@5288
  1022
        } else {
slouken@1895
  1023
            /* Palette --> BitField */
slouken@2267
  1024
            map->info.table =
slouken@2267
  1025
                Map1toN(srcfmt, src->map->info.r, src->map->info.g,
slouken@2267
  1026
                        src->map->info.b, src->map->info.a, dstfmt);
slouken@2267
  1027
            if (map->info.table == NULL) {
slouken@1895
  1028
                return (-1);
slouken@1895
  1029
            }
slouken@1895
  1030
        }
slouken@5288
  1031
    } else {
slouken@5288
  1032
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
  1033
            /* BitField --> Palette */
slouken@2267
  1034
            map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
slouken@1895
  1035
            if (!map->identity) {
slouken@2267
  1036
                if (map->info.table == NULL) {
slouken@1895
  1037
                    return (-1);
slouken@1895
  1038
                }
slouken@1895
  1039
            }
slouken@1895
  1040
            map->identity = 0;  /* Don't optimize to copy */
slouken@5288
  1041
        } else {
slouken@1895
  1042
            /* BitField --> BitField */
slouken@5288
  1043
            if (srcfmt == dstfmt) {
slouken@1895
  1044
                map->identity = 1;
slouken@5288
  1045
            }
slouken@1895
  1046
        }
slouken@1895
  1047
    }
slouken@0
  1048
slouken@1895
  1049
    map->dst = dst;
slouken@5288
  1050
slouken@6222
  1051
    if (map->dst) {
slouken@6222
  1052
        /* Keep a reference to this surface so it doesn't get deleted
slouken@6222
  1053
           while we're still pointing at it.
slouken@6222
  1054
slouken@6222
  1055
           A better method would be for the destination surface to keep
slouken@7191
  1056
           track of surfaces that are mapped to it and automatically
slouken@6222
  1057
           invalidate them when it is freed, but this will do for now.
slouken@6222
  1058
        */
slouken@6222
  1059
        ++map->dst->refcount;
slouken@6222
  1060
    }
slouken@6222
  1061
slouken@5288
  1062
    if (dstfmt->palette) {
slouken@6166
  1063
        map->dst_palette_version = dstfmt->palette->version;
slouken@5288
  1064
    } else {
slouken@6166
  1065
        map->dst_palette_version = 0;
slouken@6166
  1066
    }
slouken@6166
  1067
slouken@6166
  1068
    if (srcfmt->palette) {
slouken@6166
  1069
        map->src_palette_version = srcfmt->palette->version;
slouken@6166
  1070
    } else {
slouken@6166
  1071
        map->src_palette_version = 0;
slouken@5288
  1072
    }
slouken@0
  1073
slouken@1895
  1074
    /* Choose your blitters wisely */
slouken@1895
  1075
    return (SDL_CalculateBlit(src));
slouken@0
  1076
}
slouken@1895
  1077
slouken@1895
  1078
void
slouken@1895
  1079
SDL_FreeBlitMap(SDL_BlitMap * map)
slouken@0
  1080
{
slouken@1895
  1081
    if (map) {
slouken@1895
  1082
        SDL_InvalidateMap(map);
slouken@1895
  1083
        SDL_free(map);
slouken@1895
  1084
    }
slouken@0
  1085
}
slouken@1895
  1086
slouken@5466
  1087
void
slouken@5466
  1088
SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
slouken@5466
  1089
{
slouken@5466
  1090
    int i;
slouken@7191
  1091
aschiffler@7151
  1092
    /* Input validation */
aschiffler@7151
  1093
    if (gamma < 0.0f ) {
aschiffler@7151
  1094
      SDL_InvalidParamError("gamma");
aschiffler@7151
  1095
      return;
aschiffler@7151
  1096
    }
aschiffler@7151
  1097
    if (ramp == NULL) {
aschiffler@7151
  1098
      SDL_InvalidParamError("ramp");
aschiffler@7151
  1099
      return;
aschiffler@7151
  1100
    }
slouken@5466
  1101
slouken@5466
  1102
    /* 0.0 gamma is all black */
aschiffler@7151
  1103
    if (gamma == 0.0f) {
icculus@9715
  1104
        SDL_memset(ramp, 0, 256 * sizeof(Uint16));
slouken@5466
  1105
        return;
slouken@5466
  1106
    } else if (gamma == 1.0f) {
slouken@5466
  1107
        /* 1.0 gamma is identity */
slouken@5466
  1108
        for (i = 0; i < 256; ++i) {
slouken@5466
  1109
            ramp[i] = (i << 8) | i;
slouken@5466
  1110
        }
slouken@5466
  1111
        return;
slouken@5466
  1112
    } else {
slouken@5466
  1113
        /* Calculate a real gamma ramp */
slouken@5466
  1114
        int value;
slouken@5466
  1115
        gamma = 1.0f / gamma;
slouken@5466
  1116
        for (i = 0; i < 256; ++i) {
slouken@5466
  1117
            value =
slouken@5466
  1118
                (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
slouken@5466
  1119
            if (value > 65535) {
slouken@5466
  1120
                value = 65535;
slouken@5466
  1121
            }
slouken@5466
  1122
            ramp[i] = (Uint16) value;
slouken@5466
  1123
        }
slouken@5466
  1124
    }
slouken@5466
  1125
}
slouken@5466
  1126
slouken@1895
  1127
/* vi: set ts=4 sw=4 expandtab: */