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