src/video/SDL_pixels.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 11:28:44 -0700
changeset 7776 d4a39491577f
parent 7719 31b5f9ff36ca
child 8093 b43765095a6f
permissions -rw-r--r--
Added the platform specific messagebox function to the video function list
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2013 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_config.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 #undef CASE
   126     default:
   127         return "SDL_PIXELFORMAT_UNKNOWN";
   128     }
   129 }
   130 
   131 SDL_bool
   132 SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask,
   133                            Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
   134 {
   135     Uint32 masks[4];
   136 
   137     /* This function doesn't work with FourCC pixel formats */
   138     if (SDL_ISPIXELFORMAT_FOURCC(format)) {
   139         SDL_SetError("FOURCC pixel formats are not supported");
   140         return SDL_FALSE;
   141     }
   142 
   143     /* Initialize the values here */
   144     if (SDL_BYTESPERPIXEL(format) <= 2) {
   145         *bpp = SDL_BITSPERPIXEL(format);
   146     } else {
   147         *bpp = SDL_BYTESPERPIXEL(format) * 8;
   148     }
   149     *Rmask = *Gmask = *Bmask = *Amask = 0;
   150 
   151     if (format == SDL_PIXELFORMAT_RGB24) {
   152 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   153         *Rmask = 0x00FF0000;
   154         *Gmask = 0x0000FF00;
   155         *Bmask = 0x000000FF;
   156 #else
   157         *Rmask = 0x000000FF;
   158         *Gmask = 0x0000FF00;
   159         *Bmask = 0x00FF0000;
   160 #endif
   161         return SDL_TRUE;
   162     }
   163 
   164     if (format == SDL_PIXELFORMAT_BGR24) {
   165 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   166         *Rmask = 0x000000FF;
   167         *Gmask = 0x0000FF00;
   168         *Bmask = 0x00FF0000;
   169 #else
   170         *Rmask = 0x00FF0000;
   171         *Gmask = 0x0000FF00;
   172         *Bmask = 0x000000FF;
   173 #endif
   174         return SDL_TRUE;
   175     }
   176 
   177     if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 &&
   178         SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 &&
   179         SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) {
   180         /* Not a format that uses masks */
   181         return SDL_TRUE;
   182     }
   183 
   184     switch (SDL_PIXELLAYOUT(format)) {
   185     case SDL_PACKEDLAYOUT_332:
   186         masks[0] = 0x00000000;
   187         masks[1] = 0x000000E0;
   188         masks[2] = 0x0000001C;
   189         masks[3] = 0x00000003;
   190         break;
   191     case SDL_PACKEDLAYOUT_4444:
   192         masks[0] = 0x0000F000;
   193         masks[1] = 0x00000F00;
   194         masks[2] = 0x000000F0;
   195         masks[3] = 0x0000000F;
   196         break;
   197     case SDL_PACKEDLAYOUT_1555:
   198         masks[0] = 0x00008000;
   199         masks[1] = 0x00007C00;
   200         masks[2] = 0x000003E0;
   201         masks[3] = 0x0000001F;
   202         break;
   203     case SDL_PACKEDLAYOUT_5551:
   204         masks[0] = 0x0000F800;
   205         masks[1] = 0x000007C0;
   206         masks[2] = 0x0000003E;
   207         masks[3] = 0x00000001;
   208         break;
   209     case SDL_PACKEDLAYOUT_565:
   210         masks[0] = 0x00000000;
   211         masks[1] = 0x0000F800;
   212         masks[2] = 0x000007E0;
   213         masks[3] = 0x0000001F;
   214         break;
   215     case SDL_PACKEDLAYOUT_8888:
   216         masks[0] = 0xFF000000;
   217         masks[1] = 0x00FF0000;
   218         masks[2] = 0x0000FF00;
   219         masks[3] = 0x000000FF;
   220         break;
   221     case SDL_PACKEDLAYOUT_2101010:
   222         masks[0] = 0xC0000000;
   223         masks[1] = 0x3FF00000;
   224         masks[2] = 0x000FFC00;
   225         masks[3] = 0x000003FF;
   226         break;
   227     case SDL_PACKEDLAYOUT_1010102:
   228         masks[0] = 0xFFC00000;
   229         masks[1] = 0x003FF000;
   230         masks[2] = 0x00000FFC;
   231         masks[3] = 0x00000003;
   232         break;
   233     default:
   234         SDL_SetError("Unknown pixel format");
   235         return SDL_FALSE;
   236     }
   237 
   238     switch (SDL_PIXELORDER(format)) {
   239     case SDL_PACKEDORDER_XRGB:
   240         *Rmask = masks[1];
   241         *Gmask = masks[2];
   242         *Bmask = masks[3];
   243         break;
   244     case SDL_PACKEDORDER_RGBX:
   245         *Rmask = masks[0];
   246         *Gmask = masks[1];
   247         *Bmask = masks[2];
   248         break;
   249     case SDL_PACKEDORDER_ARGB:
   250         *Amask = masks[0];
   251         *Rmask = masks[1];
   252         *Gmask = masks[2];
   253         *Bmask = masks[3];
   254         break;
   255     case SDL_PACKEDORDER_RGBA:
   256         *Rmask = masks[0];
   257         *Gmask = masks[1];
   258         *Bmask = masks[2];
   259         *Amask = masks[3];
   260         break;
   261     case SDL_PACKEDORDER_XBGR:
   262         *Bmask = masks[1];
   263         *Gmask = masks[2];
   264         *Rmask = masks[3];
   265         break;
   266     case SDL_PACKEDORDER_BGRX:
   267         *Bmask = masks[0];
   268         *Gmask = masks[1];
   269         *Rmask = masks[2];
   270         break;
   271     case SDL_PACKEDORDER_BGRA:
   272         *Bmask = masks[0];
   273         *Gmask = masks[1];
   274         *Rmask = masks[2];
   275         *Amask = masks[3];
   276         break;
   277     case SDL_PACKEDORDER_ABGR:
   278         *Amask = masks[0];
   279         *Bmask = masks[1];
   280         *Gmask = masks[2];
   281         *Rmask = masks[3];
   282         break;
   283     default:
   284         SDL_SetError("Unknown pixel format");
   285         return SDL_FALSE;
   286     }
   287     return SDL_TRUE;
   288 }
   289 
   290 Uint32
   291 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
   292                            Uint32 Amask)
   293 {
   294     switch (bpp) {
   295     case 1:
   296         /* SDL defaults to MSB ordering */
   297         return SDL_PIXELFORMAT_INDEX1MSB;
   298     case 4:
   299         /* SDL defaults to MSB ordering */
   300         return SDL_PIXELFORMAT_INDEX4MSB;
   301     case 8:
   302         if (Rmask == 0) {
   303             return SDL_PIXELFORMAT_INDEX8;
   304         }
   305         if (Rmask == 0xE0 &&
   306             Gmask == 0x1C &&
   307             Bmask == 0x03 &&
   308             Amask == 0x00) {
   309             return SDL_PIXELFORMAT_RGB332;
   310         }
   311         break;
   312     case 12:
   313         if (Rmask == 0) {
   314             return SDL_PIXELFORMAT_RGB444;
   315         }
   316         if (Rmask == 0x0F00 &&
   317             Gmask == 0x00F0 &&
   318             Bmask == 0x000F &&
   319             Amask == 0x0000) {
   320             return SDL_PIXELFORMAT_RGB444;
   321         }
   322         break;
   323     case 15:
   324         if (Rmask == 0) {
   325             return SDL_PIXELFORMAT_RGB555;
   326         }
   327         /* Fall through to 16-bit checks */
   328     case 16:
   329         if (Rmask == 0) {
   330             return SDL_PIXELFORMAT_RGB565;
   331         }
   332         if (Rmask == 0x7C00 &&
   333             Gmask == 0x03E0 &&
   334             Bmask == 0x001F &&
   335             Amask == 0x0000) {
   336             return SDL_PIXELFORMAT_RGB555;
   337         }
   338         if (Rmask == 0x001F &&
   339             Gmask == 0x03E0 &&
   340             Bmask == 0x7C00 &&
   341             Amask == 0x0000) {
   342             return SDL_PIXELFORMAT_BGR555;
   343         }
   344         if (Rmask == 0x0F00 &&
   345             Gmask == 0x00F0 &&
   346             Bmask == 0x000F &&
   347             Amask == 0xF000) {
   348             return SDL_PIXELFORMAT_ARGB4444;
   349         }
   350         if (Rmask == 0xF000 &&
   351             Gmask == 0x0F00 &&
   352             Bmask == 0x00F0 &&
   353             Amask == 0x000F) {
   354             return SDL_PIXELFORMAT_RGBA4444;
   355         }
   356         if (Rmask == 0x000F &&
   357             Gmask == 0x00F0 &&
   358             Bmask == 0x0F00 &&
   359             Amask == 0xF000) {
   360             return SDL_PIXELFORMAT_ABGR4444;
   361         }
   362         if (Rmask == 0x00F0 &&
   363             Gmask == 0x0F00 &&
   364             Bmask == 0xF000 &&
   365             Amask == 0x000F) {
   366             return SDL_PIXELFORMAT_BGRA4444;
   367         }
   368         if (Rmask == 0x7C00 &&
   369             Gmask == 0x03E0 &&
   370             Bmask == 0x001F &&
   371             Amask == 0x8000) {
   372             return SDL_PIXELFORMAT_ARGB1555;
   373         }
   374         if (Rmask == 0xF800 &&
   375             Gmask == 0x07C0 &&
   376             Bmask == 0x003E &&
   377             Amask == 0x0001) {
   378             return SDL_PIXELFORMAT_RGBA5551;
   379         }
   380         if (Rmask == 0x001F &&
   381             Gmask == 0x03E0 &&
   382             Bmask == 0x7C00 &&
   383             Amask == 0x8000) {
   384             return SDL_PIXELFORMAT_ABGR1555;
   385         }
   386         if (Rmask == 0x003E &&
   387             Gmask == 0x07C0 &&
   388             Bmask == 0xF800 &&
   389             Amask == 0x0001) {
   390             return SDL_PIXELFORMAT_BGRA5551;
   391         }
   392         if (Rmask == 0xF800 &&
   393             Gmask == 0x07E0 &&
   394             Bmask == 0x001F &&
   395             Amask == 0x0000) {
   396             return SDL_PIXELFORMAT_RGB565;
   397         }
   398         if (Rmask == 0x001F &&
   399             Gmask == 0x07E0 &&
   400             Bmask == 0xF800 &&
   401             Amask == 0x0000) {
   402             return SDL_PIXELFORMAT_BGR565;
   403         }
   404         break;
   405     case 24:
   406         switch (Rmask) {
   407         case 0:
   408         case 0x00FF0000:
   409 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   410             return SDL_PIXELFORMAT_RGB24;
   411 #else
   412             return SDL_PIXELFORMAT_BGR24;
   413 #endif
   414         case 0x000000FF:
   415 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   416             return SDL_PIXELFORMAT_BGR24;
   417 #else
   418             return SDL_PIXELFORMAT_RGB24;
   419 #endif
   420         }
   421     case 32:
   422         if (Rmask == 0) {
   423             return SDL_PIXELFORMAT_RGB888;
   424         }
   425         if (Rmask == 0x00FF0000 &&
   426             Gmask == 0x0000FF00 &&
   427             Bmask == 0x000000FF &&
   428             Amask == 0x00000000) {
   429             return SDL_PIXELFORMAT_RGB888;
   430         }
   431         if (Rmask == 0xFF000000 &&
   432             Gmask == 0x00FF0000 &&
   433             Bmask == 0x0000FF00 &&
   434             Amask == 0x00000000) {
   435             return SDL_PIXELFORMAT_RGBX8888;
   436         }
   437         if (Rmask == 0x000000FF &&
   438             Gmask == 0x0000FF00 &&
   439             Bmask == 0x00FF0000 &&
   440             Amask == 0x00000000) {
   441             return SDL_PIXELFORMAT_BGR888;
   442         }
   443         if (Rmask == 0x0000FF00 &&
   444             Gmask == 0x00FF0000 &&
   445             Bmask == 0xFF000000 &&
   446             Amask == 0x00000000) {
   447             return SDL_PIXELFORMAT_BGRX8888;
   448         }
   449         if (Rmask == 0x00FF0000 &&
   450             Gmask == 0x0000FF00 &&
   451             Bmask == 0x000000FF &&
   452             Amask == 0xFF000000) {
   453             return SDL_PIXELFORMAT_ARGB8888;
   454         }
   455         if (Rmask == 0xFF000000 &&
   456             Gmask == 0x00FF0000 &&
   457             Bmask == 0x0000FF00 &&
   458             Amask == 0x000000FF) {
   459             return SDL_PIXELFORMAT_RGBA8888;
   460         }
   461         if (Rmask == 0x000000FF &&
   462             Gmask == 0x0000FF00 &&
   463             Bmask == 0x00FF0000 &&
   464             Amask == 0xFF000000) {
   465             return SDL_PIXELFORMAT_ABGR8888;
   466         }
   467         if (Rmask == 0x0000FF00 &&
   468             Gmask == 0x00FF0000 &&
   469             Bmask == 0xFF000000 &&
   470             Amask == 0x000000FF) {
   471             return SDL_PIXELFORMAT_BGRA8888;
   472         }
   473         if (Rmask == 0x3FF00000 &&
   474             Gmask == 0x000FFC00 &&
   475             Bmask == 0x000003FF &&
   476             Amask == 0xC0000000) {
   477             return SDL_PIXELFORMAT_ARGB2101010;
   478         }
   479     }
   480     return SDL_PIXELFORMAT_UNKNOWN;
   481 }
   482 
   483 static SDL_PixelFormat *formats;
   484 
   485 SDL_PixelFormat *
   486 SDL_AllocFormat(Uint32 pixel_format)
   487 {
   488     SDL_PixelFormat *format;
   489 
   490     /* Look it up in our list of previously allocated formats */
   491     for (format = formats; format; format = format->next) {
   492         if (pixel_format == format->format) {
   493             ++format->refcount;
   494             return format;
   495         }
   496     }
   497 
   498     /* Allocate an empty pixel format structure, and initialize it */
   499     format = SDL_malloc(sizeof(*format));
   500     if (format == NULL) {
   501         SDL_OutOfMemory();
   502         return NULL;
   503     }
   504     if (SDL_InitFormat(format, pixel_format) < 0) {
   505         SDL_free(format);
   506         SDL_InvalidParamError("format");
   507         return NULL;
   508     }
   509 
   510     if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
   511         /* Cache the RGB formats */
   512         format->next = formats;
   513         formats = format;
   514     }
   515     return format;
   516 }
   517 
   518 int
   519 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
   520 {
   521     int bpp;
   522     Uint32 Rmask, Gmask, Bmask, Amask;
   523     Uint32 mask;
   524 
   525     if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
   526                                     &Rmask, &Gmask, &Bmask, &Amask)) {
   527         return -1;
   528     }
   529 
   530     /* Set up the format */
   531     SDL_zerop(format);
   532     format->format = pixel_format;
   533     format->BitsPerPixel = bpp;
   534     format->BytesPerPixel = (bpp + 7) / 8;
   535 
   536     format->Rmask = Rmask;
   537     format->Rshift = 0;
   538     format->Rloss = 8;
   539     if (Rmask) {
   540         for (mask = Rmask; !(mask & 0x01); mask >>= 1)
   541             ++format->Rshift;
   542         for (; (mask & 0x01); mask >>= 1)
   543             --format->Rloss;
   544     }
   545 
   546     format->Gmask = Gmask;
   547     format->Gshift = 0;
   548     format->Gloss = 8;
   549     if (Gmask) {
   550         for (mask = Gmask; !(mask & 0x01); mask >>= 1)
   551             ++format->Gshift;
   552         for (; (mask & 0x01); mask >>= 1)
   553             --format->Gloss;
   554     }
   555 
   556     format->Bmask = Bmask;
   557     format->Bshift = 0;
   558     format->Bloss = 8;
   559     if (Bmask) {
   560         for (mask = Bmask; !(mask & 0x01); mask >>= 1)
   561             ++format->Bshift;
   562         for (; (mask & 0x01); mask >>= 1)
   563             --format->Bloss;
   564     }
   565 
   566     format->Amask = Amask;
   567     format->Ashift = 0;
   568     format->Aloss = 8;
   569     if (Amask) {
   570         for (mask = Amask; !(mask & 0x01); mask >>= 1)
   571             ++format->Ashift;
   572         for (; (mask & 0x01); mask >>= 1)
   573             --format->Aloss;
   574     }
   575 
   576     format->palette = NULL;
   577     format->refcount = 1;
   578     format->next = NULL;
   579 
   580     return 0;
   581 }
   582 
   583 void
   584 SDL_FreeFormat(SDL_PixelFormat *format)
   585 {
   586     SDL_PixelFormat *prev;
   587 
   588     if (!format) {
   589         SDL_InvalidParamError("format");
   590         return;
   591     }
   592     if (--format->refcount > 0) {
   593         return;
   594     }
   595 
   596     /* Remove this format from our list */
   597     if (format == formats) {
   598         formats = format->next;
   599     } else if (formats) {
   600         for (prev = formats; prev->next; prev = prev->next) {
   601             if (prev->next == format) {
   602                 prev->next = format->next;
   603                 break;
   604             }
   605         }
   606     }
   607 
   608     if (format->palette) {
   609         SDL_FreePalette(format->palette);
   610     }
   611     SDL_free(format);
   612 }
   613 
   614 SDL_Palette *
   615 SDL_AllocPalette(int ncolors)
   616 {
   617     SDL_Palette *palette;
   618 
   619     /* Input validation */
   620     if (ncolors < 1) {
   621       SDL_InvalidParamError("ncolors");
   622       return NULL;
   623     }
   624 
   625     palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
   626     if (!palette) {
   627         SDL_OutOfMemory();
   628         return NULL;
   629     }
   630     palette->colors =
   631         (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
   632     if (!palette->colors) {
   633         SDL_free(palette);
   634         return NULL;
   635     }
   636     palette->ncolors = ncolors;
   637     palette->version = 1;
   638     palette->refcount = 1;
   639 
   640     SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
   641 
   642     return palette;
   643 }
   644 
   645 int
   646 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
   647 {
   648     if (!format) {
   649         return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
   650     }
   651 
   652     if (palette && palette->ncolors != (1 << format->BitsPerPixel)) {
   653         return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
   654     }
   655 
   656     if (format->palette == palette) {
   657         return 0;
   658     }
   659 
   660     if (format->palette) {
   661         SDL_FreePalette(format->palette);
   662     }
   663 
   664     format->palette = palette;
   665 
   666     if (format->palette) {
   667         ++format->palette->refcount;
   668     }
   669 
   670     return 0;
   671 }
   672 
   673 int
   674 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
   675                      int firstcolor, int ncolors)
   676 {
   677     int status = 0;
   678 
   679     /* Verify the parameters */
   680     if (!palette) {
   681         return -1;
   682     }
   683     if (ncolors > (palette->ncolors - firstcolor)) {
   684         ncolors = (palette->ncolors - firstcolor);
   685         status = -1;
   686     }
   687 
   688     if (colors != (palette->colors + firstcolor)) {
   689         SDL_memcpy(palette->colors + firstcolor, colors,
   690                    ncolors * sizeof(*colors));
   691     }
   692     ++palette->version;
   693     if (!palette->version) {
   694         palette->version = 1;
   695     }
   696 
   697     return status;
   698 }
   699 
   700 void
   701 SDL_FreePalette(SDL_Palette * palette)
   702 {
   703     if (!palette) {
   704         SDL_InvalidParamError("palette");
   705         return;
   706     }
   707     if (--palette->refcount > 0) {
   708         return;
   709     }
   710     SDL_free(palette->colors);
   711     SDL_free(palette);
   712 }
   713 
   714 /*
   715  * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
   716  */
   717 void
   718 SDL_DitherColors(SDL_Color * colors, int bpp)
   719 {
   720     int i;
   721     if (bpp != 8)
   722         return;                 /* only 8bpp supported right now */
   723 
   724     for (i = 0; i < 256; i++) {
   725         int r, g, b;
   726         /* map each bit field to the full [0, 255] interval,
   727            so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
   728         r = i & 0xe0;
   729         r |= r >> 3 | r >> 6;
   730         colors[i].r = r;
   731         g = (i << 3) & 0xe0;
   732         g |= g >> 3 | g >> 6;
   733         colors[i].g = g;
   734         b = i & 0x3;
   735         b |= b << 2;
   736         b |= b << 4;
   737         colors[i].b = b;
   738         colors[i].a = SDL_ALPHA_OPAQUE;
   739     }
   740 }
   741 
   742 /*
   743  * Calculate the pad-aligned scanline width of a surface
   744  */
   745 int
   746 SDL_CalculatePitch(SDL_Surface * surface)
   747 {
   748     int pitch;
   749 
   750     /* Surface should be 4-byte aligned for speed */
   751     pitch = surface->w * surface->format->BytesPerPixel;
   752     switch (surface->format->BitsPerPixel) {
   753     case 1:
   754         pitch = (pitch + 7) / 8;
   755         break;
   756     case 4:
   757         pitch = (pitch + 1) / 2;
   758         break;
   759     default:
   760         break;
   761     }
   762     pitch = (pitch + 3) & ~3;   /* 4-byte aligning */
   763     return (pitch);
   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         for (i = 0; i < 256; ++i) {
  1103             ramp[i] = 0;
  1104         }
  1105         return;
  1106     } else if (gamma == 1.0f) {
  1107         /* 1.0 gamma is identity */
  1108         for (i = 0; i < 256; ++i) {
  1109             ramp[i] = (i << 8) | i;
  1110         }
  1111         return;
  1112     } else {
  1113         /* Calculate a real gamma ramp */
  1114         int value;
  1115         gamma = 1.0f / gamma;
  1116         for (i = 0; i < 256; ++i) {
  1117             value =
  1118                 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
  1119             if (value > 65535) {
  1120                 value = 65535;
  1121             }
  1122             ramp[i] = (Uint16) value;
  1123         }
  1124     }
  1125 }
  1126 
  1127 /* vi: set ts=4 sw=4 expandtab: */