cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_pixels.c (31965B)


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