src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 11:28:44 -0700
changeset 7776 d4a39491577f
parent 7719 31b5f9ff36ca
child 8093 b43765095a6f
permissions -rw-r--r--
Added the platform specific messagebox function to the video function list
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@7191
   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;
slouken@7191
   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@7719
   710
    SDL_free(palette->colors);
slouken@5288
   711
    SDL_free(palette);
slouken@5288
   712
}
slouken@5288
   713
slouken@0
   714
/*
slouken@0
   715
 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
slouken@0
   716
 */
slouken@1895
   717
void
slouken@1895
   718
SDL_DitherColors(SDL_Color * colors, int bpp)
slouken@0
   719
{
slouken@1895
   720
    int i;
slouken@1895
   721
    if (bpp != 8)
slouken@1895
   722
        return;                 /* only 8bpp supported right now */
slouken@0
   723
slouken@1895
   724
    for (i = 0; i < 256; i++) {
slouken@1895
   725
        int r, g, b;
slouken@1895
   726
        /* map each bit field to the full [0, 255] interval,
slouken@1895
   727
           so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
slouken@1895
   728
        r = i & 0xe0;
slouken@1895
   729
        r |= r >> 3 | r >> 6;
slouken@1895
   730
        colors[i].r = r;
slouken@1895
   731
        g = (i << 3) & 0xe0;
slouken@1895
   732
        g |= g >> 3 | g >> 6;
slouken@1895
   733
        colors[i].g = g;
slouken@1895
   734
        b = i & 0x3;
slouken@1895
   735
        b |= b << 2;
slouken@1895
   736
        b |= b << 4;
slouken@1895
   737
        colors[i].b = b;
slouken@7024
   738
        colors[i].a = SDL_ALPHA_OPAQUE;
slouken@1895
   739
    }
slouken@0
   740
}
slouken@1895
   741
slouken@7191
   742
/*
slouken@0
   743
 * Calculate the pad-aligned scanline width of a surface
slouken@0
   744
 */
slouken@1895
   745
int
slouken@1895
   746
SDL_CalculatePitch(SDL_Surface * surface)
slouken@0
   747
{
slouken@1895
   748
    int pitch;
slouken@0
   749
slouken@1895
   750
    /* Surface should be 4-byte aligned for speed */
slouken@1895
   751
    pitch = surface->w * surface->format->BytesPerPixel;
slouken@1895
   752
    switch (surface->format->BitsPerPixel) {
slouken@1895
   753
    case 1:
slouken@1895
   754
        pitch = (pitch + 7) / 8;
slouken@1895
   755
        break;
slouken@1895
   756
    case 4:
slouken@1895
   757
        pitch = (pitch + 1) / 2;
slouken@1895
   758
        break;
slouken@1895
   759
    default:
slouken@1895
   760
        break;
slouken@1895
   761
    }
slouken@1895
   762
    pitch = (pitch + 3) & ~3;   /* 4-byte aligning */
slouken@1895
   763
    return (pitch);
slouken@0
   764
}
slouken@1895
   765
slouken@0
   766
/*
slouken@0
   767
 * Match an RGB value to a particular palette index
slouken@0
   768
 */
slouken@1895
   769
Uint8
slouken@7023
   770
SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
slouken@0
   771
{
slouken@1895
   772
    /* Do colorspace distance matching */
slouken@1895
   773
    unsigned int smallest;
slouken@1895
   774
    unsigned int distance;
slouken@7023
   775
    int rd, gd, bd, ad;
slouken@1895
   776
    int i;
slouken@1895
   777
    Uint8 pixel = 0;
slouken@1895
   778
slouken@1895
   779
    smallest = ~0;
slouken@1895
   780
    for (i = 0; i < pal->ncolors; ++i) {
slouken@1895
   781
        rd = pal->colors[i].r - r;
slouken@1895
   782
        gd = pal->colors[i].g - g;
slouken@1895
   783
        bd = pal->colors[i].b - b;
slouken@7024
   784
        ad = pal->colors[i].a - a;
slouken@7023
   785
        distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
slouken@1895
   786
        if (distance < smallest) {
slouken@1895
   787
            pixel = i;
slouken@1895
   788
            if (distance == 0) {        /* Perfect match! */
slouken@1895
   789
                break;
slouken@1895
   790
            }
slouken@1895
   791
            smallest = distance;
slouken@1895
   792
        }
slouken@1895
   793
    }
slouken@1895
   794
    return (pixel);
slouken@0
   795
}
slouken@0
   796
slouken@0
   797
/* Find the opaque pixel value corresponding to an RGB triple */
slouken@1895
   798
Uint32
slouken@2275
   799
SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
slouken@0
   800
{
slouken@1895
   801
    if (format->palette == NULL) {
slouken@1895
   802
        return (r >> format->Rloss) << format->Rshift
slouken@1895
   803
            | (g >> format->Gloss) << format->Gshift
slouken@1895
   804
            | (b >> format->Bloss) << format->Bshift | format->Amask;
slouken@1895
   805
    } else {
slouken@7023
   806
        return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
slouken@1895
   807
    }
slouken@0
   808
}
slouken@0
   809
slouken@0
   810
/* Find the pixel value corresponding to an RGBA quadruple */
slouken@1895
   811
Uint32
slouken@2275
   812
SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
slouken@2275
   813
            Uint8 a)
slouken@0
   814
{
slouken@1895
   815
    if (format->palette == NULL) {
slouken@1895
   816
        return (r >> format->Rloss) << format->Rshift
slouken@1895
   817
            | (g >> format->Gloss) << format->Gshift
slouken@1895
   818
            | (b >> format->Bloss) << format->Bshift
slouken@1895
   819
            | ((a >> format->Aloss) << format->Ashift & format->Amask);
slouken@1895
   820
    } else {
slouken@7023
   821
        return SDL_FindColor(format->palette, r, g, b, a);
slouken@1895
   822
    }
slouken@0
   823
}
slouken@0
   824
slouken@1895
   825
void
slouken@2275
   826
SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
slouken@2275
   827
           Uint8 * b)
slouken@2275
   828
{
slouken@2275
   829
    if (format->palette == NULL) {
slouken@2275
   830
        unsigned v;
slouken@2275
   831
        v = (pixel & format->Rmask) >> format->Rshift;
slouken@5439
   832
        *r = SDL_expand_byte[format->Rloss][v];
slouken@2275
   833
        v = (pixel & format->Gmask) >> format->Gshift;
slouken@5439
   834
        *g = SDL_expand_byte[format->Gloss][v];
slouken@2275
   835
        v = (pixel & format->Bmask) >> format->Bshift;
slouken@5439
   836
        *b = SDL_expand_byte[format->Bloss][v];
slouken@2275
   837
    } else {
slouken@5447
   838
        if (pixel < (unsigned)format->palette->ncolors) {
slouken@5436
   839
            *r = format->palette->colors[pixel].r;
slouken@5436
   840
            *g = format->palette->colors[pixel].g;
slouken@5436
   841
            *b = format->palette->colors[pixel].b;
slouken@5436
   842
        } else {
slouken@5436
   843
            *r = *g = *b = 0;
slouken@5436
   844
        }
slouken@2275
   845
    }
slouken@2275
   846
}
slouken@2275
   847
slouken@2275
   848
void
slouken@2275
   849
SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
slouken@1895
   850
            Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
slouken@0
   851
{
slouken@2275
   852
    if (format->palette == NULL) {
slouken@1895
   853
        unsigned v;
slouken@2275
   854
        v = (pixel & format->Rmask) >> format->Rshift;
slouken@5439
   855
        *r = SDL_expand_byte[format->Rloss][v];
slouken@2275
   856
        v = (pixel & format->Gmask) >> format->Gshift;
slouken@5439
   857
        *g = SDL_expand_byte[format->Gloss][v];
slouken@2275
   858
        v = (pixel & format->Bmask) >> format->Bshift;
slouken@5439
   859
        *b = SDL_expand_byte[format->Bloss][v];
slouken@5439
   860
        v = (pixel & format->Amask) >> format->Ashift;
slouken@5439
   861
        *a = SDL_expand_byte[format->Aloss][v];
slouken@1895
   862
    } else {
slouken@5447
   863
        if (pixel < (unsigned)format->palette->ncolors) {
slouken@5436
   864
            *r = format->palette->colors[pixel].r;
slouken@5436
   865
            *g = format->palette->colors[pixel].g;
slouken@5436
   866
            *b = format->palette->colors[pixel].b;
slouken@7024
   867
            *a = format->palette->colors[pixel].a;
slouken@5436
   868
        } else {
slouken@5436
   869
            *r = *g = *b = *a = 0;
slouken@5436
   870
        }
slouken@1895
   871
    }
slouken@0
   872
}
slouken@0
   873
slouken@0
   874
/* Map from Palette to Palette */
slouken@1895
   875
static Uint8 *
slouken@1895
   876
Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
slouken@0
   877
{
slouken@1895
   878
    Uint8 *map;
slouken@1895
   879
    int i;
slouken@0
   880
slouken@1895
   881
    if (identical) {
slouken@1895
   882
        if (src->ncolors <= dst->ncolors) {
slouken@1895
   883
            /* If an identical palette, no need to map */
slouken@1895
   884
            if (src == dst
slouken@1895
   885
                ||
slouken@1895
   886
                (SDL_memcmp
slouken@1895
   887
                 (src->colors, dst->colors,
slouken@1895
   888
                  src->ncolors * sizeof(SDL_Color)) == 0)) {
slouken@1895
   889
                *identical = 1;
slouken@1895
   890
                return (NULL);
slouken@1895
   891
            }
slouken@1895
   892
        }
slouken@1895
   893
        *identical = 0;
slouken@1895
   894
    }
slouken@1895
   895
    map = (Uint8 *) SDL_malloc(src->ncolors);
slouken@1895
   896
    if (map == NULL) {
slouken@1895
   897
        SDL_OutOfMemory();
slouken@1895
   898
        return (NULL);
slouken@1895
   899
    }
slouken@1895
   900
    for (i = 0; i < src->ncolors; ++i) {
slouken@1895
   901
        map[i] = SDL_FindColor(dst,
slouken@1895
   902
                               src->colors[i].r, src->colors[i].g,
slouken@7024
   903
                               src->colors[i].b, src->colors[i].a);
slouken@1895
   904
    }
slouken@1895
   905
    return (map);
slouken@0
   906
}
slouken@0
   907
slouken@1895
   908
/* Map from Palette to BitField */
slouken@1895
   909
static Uint8 *
slouken@2267
   910
Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
slouken@2267
   911
        SDL_PixelFormat * dst)
slouken@0
   912
{
slouken@1895
   913
    Uint8 *map;
slouken@1895
   914
    int i;
slouken@1895
   915
    int bpp;
slouken@1895
   916
    SDL_Palette *pal = src->palette;
slouken@0
   917
slouken@1895
   918
    bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
slouken@1895
   919
    map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
slouken@1895
   920
    if (map == NULL) {
slouken@1895
   921
        SDL_OutOfMemory();
slouken@1895
   922
        return (NULL);
slouken@1895
   923
    }
slouken@0
   924
slouken@1895
   925
    /* We memory copy to the pixel map so the endianness is preserved */
slouken@1895
   926
    for (i = 0; i < pal->ncolors; ++i) {
slouken@2267
   927
        Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
slouken@2267
   928
        Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
slouken@2267
   929
        Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
slouken@7024
   930
        Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
slouken@2257
   931
        ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
slouken@1895
   932
    }
slouken@1895
   933
    return (map);
slouken@1895
   934
}
slouken@0
   935
slouken@1895
   936
/* Map from BitField to Dithered-Palette to Palette */
slouken@1895
   937
static Uint8 *
slouken@1895
   938
MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
slouken@1895
   939
{
slouken@1895
   940
    /* Generate a 256 color dither palette */
slouken@1895
   941
    SDL_Palette dithered;
slouken@1895
   942
    SDL_Color colors[256];
slouken@1895
   943
    SDL_Palette *pal = dst->palette;
slouken@1895
   944
slouken@1895
   945
    dithered.ncolors = 256;
slouken@1895
   946
    SDL_DitherColors(colors, 8);
slouken@1895
   947
    dithered.colors = colors;
slouken@1895
   948
    return (Map1to1(&dithered, pal, identical));
slouken@0
   949
}
slouken@1895
   950
slouken@1895
   951
SDL_BlitMap *
slouken@1895
   952
SDL_AllocBlitMap(void)
slouken@0
   953
{
slouken@1895
   954
    SDL_BlitMap *map;
slouken@1895
   955
slouken@1895
   956
    /* Allocate the empty map */
slouken@1920
   957
    map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
slouken@1895
   958
    if (map == NULL) {
slouken@1895
   959
        SDL_OutOfMemory();
slouken@1895
   960
        return (NULL);
slouken@1895
   961
    }
slouken@2267
   962
    map->info.r = 0xFF;
slouken@2267
   963
    map->info.g = 0xFF;
slouken@2267
   964
    map->info.b = 0xFF;
slouken@2267
   965
    map->info.a = 0xFF;
slouken@1895
   966
slouken@1895
   967
    /* It's ready to go */
slouken@1895
   968
    return (map);
slouken@0
   969
}
slouken@1895
   970
slouken@1895
   971
void
slouken@1895
   972
SDL_InvalidateMap(SDL_BlitMap * map)
slouken@0
   973
{
slouken@1895
   974
    if (!map) {
slouken@1895
   975
        return;
slouken@1895
   976
    }
slouken@6222
   977
    if (map->dst) {
slouken@6222
   978
        /* Release our reference to the surface - see the note below */
slouken@6222
   979
        if (--map->dst->refcount <= 0) {
slouken@6222
   980
            SDL_FreeSurface(map->dst);
slouken@6222
   981
        }
slouken@6222
   982
    }
slouken@1895
   983
    map->dst = NULL;
slouken@6166
   984
    map->src_palette_version = 0;
slouken@6166
   985
    map->dst_palette_version = 0;
slouken@7719
   986
    SDL_free(map->info.table);
slouken@7719
   987
    map->info.table = NULL;
slouken@1895
   988
}
slouken@2735
   989
slouken@1895
   990
int
slouken@1895
   991
SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
slouken@1895
   992
{
slouken@1895
   993
    SDL_PixelFormat *srcfmt;
slouken@1895
   994
    SDL_PixelFormat *dstfmt;
slouken@1895
   995
    SDL_BlitMap *map;
slouken@0
   996
slouken@1895
   997
    /* Clear out any previous mapping */
slouken@1895
   998
    map = src->map;
slouken@1895
   999
    if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
slouken@1895
  1000
        SDL_UnRLESurface(src, 1);
slouken@1895
  1001
    }
slouken@1895
  1002
    SDL_InvalidateMap(map);
slouken@0
  1003
slouken@1895
  1004
    /* Figure out what kind of mapping we're doing */
slouken@1895
  1005
    map->identity = 0;
slouken@1895
  1006
    srcfmt = src->format;
slouken@1895
  1007
    dstfmt = dst->format;
slouken@5288
  1008
    if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
slouken@5288
  1009
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
  1010
            /* Palette --> Palette */
slouken@2267
  1011
            map->info.table =
slouken@1895
  1012
                Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
slouken@1895
  1013
            if (!map->identity) {
slouken@2267
  1014
                if (map->info.table == NULL) {
slouken@1895
  1015
                    return (-1);
slouken@1895
  1016
                }
slouken@1895
  1017
            }
slouken@1895
  1018
            if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
slouken@1895
  1019
                map->identity = 0;
slouken@5288
  1020
        } else {
slouken@1895
  1021
            /* Palette --> BitField */
slouken@2267
  1022
            map->info.table =
slouken@2267
  1023
                Map1toN(srcfmt, src->map->info.r, src->map->info.g,
slouken@2267
  1024
                        src->map->info.b, src->map->info.a, dstfmt);
slouken@2267
  1025
            if (map->info.table == NULL) {
slouken@1895
  1026
                return (-1);
slouken@1895
  1027
            }
slouken@1895
  1028
        }
slouken@5288
  1029
    } else {
slouken@5288
  1030
        if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
slouken@1895
  1031
            /* BitField --> Palette */
slouken@2267
  1032
            map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
slouken@1895
  1033
            if (!map->identity) {
slouken@2267
  1034
                if (map->info.table == NULL) {
slouken@1895
  1035
                    return (-1);
slouken@1895
  1036
                }
slouken@1895
  1037
            }
slouken@1895
  1038
            map->identity = 0;  /* Don't optimize to copy */
slouken@5288
  1039
        } else {
slouken@1895
  1040
            /* BitField --> BitField */
slouken@5288
  1041
            if (srcfmt == dstfmt) {
slouken@1895
  1042
                map->identity = 1;
slouken@5288
  1043
            }
slouken@1895
  1044
        }
slouken@1895
  1045
    }
slouken@0
  1046
slouken@1895
  1047
    map->dst = dst;
slouken@5288
  1048
slouken@6222
  1049
    if (map->dst) {
slouken@6222
  1050
        /* Keep a reference to this surface so it doesn't get deleted
slouken@6222
  1051
           while we're still pointing at it.
slouken@6222
  1052
slouken@6222
  1053
           A better method would be for the destination surface to keep
slouken@7191
  1054
           track of surfaces that are mapped to it and automatically
slouken@6222
  1055
           invalidate them when it is freed, but this will do for now.
slouken@6222
  1056
        */
slouken@6222
  1057
        ++map->dst->refcount;
slouken@6222
  1058
    }
slouken@6222
  1059
slouken@5288
  1060
    if (dstfmt->palette) {
slouken@6166
  1061
        map->dst_palette_version = dstfmt->palette->version;
slouken@5288
  1062
    } else {
slouken@6166
  1063
        map->dst_palette_version = 0;
slouken@6166
  1064
    }
slouken@6166
  1065
slouken@6166
  1066
    if (srcfmt->palette) {
slouken@6166
  1067
        map->src_palette_version = srcfmt->palette->version;
slouken@6166
  1068
    } else {
slouken@6166
  1069
        map->src_palette_version = 0;
slouken@5288
  1070
    }
slouken@0
  1071
slouken@1895
  1072
    /* Choose your blitters wisely */
slouken@1895
  1073
    return (SDL_CalculateBlit(src));
slouken@0
  1074
}
slouken@1895
  1075
slouken@1895
  1076
void
slouken@1895
  1077
SDL_FreeBlitMap(SDL_BlitMap * map)
slouken@0
  1078
{
slouken@1895
  1079
    if (map) {
slouken@1895
  1080
        SDL_InvalidateMap(map);
slouken@1895
  1081
        SDL_free(map);
slouken@1895
  1082
    }
slouken@0
  1083
}
slouken@1895
  1084
slouken@5466
  1085
void
slouken@5466
  1086
SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
slouken@5466
  1087
{
slouken@5466
  1088
    int i;
slouken@7191
  1089
aschiffler@7151
  1090
    /* Input validation */
aschiffler@7151
  1091
    if (gamma < 0.0f ) {
aschiffler@7151
  1092
      SDL_InvalidParamError("gamma");
aschiffler@7151
  1093
      return;
aschiffler@7151
  1094
    }
aschiffler@7151
  1095
    if (ramp == NULL) {
aschiffler@7151
  1096
      SDL_InvalidParamError("ramp");
aschiffler@7151
  1097
      return;
aschiffler@7151
  1098
    }
slouken@5466
  1099
slouken@5466
  1100
    /* 0.0 gamma is all black */
aschiffler@7151
  1101
    if (gamma == 0.0f) {
slouken@5466
  1102
        for (i = 0; i < 256; ++i) {
slouken@5466
  1103
            ramp[i] = 0;
slouken@5466
  1104
        }
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: */