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