src/video/SDL_pixels.c
author Cameron Gutman <cameron.gutman@gmail.com>
Mon, 24 Jun 2019 21:08:26 -0700
changeset 12944 886b79177762
parent 12503 806492103856
permissions -rw-r--r--
Allow hotplugging joysticks without udev
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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 
    35 static Uint8 lookup_0[] = {
    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
    37 };
    38 
    39 static Uint8 lookup_1[] = {
    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
    41 };
    42 
    43 static Uint8 lookup_2[] = {
    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
    45 };
    46 
    47 static Uint8 lookup_3[] = {
    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
    49 };
    50 
    51 static Uint8 lookup_4[] = {
    52 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
    53 };
    54 
    55 static Uint8 lookup_5[] = {
    56 0, 36, 72, 109, 145, 182, 218, 255
    57 };
    58 
    59 static Uint8 lookup_6[] = {
    60 0, 85, 170, 255
    61 };
    62 
    63 static Uint8 lookup_7[] = {
    64 0, 255
    65 };
    66 
    67 static Uint8 lookup_8[] = {
    68 255
    69 };
    70 
    71 Uint8* 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 
    85 const char*
    86 SDL_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 
   133 SDL_bool
   134 SDL_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 
   292 Uint32
   293 SDL_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     /* fallthrough */
   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         if (Rmask == 0x003F &&
   407             Gmask == 0x07C0 &&
   408             Bmask == 0xF800 &&
   409             Amask == 0x0000) {
   410             /* Technically this would be BGR556, but Witek says this works in bug 3158 */
   411             return SDL_PIXELFORMAT_RGB565;
   412         }
   413         break;
   414     case 24:
   415         switch (Rmask) {
   416         case 0:
   417         case 0x00FF0000:
   418 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   419             return SDL_PIXELFORMAT_RGB24;
   420 #else
   421             return SDL_PIXELFORMAT_BGR24;
   422 #endif
   423         case 0x000000FF:
   424 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   425             return SDL_PIXELFORMAT_BGR24;
   426 #else
   427             return SDL_PIXELFORMAT_RGB24;
   428 #endif
   429         }
   430     case 32:
   431         if (Rmask == 0) {
   432             return SDL_PIXELFORMAT_RGB888;
   433         }
   434         if (Rmask == 0x00FF0000 &&
   435             Gmask == 0x0000FF00 &&
   436             Bmask == 0x000000FF &&
   437             Amask == 0x00000000) {
   438             return SDL_PIXELFORMAT_RGB888;
   439         }
   440         if (Rmask == 0xFF000000 &&
   441             Gmask == 0x00FF0000 &&
   442             Bmask == 0x0000FF00 &&
   443             Amask == 0x00000000) {
   444             return SDL_PIXELFORMAT_RGBX8888;
   445         }
   446         if (Rmask == 0x000000FF &&
   447             Gmask == 0x0000FF00 &&
   448             Bmask == 0x00FF0000 &&
   449             Amask == 0x00000000) {
   450             return SDL_PIXELFORMAT_BGR888;
   451         }
   452         if (Rmask == 0x0000FF00 &&
   453             Gmask == 0x00FF0000 &&
   454             Bmask == 0xFF000000 &&
   455             Amask == 0x00000000) {
   456             return SDL_PIXELFORMAT_BGRX8888;
   457         }
   458         if (Rmask == 0x00FF0000 &&
   459             Gmask == 0x0000FF00 &&
   460             Bmask == 0x000000FF &&
   461             Amask == 0xFF000000) {
   462             return SDL_PIXELFORMAT_ARGB8888;
   463         }
   464         if (Rmask == 0xFF000000 &&
   465             Gmask == 0x00FF0000 &&
   466             Bmask == 0x0000FF00 &&
   467             Amask == 0x000000FF) {
   468             return SDL_PIXELFORMAT_RGBA8888;
   469         }
   470         if (Rmask == 0x000000FF &&
   471             Gmask == 0x0000FF00 &&
   472             Bmask == 0x00FF0000 &&
   473             Amask == 0xFF000000) {
   474             return SDL_PIXELFORMAT_ABGR8888;
   475         }
   476         if (Rmask == 0x0000FF00 &&
   477             Gmask == 0x00FF0000 &&
   478             Bmask == 0xFF000000 &&
   479             Amask == 0x000000FF) {
   480             return SDL_PIXELFORMAT_BGRA8888;
   481         }
   482         if (Rmask == 0x3FF00000 &&
   483             Gmask == 0x000FFC00 &&
   484             Bmask == 0x000003FF &&
   485             Amask == 0xC0000000) {
   486             return SDL_PIXELFORMAT_ARGB2101010;
   487         }
   488     }
   489     return SDL_PIXELFORMAT_UNKNOWN;
   490 }
   491 
   492 static SDL_PixelFormat *formats;
   493 static SDL_SpinLock formats_lock = 0;
   494 
   495 SDL_PixelFormat *
   496 SDL_AllocFormat(Uint32 pixel_format)
   497 {
   498     SDL_PixelFormat *format;
   499 
   500     SDL_AtomicLock(&formats_lock);
   501 
   502     /* Look it up in our list of previously allocated formats */
   503     for (format = formats; format; format = format->next) {
   504         if (pixel_format == format->format) {
   505             ++format->refcount;
   506             SDL_AtomicUnlock(&formats_lock);
   507             return format;
   508         }
   509     }
   510 
   511     /* Allocate an empty pixel format structure, and initialize it */
   512     format = SDL_malloc(sizeof(*format));
   513     if (format == NULL) {
   514         SDL_AtomicUnlock(&formats_lock);
   515         SDL_OutOfMemory();
   516         return NULL;
   517     }
   518     if (SDL_InitFormat(format, pixel_format) < 0) {
   519         SDL_AtomicUnlock(&formats_lock);
   520         SDL_free(format);
   521         SDL_InvalidParamError("format");
   522         return NULL;
   523     }
   524 
   525     if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
   526         /* Cache the RGB formats */
   527         format->next = formats;
   528         formats = format;
   529     }
   530 
   531     SDL_AtomicUnlock(&formats_lock);
   532 
   533     return format;
   534 }
   535 
   536 int
   537 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
   538 {
   539     int bpp;
   540     Uint32 Rmask, Gmask, Bmask, Amask;
   541     Uint32 mask;
   542 
   543     if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
   544                                     &Rmask, &Gmask, &Bmask, &Amask)) {
   545         return -1;
   546     }
   547 
   548     /* Set up the format */
   549     SDL_zerop(format);
   550     format->format = pixel_format;
   551     format->BitsPerPixel = bpp;
   552     format->BytesPerPixel = (bpp + 7) / 8;
   553 
   554     format->Rmask = Rmask;
   555     format->Rshift = 0;
   556     format->Rloss = 8;
   557     if (Rmask) {
   558         for (mask = Rmask; !(mask & 0x01); mask >>= 1)
   559             ++format->Rshift;
   560         for (; (mask & 0x01); mask >>= 1)
   561             --format->Rloss;
   562     }
   563 
   564     format->Gmask = Gmask;
   565     format->Gshift = 0;
   566     format->Gloss = 8;
   567     if (Gmask) {
   568         for (mask = Gmask; !(mask & 0x01); mask >>= 1)
   569             ++format->Gshift;
   570         for (; (mask & 0x01); mask >>= 1)
   571             --format->Gloss;
   572     }
   573 
   574     format->Bmask = Bmask;
   575     format->Bshift = 0;
   576     format->Bloss = 8;
   577     if (Bmask) {
   578         for (mask = Bmask; !(mask & 0x01); mask >>= 1)
   579             ++format->Bshift;
   580         for (; (mask & 0x01); mask >>= 1)
   581             --format->Bloss;
   582     }
   583 
   584     format->Amask = Amask;
   585     format->Ashift = 0;
   586     format->Aloss = 8;
   587     if (Amask) {
   588         for (mask = Amask; !(mask & 0x01); mask >>= 1)
   589             ++format->Ashift;
   590         for (; (mask & 0x01); mask >>= 1)
   591             --format->Aloss;
   592     }
   593 
   594     format->palette = NULL;
   595     format->refcount = 1;
   596     format->next = NULL;
   597 
   598     return 0;
   599 }
   600 
   601 void
   602 SDL_FreeFormat(SDL_PixelFormat *format)
   603 {
   604     SDL_PixelFormat *prev;
   605 
   606     if (!format) {
   607         SDL_InvalidParamError("format");
   608         return;
   609     }
   610 
   611     SDL_AtomicLock(&formats_lock);
   612 
   613     if (--format->refcount > 0) {
   614         SDL_AtomicUnlock(&formats_lock);
   615         return;
   616     }
   617 
   618     /* Remove this format from our list */
   619     if (format == formats) {
   620         formats = format->next;
   621     } else if (formats) {
   622         for (prev = formats; prev->next; prev = prev->next) {
   623             if (prev->next == format) {
   624                 prev->next = format->next;
   625                 break;
   626             }
   627         }
   628     }
   629 
   630     SDL_AtomicUnlock(&formats_lock);
   631 
   632     if (format->palette) {
   633         SDL_FreePalette(format->palette);
   634     }
   635     SDL_free(format);
   636 }
   637 
   638 SDL_Palette *
   639 SDL_AllocPalette(int ncolors)
   640 {
   641     SDL_Palette *palette;
   642 
   643     /* Input validation */
   644     if (ncolors < 1) {
   645       SDL_InvalidParamError("ncolors");
   646       return NULL;
   647     }
   648 
   649     palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
   650     if (!palette) {
   651         SDL_OutOfMemory();
   652         return NULL;
   653     }
   654     palette->colors =
   655         (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
   656     if (!palette->colors) {
   657         SDL_free(palette);
   658         return NULL;
   659     }
   660     palette->ncolors = ncolors;
   661     palette->version = 1;
   662     palette->refcount = 1;
   663 
   664     SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
   665 
   666     return palette;
   667 }
   668 
   669 int
   670 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
   671 {
   672     if (!format) {
   673         return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
   674     }
   675 
   676     if (palette && palette->ncolors > (1 << format->BitsPerPixel)) {
   677         return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
   678     }
   679 
   680     if (format->palette == palette) {
   681         return 0;
   682     }
   683 
   684     if (format->palette) {
   685         SDL_FreePalette(format->palette);
   686     }
   687 
   688     format->palette = palette;
   689 
   690     if (format->palette) {
   691         ++format->palette->refcount;
   692     }
   693 
   694     return 0;
   695 }
   696 
   697 int
   698 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
   699                      int firstcolor, int ncolors)
   700 {
   701     int status = 0;
   702 
   703     /* Verify the parameters */
   704     if (!palette) {
   705         return -1;
   706     }
   707     if (ncolors > (palette->ncolors - firstcolor)) {
   708         ncolors = (palette->ncolors - firstcolor);
   709         status = -1;
   710     }
   711 
   712     if (colors != (palette->colors + firstcolor)) {
   713         SDL_memcpy(palette->colors + firstcolor, colors,
   714                    ncolors * sizeof(*colors));
   715     }
   716     ++palette->version;
   717     if (!palette->version) {
   718         palette->version = 1;
   719     }
   720 
   721     return status;
   722 }
   723 
   724 void
   725 SDL_FreePalette(SDL_Palette * palette)
   726 {
   727     if (!palette) {
   728         SDL_InvalidParamError("palette");
   729         return;
   730     }
   731     if (--palette->refcount > 0) {
   732         return;
   733     }
   734     SDL_free(palette->colors);
   735     SDL_free(palette);
   736 }
   737 
   738 /*
   739  * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
   740  */
   741 void
   742 SDL_DitherColors(SDL_Color * colors, int bpp)
   743 {
   744     int i;
   745     if (bpp != 8)
   746         return;                 /* only 8bpp supported right now */
   747 
   748     for (i = 0; i < 256; i++) {
   749         int r, g, b;
   750         /* map each bit field to the full [0, 255] interval,
   751            so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
   752         r = i & 0xe0;
   753         r |= r >> 3 | r >> 6;
   754         colors[i].r = r;
   755         g = (i << 3) & 0xe0;
   756         g |= g >> 3 | g >> 6;
   757         colors[i].g = g;
   758         b = i & 0x3;
   759         b |= b << 2;
   760         b |= b << 4;
   761         colors[i].b = b;
   762         colors[i].a = SDL_ALPHA_OPAQUE;
   763     }
   764 }
   765 
   766 /*
   767  * Match an RGB value to a particular palette index
   768  */
   769 Uint8
   770 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   771 {
   772     /* Do colorspace distance matching */
   773     unsigned int smallest;
   774     unsigned int distance;
   775     int rd, gd, bd, ad;
   776     int i;
   777     Uint8 pixel = 0;
   778 
   779     smallest = ~0;
   780     for (i = 0; i < pal->ncolors; ++i) {
   781         rd = pal->colors[i].r - r;
   782         gd = pal->colors[i].g - g;
   783         bd = pal->colors[i].b - b;
   784         ad = pal->colors[i].a - a;
   785         distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
   786         if (distance < smallest) {
   787             pixel = i;
   788             if (distance == 0) {        /* Perfect match! */
   789                 break;
   790             }
   791             smallest = distance;
   792         }
   793     }
   794     return (pixel);
   795 }
   796 
   797 /* Find the opaque pixel value corresponding to an RGB triple */
   798 Uint32
   799 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
   800 {
   801     if (format->palette == NULL) {
   802         return (r >> format->Rloss) << format->Rshift
   803             | (g >> format->Gloss) << format->Gshift
   804             | (b >> format->Bloss) << format->Bshift | format->Amask;
   805     } else {
   806         return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
   807     }
   808 }
   809 
   810 /* Find the pixel value corresponding to an RGBA quadruple */
   811 Uint32
   812 SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
   813             Uint8 a)
   814 {
   815     if (format->palette == NULL) {
   816         return (r >> format->Rloss) << format->Rshift
   817             | (g >> format->Gloss) << format->Gshift
   818             | (b >> format->Bloss) << format->Bshift
   819             | ((a >> format->Aloss) << format->Ashift & format->Amask);
   820     } else {
   821         return SDL_FindColor(format->palette, r, g, b, a);
   822     }
   823 }
   824 
   825 void
   826 SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
   827            Uint8 * b)
   828 {
   829     if (format->palette == NULL) {
   830         unsigned v;
   831         v = (pixel & format->Rmask) >> format->Rshift;
   832         *r = SDL_expand_byte[format->Rloss][v];
   833         v = (pixel & format->Gmask) >> format->Gshift;
   834         *g = SDL_expand_byte[format->Gloss][v];
   835         v = (pixel & format->Bmask) >> format->Bshift;
   836         *b = SDL_expand_byte[format->Bloss][v];
   837     } else {
   838         if (pixel < (unsigned)format->palette->ncolors) {
   839             *r = format->palette->colors[pixel].r;
   840             *g = format->palette->colors[pixel].g;
   841             *b = format->palette->colors[pixel].b;
   842         } else {
   843             *r = *g = *b = 0;
   844         }
   845     }
   846 }
   847 
   848 void
   849 SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
   850             Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
   851 {
   852     if (format->palette == NULL) {
   853         unsigned v;
   854         v = (pixel & format->Rmask) >> format->Rshift;
   855         *r = SDL_expand_byte[format->Rloss][v];
   856         v = (pixel & format->Gmask) >> format->Gshift;
   857         *g = SDL_expand_byte[format->Gloss][v];
   858         v = (pixel & format->Bmask) >> format->Bshift;
   859         *b = SDL_expand_byte[format->Bloss][v];
   860         v = (pixel & format->Amask) >> format->Ashift;
   861         *a = SDL_expand_byte[format->Aloss][v];
   862     } else {
   863         if (pixel < (unsigned)format->palette->ncolors) {
   864             *r = format->palette->colors[pixel].r;
   865             *g = format->palette->colors[pixel].g;
   866             *b = format->palette->colors[pixel].b;
   867             *a = format->palette->colors[pixel].a;
   868         } else {
   869             *r = *g = *b = *a = 0;
   870         }
   871     }
   872 }
   873 
   874 /* Map from Palette to Palette */
   875 static Uint8 *
   876 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
   877 {
   878     Uint8 *map;
   879     int i;
   880 
   881     if (identical) {
   882         if (src->ncolors <= dst->ncolors) {
   883             /* If an identical palette, no need to map */
   884             if (src == dst
   885                 ||
   886                 (SDL_memcmp
   887                  (src->colors, dst->colors,
   888                   src->ncolors * sizeof(SDL_Color)) == 0)) {
   889                 *identical = 1;
   890                 return (NULL);
   891             }
   892         }
   893         *identical = 0;
   894     }
   895     map = (Uint8 *) SDL_malloc(src->ncolors);
   896     if (map == NULL) {
   897         SDL_OutOfMemory();
   898         return (NULL);
   899     }
   900     for (i = 0; i < src->ncolors; ++i) {
   901         map[i] = SDL_FindColor(dst,
   902                                src->colors[i].r, src->colors[i].g,
   903                                src->colors[i].b, src->colors[i].a);
   904     }
   905     return (map);
   906 }
   907 
   908 /* Map from Palette to BitField */
   909 static Uint8 *
   910 Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
   911         SDL_PixelFormat * dst)
   912 {
   913     Uint8 *map;
   914     int i;
   915     int bpp;
   916     SDL_Palette *pal = src->palette;
   917 
   918     bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
   919     map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
   920     if (map == NULL) {
   921         SDL_OutOfMemory();
   922         return (NULL);
   923     }
   924 
   925     /* We memory copy to the pixel map so the endianness is preserved */
   926     for (i = 0; i < pal->ncolors; ++i) {
   927         Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
   928         Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
   929         Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
   930         Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
   931         ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
   932     }
   933     return (map);
   934 }
   935 
   936 /* Map from BitField to Dithered-Palette to Palette */
   937 static Uint8 *
   938 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
   939 {
   940     /* Generate a 256 color dither palette */
   941     SDL_Palette dithered;
   942     SDL_Color colors[256];
   943     SDL_Palette *pal = dst->palette;
   944 
   945     dithered.ncolors = 256;
   946     SDL_DitherColors(colors, 8);
   947     dithered.colors = colors;
   948     return (Map1to1(&dithered, pal, identical));
   949 }
   950 
   951 SDL_BlitMap *
   952 SDL_AllocBlitMap(void)
   953 {
   954     SDL_BlitMap *map;
   955 
   956     /* Allocate the empty map */
   957     map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
   958     if (map == NULL) {
   959         SDL_OutOfMemory();
   960         return (NULL);
   961     }
   962     map->info.r = 0xFF;
   963     map->info.g = 0xFF;
   964     map->info.b = 0xFF;
   965     map->info.a = 0xFF;
   966 
   967     /* It's ready to go */
   968     return (map);
   969 }
   970 
   971 void
   972 SDL_InvalidateMap(SDL_BlitMap * map)
   973 {
   974     if (!map) {
   975         return;
   976     }
   977     if (map->dst) {
   978         /* Release our reference to the surface - see the note below */
   979         if (--map->dst->refcount <= 0) {
   980             SDL_FreeSurface(map->dst);
   981         }
   982     }
   983     map->dst = NULL;
   984     map->src_palette_version = 0;
   985     map->dst_palette_version = 0;
   986     SDL_free(map->info.table);
   987     map->info.table = NULL;
   988 }
   989 
   990 int
   991 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
   992 {
   993     SDL_PixelFormat *srcfmt;
   994     SDL_PixelFormat *dstfmt;
   995     SDL_BlitMap *map;
   996 
   997     /* Clear out any previous mapping */
   998     map = src->map;
   999     if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
  1000         SDL_UnRLESurface(src, 1);
  1001     }
  1002     SDL_InvalidateMap(map);
  1003 
  1004     /* Figure out what kind of mapping we're doing */
  1005     map->identity = 0;
  1006     srcfmt = src->format;
  1007     dstfmt = dst->format;
  1008     if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
  1009         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1010             /* Palette --> Palette */
  1011             map->info.table =
  1012                 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
  1013             if (!map->identity) {
  1014                 if (map->info.table == NULL) {
  1015                     return (-1);
  1016                 }
  1017             }
  1018             if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
  1019                 map->identity = 0;
  1020         } else {
  1021             /* Palette --> BitField */
  1022             map->info.table =
  1023                 Map1toN(srcfmt, src->map->info.r, src->map->info.g,
  1024                         src->map->info.b, src->map->info.a, dstfmt);
  1025             if (map->info.table == NULL) {
  1026                 return (-1);
  1027             }
  1028         }
  1029     } else {
  1030         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1031             /* BitField --> Palette */
  1032             map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
  1033             if (!map->identity) {
  1034                 if (map->info.table == NULL) {
  1035                     return (-1);
  1036                 }
  1037             }
  1038             map->identity = 0;  /* Don't optimize to copy */
  1039         } else {
  1040             /* BitField --> BitField */
  1041             if (srcfmt == dstfmt) {
  1042                 map->identity = 1;
  1043             }
  1044         }
  1045     }
  1046 
  1047     map->dst = dst;
  1048 
  1049     if (map->dst) {
  1050         /* Keep a reference to this surface so it doesn't get deleted
  1051            while we're still pointing at it.
  1052 
  1053            A better method would be for the destination surface to keep
  1054            track of surfaces that are mapped to it and automatically
  1055            invalidate them when it is freed, but this will do for now.
  1056         */
  1057         ++map->dst->refcount;
  1058     }
  1059 
  1060     if (dstfmt->palette) {
  1061         map->dst_palette_version = dstfmt->palette->version;
  1062     } else {
  1063         map->dst_palette_version = 0;
  1064     }
  1065 
  1066     if (srcfmt->palette) {
  1067         map->src_palette_version = srcfmt->palette->version;
  1068     } else {
  1069         map->src_palette_version = 0;
  1070     }
  1071 
  1072     /* Choose your blitters wisely */
  1073     return (SDL_CalculateBlit(src));
  1074 }
  1075 
  1076 void
  1077 SDL_FreeBlitMap(SDL_BlitMap * map)
  1078 {
  1079     if (map) {
  1080         SDL_InvalidateMap(map);
  1081         SDL_free(map);
  1082     }
  1083 }
  1084 
  1085 void
  1086 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
  1087 {
  1088     int i;
  1089 
  1090     /* Input validation */
  1091     if (gamma < 0.0f ) {
  1092       SDL_InvalidParamError("gamma");
  1093       return;
  1094     }
  1095     if (ramp == NULL) {
  1096       SDL_InvalidParamError("ramp");
  1097       return;
  1098     }
  1099 
  1100     /* 0.0 gamma is all black */
  1101     if (gamma == 0.0f) {
  1102         SDL_memset(ramp, 0, 256 * sizeof(Uint16));
  1103         return;
  1104     } else if (gamma == 1.0f) {
  1105         /* 1.0 gamma is identity */
  1106         for (i = 0; i < 256; ++i) {
  1107             ramp[i] = (i << 8) | i;
  1108         }
  1109         return;
  1110     } else {
  1111         /* Calculate a real gamma ramp */
  1112         int value;
  1113         gamma = 1.0f / gamma;
  1114         for (i = 0; i < 256; ++i) {
  1115             value =
  1116                 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
  1117             if (value > 65535) {
  1118                 value = 65535;
  1119             }
  1120             ramp[i] = (Uint16) value;
  1121         }
  1122     }
  1123 }
  1124 
  1125 /* vi: set ts=4 sw=4 expandtab: */