src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 30 Jan 2018 18:08:34 -0800
changeset 11839 971881e55d61
parent 11811 5d94cb6b24d3
child 11877 2a25e8690229
permissions -rw-r--r--
Fixed ISO C99 compatibility
SDL now builds with gcc 7.2 with the following command line options:
-Wall -pedantic-errors -Wno-deprecated-declarations -Wno-overlength-strings --std=c99
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2018 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 
   494 SDL_PixelFormat *
   495 SDL_AllocFormat(Uint32 pixel_format)
   496 {
   497     SDL_PixelFormat *format;
   498 
   499     /* Look it up in our list of previously allocated formats */
   500     for (format = formats; format; format = format->next) {
   501         if (pixel_format == format->format) {
   502             ++format->refcount;
   503             return format;
   504         }
   505     }
   506 
   507     /* Allocate an empty pixel format structure, and initialize it */
   508     format = SDL_malloc(sizeof(*format));
   509     if (format == NULL) {
   510         SDL_OutOfMemory();
   511         return NULL;
   512     }
   513     if (SDL_InitFormat(format, pixel_format) < 0) {
   514         SDL_free(format);
   515         SDL_InvalidParamError("format");
   516         return NULL;
   517     }
   518 
   519     if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
   520         /* Cache the RGB formats */
   521         format->next = formats;
   522         formats = format;
   523     }
   524     return format;
   525 }
   526 
   527 int
   528 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
   529 {
   530     int bpp;
   531     Uint32 Rmask, Gmask, Bmask, Amask;
   532     Uint32 mask;
   533 
   534     if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
   535                                     &Rmask, &Gmask, &Bmask, &Amask)) {
   536         return -1;
   537     }
   538 
   539     /* Set up the format */
   540     SDL_zerop(format);
   541     format->format = pixel_format;
   542     format->BitsPerPixel = bpp;
   543     format->BytesPerPixel = (bpp + 7) / 8;
   544 
   545     format->Rmask = Rmask;
   546     format->Rshift = 0;
   547     format->Rloss = 8;
   548     if (Rmask) {
   549         for (mask = Rmask; !(mask & 0x01); mask >>= 1)
   550             ++format->Rshift;
   551         for (; (mask & 0x01); mask >>= 1)
   552             --format->Rloss;
   553     }
   554 
   555     format->Gmask = Gmask;
   556     format->Gshift = 0;
   557     format->Gloss = 8;
   558     if (Gmask) {
   559         for (mask = Gmask; !(mask & 0x01); mask >>= 1)
   560             ++format->Gshift;
   561         for (; (mask & 0x01); mask >>= 1)
   562             --format->Gloss;
   563     }
   564 
   565     format->Bmask = Bmask;
   566     format->Bshift = 0;
   567     format->Bloss = 8;
   568     if (Bmask) {
   569         for (mask = Bmask; !(mask & 0x01); mask >>= 1)
   570             ++format->Bshift;
   571         for (; (mask & 0x01); mask >>= 1)
   572             --format->Bloss;
   573     }
   574 
   575     format->Amask = Amask;
   576     format->Ashift = 0;
   577     format->Aloss = 8;
   578     if (Amask) {
   579         for (mask = Amask; !(mask & 0x01); mask >>= 1)
   580             ++format->Ashift;
   581         for (; (mask & 0x01); mask >>= 1)
   582             --format->Aloss;
   583     }
   584 
   585     format->palette = NULL;
   586     format->refcount = 1;
   587     format->next = NULL;
   588 
   589     return 0;
   590 }
   591 
   592 void
   593 SDL_FreeFormat(SDL_PixelFormat *format)
   594 {
   595     SDL_PixelFormat *prev;
   596 
   597     if (!format) {
   598         SDL_InvalidParamError("format");
   599         return;
   600     }
   601     if (--format->refcount > 0) {
   602         return;
   603     }
   604 
   605     /* Remove this format from our list */
   606     if (format == formats) {
   607         formats = format->next;
   608     } else if (formats) {
   609         for (prev = formats; prev->next; prev = prev->next) {
   610             if (prev->next == format) {
   611                 prev->next = format->next;
   612                 break;
   613             }
   614         }
   615     }
   616 
   617     if (format->palette) {
   618         SDL_FreePalette(format->palette);
   619     }
   620     SDL_free(format);
   621 }
   622 
   623 SDL_Palette *
   624 SDL_AllocPalette(int ncolors)
   625 {
   626     SDL_Palette *palette;
   627 
   628     /* Input validation */
   629     if (ncolors < 1) {
   630       SDL_InvalidParamError("ncolors");
   631       return NULL;
   632     }
   633 
   634     palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
   635     if (!palette) {
   636         SDL_OutOfMemory();
   637         return NULL;
   638     }
   639     palette->colors =
   640         (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
   641     if (!palette->colors) {
   642         SDL_free(palette);
   643         return NULL;
   644     }
   645     palette->ncolors = ncolors;
   646     palette->version = 1;
   647     palette->refcount = 1;
   648 
   649     SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
   650 
   651     return palette;
   652 }
   653 
   654 int
   655 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
   656 {
   657     if (!format) {
   658         return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
   659     }
   660 
   661     if (palette && palette->ncolors > (1 << format->BitsPerPixel)) {
   662         return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
   663     }
   664 
   665     if (format->palette == palette) {
   666         return 0;
   667     }
   668 
   669     if (format->palette) {
   670         SDL_FreePalette(format->palette);
   671     }
   672 
   673     format->palette = palette;
   674 
   675     if (format->palette) {
   676         ++format->palette->refcount;
   677     }
   678 
   679     return 0;
   680 }
   681 
   682 int
   683 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
   684                      int firstcolor, int ncolors)
   685 {
   686     int status = 0;
   687 
   688     /* Verify the parameters */
   689     if (!palette) {
   690         return -1;
   691     }
   692     if (ncolors > (palette->ncolors - firstcolor)) {
   693         ncolors = (palette->ncolors - firstcolor);
   694         status = -1;
   695     }
   696 
   697     if (colors != (palette->colors + firstcolor)) {
   698         SDL_memcpy(palette->colors + firstcolor, colors,
   699                    ncolors * sizeof(*colors));
   700     }
   701     ++palette->version;
   702     if (!palette->version) {
   703         palette->version = 1;
   704     }
   705 
   706     return status;
   707 }
   708 
   709 void
   710 SDL_FreePalette(SDL_Palette * palette)
   711 {
   712     if (!palette) {
   713         SDL_InvalidParamError("palette");
   714         return;
   715     }
   716     if (--palette->refcount > 0) {
   717         return;
   718     }
   719     SDL_free(palette->colors);
   720     SDL_free(palette);
   721 }
   722 
   723 /*
   724  * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
   725  */
   726 void
   727 SDL_DitherColors(SDL_Color * colors, int bpp)
   728 {
   729     int i;
   730     if (bpp != 8)
   731         return;                 /* only 8bpp supported right now */
   732 
   733     for (i = 0; i < 256; i++) {
   734         int r, g, b;
   735         /* map each bit field to the full [0, 255] interval,
   736            so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
   737         r = i & 0xe0;
   738         r |= r >> 3 | r >> 6;
   739         colors[i].r = r;
   740         g = (i << 3) & 0xe0;
   741         g |= g >> 3 | g >> 6;
   742         colors[i].g = g;
   743         b = i & 0x3;
   744         b |= b << 2;
   745         b |= b << 4;
   746         colors[i].b = b;
   747         colors[i].a = SDL_ALPHA_OPAQUE;
   748     }
   749 }
   750 
   751 /*
   752  * Match an RGB value to a particular palette index
   753  */
   754 Uint8
   755 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   756 {
   757     /* Do colorspace distance matching */
   758     unsigned int smallest;
   759     unsigned int distance;
   760     int rd, gd, bd, ad;
   761     int i;
   762     Uint8 pixel = 0;
   763 
   764     smallest = ~0;
   765     for (i = 0; i < pal->ncolors; ++i) {
   766         rd = pal->colors[i].r - r;
   767         gd = pal->colors[i].g - g;
   768         bd = pal->colors[i].b - b;
   769         ad = pal->colors[i].a - a;
   770         distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
   771         if (distance < smallest) {
   772             pixel = i;
   773             if (distance == 0) {        /* Perfect match! */
   774                 break;
   775             }
   776             smallest = distance;
   777         }
   778     }
   779     return (pixel);
   780 }
   781 
   782 /* Find the opaque pixel value corresponding to an RGB triple */
   783 Uint32
   784 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
   785 {
   786     if (format->palette == NULL) {
   787         return (r >> format->Rloss) << format->Rshift
   788             | (g >> format->Gloss) << format->Gshift
   789             | (b >> format->Bloss) << format->Bshift | format->Amask;
   790     } else {
   791         return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
   792     }
   793 }
   794 
   795 /* Find the pixel value corresponding to an RGBA quadruple */
   796 Uint32
   797 SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
   798             Uint8 a)
   799 {
   800     if (format->palette == NULL) {
   801         return (r >> format->Rloss) << format->Rshift
   802             | (g >> format->Gloss) << format->Gshift
   803             | (b >> format->Bloss) << format->Bshift
   804             | ((a >> format->Aloss) << format->Ashift & format->Amask);
   805     } else {
   806         return SDL_FindColor(format->palette, r, g, b, a);
   807     }
   808 }
   809 
   810 void
   811 SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
   812            Uint8 * b)
   813 {
   814     if (format->palette == NULL) {
   815         unsigned v;
   816         v = (pixel & format->Rmask) >> format->Rshift;
   817         *r = SDL_expand_byte[format->Rloss][v];
   818         v = (pixel & format->Gmask) >> format->Gshift;
   819         *g = SDL_expand_byte[format->Gloss][v];
   820         v = (pixel & format->Bmask) >> format->Bshift;
   821         *b = SDL_expand_byte[format->Bloss][v];
   822     } else {
   823         if (pixel < (unsigned)format->palette->ncolors) {
   824             *r = format->palette->colors[pixel].r;
   825             *g = format->palette->colors[pixel].g;
   826             *b = format->palette->colors[pixel].b;
   827         } else {
   828             *r = *g = *b = 0;
   829         }
   830     }
   831 }
   832 
   833 void
   834 SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
   835             Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
   836 {
   837     if (format->palette == NULL) {
   838         unsigned v;
   839         v = (pixel & format->Rmask) >> format->Rshift;
   840         *r = SDL_expand_byte[format->Rloss][v];
   841         v = (pixel & format->Gmask) >> format->Gshift;
   842         *g = SDL_expand_byte[format->Gloss][v];
   843         v = (pixel & format->Bmask) >> format->Bshift;
   844         *b = SDL_expand_byte[format->Bloss][v];
   845         v = (pixel & format->Amask) >> format->Ashift;
   846         *a = SDL_expand_byte[format->Aloss][v];
   847     } else {
   848         if (pixel < (unsigned)format->palette->ncolors) {
   849             *r = format->palette->colors[pixel].r;
   850             *g = format->palette->colors[pixel].g;
   851             *b = format->palette->colors[pixel].b;
   852             *a = format->palette->colors[pixel].a;
   853         } else {
   854             *r = *g = *b = *a = 0;
   855         }
   856     }
   857 }
   858 
   859 /* Map from Palette to Palette */
   860 static Uint8 *
   861 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
   862 {
   863     Uint8 *map;
   864     int i;
   865 
   866     if (identical) {
   867         if (src->ncolors <= dst->ncolors) {
   868             /* If an identical palette, no need to map */
   869             if (src == dst
   870                 ||
   871                 (SDL_memcmp
   872                  (src->colors, dst->colors,
   873                   src->ncolors * sizeof(SDL_Color)) == 0)) {
   874                 *identical = 1;
   875                 return (NULL);
   876             }
   877         }
   878         *identical = 0;
   879     }
   880     map = (Uint8 *) SDL_malloc(src->ncolors);
   881     if (map == NULL) {
   882         SDL_OutOfMemory();
   883         return (NULL);
   884     }
   885     for (i = 0; i < src->ncolors; ++i) {
   886         map[i] = SDL_FindColor(dst,
   887                                src->colors[i].r, src->colors[i].g,
   888                                src->colors[i].b, src->colors[i].a);
   889     }
   890     return (map);
   891 }
   892 
   893 /* Map from Palette to BitField */
   894 static Uint8 *
   895 Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
   896         SDL_PixelFormat * dst)
   897 {
   898     Uint8 *map;
   899     int i;
   900     int bpp;
   901     SDL_Palette *pal = src->palette;
   902 
   903     bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
   904     map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
   905     if (map == NULL) {
   906         SDL_OutOfMemory();
   907         return (NULL);
   908     }
   909 
   910     /* We memory copy to the pixel map so the endianness is preserved */
   911     for (i = 0; i < pal->ncolors; ++i) {
   912         Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
   913         Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
   914         Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
   915         Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
   916         ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
   917     }
   918     return (map);
   919 }
   920 
   921 /* Map from BitField to Dithered-Palette to Palette */
   922 static Uint8 *
   923 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
   924 {
   925     /* Generate a 256 color dither palette */
   926     SDL_Palette dithered;
   927     SDL_Color colors[256];
   928     SDL_Palette *pal = dst->palette;
   929 
   930     dithered.ncolors = 256;
   931     SDL_DitherColors(colors, 8);
   932     dithered.colors = colors;
   933     return (Map1to1(&dithered, pal, identical));
   934 }
   935 
   936 SDL_BlitMap *
   937 SDL_AllocBlitMap(void)
   938 {
   939     SDL_BlitMap *map;
   940 
   941     /* Allocate the empty map */
   942     map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
   943     if (map == NULL) {
   944         SDL_OutOfMemory();
   945         return (NULL);
   946     }
   947     map->info.r = 0xFF;
   948     map->info.g = 0xFF;
   949     map->info.b = 0xFF;
   950     map->info.a = 0xFF;
   951 
   952     /* It's ready to go */
   953     return (map);
   954 }
   955 
   956 void
   957 SDL_InvalidateMap(SDL_BlitMap * map)
   958 {
   959     if (!map) {
   960         return;
   961     }
   962     if (map->dst) {
   963         /* Release our reference to the surface - see the note below */
   964         if (--map->dst->refcount <= 0) {
   965             SDL_FreeSurface(map->dst);
   966         }
   967     }
   968     map->dst = NULL;
   969     map->src_palette_version = 0;
   970     map->dst_palette_version = 0;
   971     SDL_free(map->info.table);
   972     map->info.table = NULL;
   973 }
   974 
   975 int
   976 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
   977 {
   978     SDL_PixelFormat *srcfmt;
   979     SDL_PixelFormat *dstfmt;
   980     SDL_BlitMap *map;
   981 
   982     /* Clear out any previous mapping */
   983     map = src->map;
   984     if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
   985         SDL_UnRLESurface(src, 1);
   986     }
   987     SDL_InvalidateMap(map);
   988 
   989     /* Figure out what kind of mapping we're doing */
   990     map->identity = 0;
   991     srcfmt = src->format;
   992     dstfmt = dst->format;
   993     if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
   994         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
   995             /* Palette --> Palette */
   996             map->info.table =
   997                 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
   998             if (!map->identity) {
   999                 if (map->info.table == NULL) {
  1000                     return (-1);
  1001                 }
  1002             }
  1003             if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
  1004                 map->identity = 0;
  1005         } else {
  1006             /* Palette --> BitField */
  1007             map->info.table =
  1008                 Map1toN(srcfmt, src->map->info.r, src->map->info.g,
  1009                         src->map->info.b, src->map->info.a, dstfmt);
  1010             if (map->info.table == NULL) {
  1011                 return (-1);
  1012             }
  1013         }
  1014     } else {
  1015         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1016             /* BitField --> Palette */
  1017             map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
  1018             if (!map->identity) {
  1019                 if (map->info.table == NULL) {
  1020                     return (-1);
  1021                 }
  1022             }
  1023             map->identity = 0;  /* Don't optimize to copy */
  1024         } else {
  1025             /* BitField --> BitField */
  1026             if (srcfmt == dstfmt) {
  1027                 map->identity = 1;
  1028             }
  1029         }
  1030     }
  1031 
  1032     map->dst = dst;
  1033 
  1034     if (map->dst) {
  1035         /* Keep a reference to this surface so it doesn't get deleted
  1036            while we're still pointing at it.
  1037 
  1038            A better method would be for the destination surface to keep
  1039            track of surfaces that are mapped to it and automatically
  1040            invalidate them when it is freed, but this will do for now.
  1041         */
  1042         ++map->dst->refcount;
  1043     }
  1044 
  1045     if (dstfmt->palette) {
  1046         map->dst_palette_version = dstfmt->palette->version;
  1047     } else {
  1048         map->dst_palette_version = 0;
  1049     }
  1050 
  1051     if (srcfmt->palette) {
  1052         map->src_palette_version = srcfmt->palette->version;
  1053     } else {
  1054         map->src_palette_version = 0;
  1055     }
  1056 
  1057     /* Choose your blitters wisely */
  1058     return (SDL_CalculateBlit(src));
  1059 }
  1060 
  1061 void
  1062 SDL_FreeBlitMap(SDL_BlitMap * map)
  1063 {
  1064     if (map) {
  1065         SDL_InvalidateMap(map);
  1066         SDL_free(map);
  1067     }
  1068 }
  1069 
  1070 void
  1071 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
  1072 {
  1073     int i;
  1074 
  1075     /* Input validation */
  1076     if (gamma < 0.0f ) {
  1077       SDL_InvalidParamError("gamma");
  1078       return;
  1079     }
  1080     if (ramp == NULL) {
  1081       SDL_InvalidParamError("ramp");
  1082       return;
  1083     }
  1084 
  1085     /* 0.0 gamma is all black */
  1086     if (gamma == 0.0f) {
  1087         SDL_memset(ramp, 0, 256 * sizeof(Uint16));
  1088         return;
  1089     } else if (gamma == 1.0f) {
  1090         /* 1.0 gamma is identity */
  1091         for (i = 0; i < 256; ++i) {
  1092             ramp[i] = (i << 8) | i;
  1093         }
  1094         return;
  1095     } else {
  1096         /* Calculate a real gamma ramp */
  1097         int value;
  1098         gamma = 1.0f / gamma;
  1099         for (i = 0; i < 256; ++i) {
  1100             value =
  1101                 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
  1102             if (value > 65535) {
  1103                 value = 65535;
  1104             }
  1105             ramp[i] = (Uint16) value;
  1106         }
  1107     }
  1108 }
  1109 
  1110 /* vi: set ts=4 sw=4 expandtab: */