src/video/SDL_pixels.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Tue, 29 Dec 2015 19:13:56 +0100
changeset 9988 08d023f75d78
parent 9715 8945c203a54b
child 9998 f67cf37e9cd4
permissions -rw-r--r--
Fixed a crash if creating accelerated renderer after accessing window surface.

Partially fixes Bugzilla #3196.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2015 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         /* Fall through to 16-bit checks */
   330     case 16:
   331         if (Rmask == 0) {
   332             return SDL_PIXELFORMAT_RGB565;
   333         }
   334         if (Rmask == 0x7C00 &&
   335             Gmask == 0x03E0 &&
   336             Bmask == 0x001F &&
   337             Amask == 0x0000) {
   338             return SDL_PIXELFORMAT_RGB555;
   339         }
   340         if (Rmask == 0x001F &&
   341             Gmask == 0x03E0 &&
   342             Bmask == 0x7C00 &&
   343             Amask == 0x0000) {
   344             return SDL_PIXELFORMAT_BGR555;
   345         }
   346         if (Rmask == 0x0F00 &&
   347             Gmask == 0x00F0 &&
   348             Bmask == 0x000F &&
   349             Amask == 0xF000) {
   350             return SDL_PIXELFORMAT_ARGB4444;
   351         }
   352         if (Rmask == 0xF000 &&
   353             Gmask == 0x0F00 &&
   354             Bmask == 0x00F0 &&
   355             Amask == 0x000F) {
   356             return SDL_PIXELFORMAT_RGBA4444;
   357         }
   358         if (Rmask == 0x000F &&
   359             Gmask == 0x00F0 &&
   360             Bmask == 0x0F00 &&
   361             Amask == 0xF000) {
   362             return SDL_PIXELFORMAT_ABGR4444;
   363         }
   364         if (Rmask == 0x00F0 &&
   365             Gmask == 0x0F00 &&
   366             Bmask == 0xF000 &&
   367             Amask == 0x000F) {
   368             return SDL_PIXELFORMAT_BGRA4444;
   369         }
   370         if (Rmask == 0x7C00 &&
   371             Gmask == 0x03E0 &&
   372             Bmask == 0x001F &&
   373             Amask == 0x8000) {
   374             return SDL_PIXELFORMAT_ARGB1555;
   375         }
   376         if (Rmask == 0xF800 &&
   377             Gmask == 0x07C0 &&
   378             Bmask == 0x003E &&
   379             Amask == 0x0001) {
   380             return SDL_PIXELFORMAT_RGBA5551;
   381         }
   382         if (Rmask == 0x001F &&
   383             Gmask == 0x03E0 &&
   384             Bmask == 0x7C00 &&
   385             Amask == 0x8000) {
   386             return SDL_PIXELFORMAT_ABGR1555;
   387         }
   388         if (Rmask == 0x003E &&
   389             Gmask == 0x07C0 &&
   390             Bmask == 0xF800 &&
   391             Amask == 0x0001) {
   392             return SDL_PIXELFORMAT_BGRA5551;
   393         }
   394         if (Rmask == 0xF800 &&
   395             Gmask == 0x07E0 &&
   396             Bmask == 0x001F &&
   397             Amask == 0x0000) {
   398             return SDL_PIXELFORMAT_RGB565;
   399         }
   400         if (Rmask == 0x001F &&
   401             Gmask == 0x07E0 &&
   402             Bmask == 0xF800 &&
   403             Amask == 0x0000) {
   404             return SDL_PIXELFORMAT_BGR565;
   405         }
   406         break;
   407     case 24:
   408         switch (Rmask) {
   409         case 0:
   410         case 0x00FF0000:
   411 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   412             return SDL_PIXELFORMAT_RGB24;
   413 #else
   414             return SDL_PIXELFORMAT_BGR24;
   415 #endif
   416         case 0x000000FF:
   417 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   418             return SDL_PIXELFORMAT_BGR24;
   419 #else
   420             return SDL_PIXELFORMAT_RGB24;
   421 #endif
   422         }
   423     case 32:
   424         if (Rmask == 0) {
   425             return SDL_PIXELFORMAT_RGB888;
   426         }
   427         if (Rmask == 0x00FF0000 &&
   428             Gmask == 0x0000FF00 &&
   429             Bmask == 0x000000FF &&
   430             Amask == 0x00000000) {
   431             return SDL_PIXELFORMAT_RGB888;
   432         }
   433         if (Rmask == 0xFF000000 &&
   434             Gmask == 0x00FF0000 &&
   435             Bmask == 0x0000FF00 &&
   436             Amask == 0x00000000) {
   437             return SDL_PIXELFORMAT_RGBX8888;
   438         }
   439         if (Rmask == 0x000000FF &&
   440             Gmask == 0x0000FF00 &&
   441             Bmask == 0x00FF0000 &&
   442             Amask == 0x00000000) {
   443             return SDL_PIXELFORMAT_BGR888;
   444         }
   445         if (Rmask == 0x0000FF00 &&
   446             Gmask == 0x00FF0000 &&
   447             Bmask == 0xFF000000 &&
   448             Amask == 0x00000000) {
   449             return SDL_PIXELFORMAT_BGRX8888;
   450         }
   451         if (Rmask == 0x00FF0000 &&
   452             Gmask == 0x0000FF00 &&
   453             Bmask == 0x000000FF &&
   454             Amask == 0xFF000000) {
   455             return SDL_PIXELFORMAT_ARGB8888;
   456         }
   457         if (Rmask == 0xFF000000 &&
   458             Gmask == 0x00FF0000 &&
   459             Bmask == 0x0000FF00 &&
   460             Amask == 0x000000FF) {
   461             return SDL_PIXELFORMAT_RGBA8888;
   462         }
   463         if (Rmask == 0x000000FF &&
   464             Gmask == 0x0000FF00 &&
   465             Bmask == 0x00FF0000 &&
   466             Amask == 0xFF000000) {
   467             return SDL_PIXELFORMAT_ABGR8888;
   468         }
   469         if (Rmask == 0x0000FF00 &&
   470             Gmask == 0x00FF0000 &&
   471             Bmask == 0xFF000000 &&
   472             Amask == 0x000000FF) {
   473             return SDL_PIXELFORMAT_BGRA8888;
   474         }
   475         if (Rmask == 0x3FF00000 &&
   476             Gmask == 0x000FFC00 &&
   477             Bmask == 0x000003FF &&
   478             Amask == 0xC0000000) {
   479             return SDL_PIXELFORMAT_ARGB2101010;
   480         }
   481     }
   482     return SDL_PIXELFORMAT_UNKNOWN;
   483 }
   484 
   485 static SDL_PixelFormat *formats;
   486 
   487 SDL_PixelFormat *
   488 SDL_AllocFormat(Uint32 pixel_format)
   489 {
   490     SDL_PixelFormat *format;
   491 
   492     /* Look it up in our list of previously allocated formats */
   493     for (format = formats; format; format = format->next) {
   494         if (pixel_format == format->format) {
   495             ++format->refcount;
   496             return format;
   497         }
   498     }
   499 
   500     /* Allocate an empty pixel format structure, and initialize it */
   501     format = SDL_malloc(sizeof(*format));
   502     if (format == NULL) {
   503         SDL_OutOfMemory();
   504         return NULL;
   505     }
   506     if (SDL_InitFormat(format, pixel_format) < 0) {
   507         SDL_free(format);
   508         SDL_InvalidParamError("format");
   509         return NULL;
   510     }
   511 
   512     if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
   513         /* Cache the RGB formats */
   514         format->next = formats;
   515         formats = format;
   516     }
   517     return format;
   518 }
   519 
   520 int
   521 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
   522 {
   523     int bpp;
   524     Uint32 Rmask, Gmask, Bmask, Amask;
   525     Uint32 mask;
   526 
   527     if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
   528                                     &Rmask, &Gmask, &Bmask, &Amask)) {
   529         return -1;
   530     }
   531 
   532     /* Set up the format */
   533     SDL_zerop(format);
   534     format->format = pixel_format;
   535     format->BitsPerPixel = bpp;
   536     format->BytesPerPixel = (bpp + 7) / 8;
   537 
   538     format->Rmask = Rmask;
   539     format->Rshift = 0;
   540     format->Rloss = 8;
   541     if (Rmask) {
   542         for (mask = Rmask; !(mask & 0x01); mask >>= 1)
   543             ++format->Rshift;
   544         for (; (mask & 0x01); mask >>= 1)
   545             --format->Rloss;
   546     }
   547 
   548     format->Gmask = Gmask;
   549     format->Gshift = 0;
   550     format->Gloss = 8;
   551     if (Gmask) {
   552         for (mask = Gmask; !(mask & 0x01); mask >>= 1)
   553             ++format->Gshift;
   554         for (; (mask & 0x01); mask >>= 1)
   555             --format->Gloss;
   556     }
   557 
   558     format->Bmask = Bmask;
   559     format->Bshift = 0;
   560     format->Bloss = 8;
   561     if (Bmask) {
   562         for (mask = Bmask; !(mask & 0x01); mask >>= 1)
   563             ++format->Bshift;
   564         for (; (mask & 0x01); mask >>= 1)
   565             --format->Bloss;
   566     }
   567 
   568     format->Amask = Amask;
   569     format->Ashift = 0;
   570     format->Aloss = 8;
   571     if (Amask) {
   572         for (mask = Amask; !(mask & 0x01); mask >>= 1)
   573             ++format->Ashift;
   574         for (; (mask & 0x01); mask >>= 1)
   575             --format->Aloss;
   576     }
   577 
   578     format->palette = NULL;
   579     format->refcount = 1;
   580     format->next = NULL;
   581 
   582     return 0;
   583 }
   584 
   585 void
   586 SDL_FreeFormat(SDL_PixelFormat *format)
   587 {
   588     SDL_PixelFormat *prev;
   589 
   590     if (!format) {
   591         SDL_InvalidParamError("format");
   592         return;
   593     }
   594     if (--format->refcount > 0) {
   595         return;
   596     }
   597 
   598     /* Remove this format from our list */
   599     if (format == formats) {
   600         formats = format->next;
   601     } else if (formats) {
   602         for (prev = formats; prev->next; prev = prev->next) {
   603             if (prev->next == format) {
   604                 prev->next = format->next;
   605                 break;
   606             }
   607         }
   608     }
   609 
   610     if (format->palette) {
   611         SDL_FreePalette(format->palette);
   612     }
   613     SDL_free(format);
   614 }
   615 
   616 SDL_Palette *
   617 SDL_AllocPalette(int ncolors)
   618 {
   619     SDL_Palette *palette;
   620 
   621     /* Input validation */
   622     if (ncolors < 1) {
   623       SDL_InvalidParamError("ncolors");
   624       return NULL;
   625     }
   626 
   627     palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
   628     if (!palette) {
   629         SDL_OutOfMemory();
   630         return NULL;
   631     }
   632     palette->colors =
   633         (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
   634     if (!palette->colors) {
   635         SDL_free(palette);
   636         return NULL;
   637     }
   638     palette->ncolors = ncolors;
   639     palette->version = 1;
   640     palette->refcount = 1;
   641 
   642     SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
   643 
   644     return palette;
   645 }
   646 
   647 int
   648 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
   649 {
   650     if (!format) {
   651         return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
   652     }
   653 
   654     if (palette && palette->ncolors != (1 << format->BitsPerPixel)) {
   655         return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
   656     }
   657 
   658     if (format->palette == palette) {
   659         return 0;
   660     }
   661 
   662     if (format->palette) {
   663         SDL_FreePalette(format->palette);
   664     }
   665 
   666     format->palette = palette;
   667 
   668     if (format->palette) {
   669         ++format->palette->refcount;
   670     }
   671 
   672     return 0;
   673 }
   674 
   675 int
   676 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
   677                      int firstcolor, int ncolors)
   678 {
   679     int status = 0;
   680 
   681     /* Verify the parameters */
   682     if (!palette) {
   683         return -1;
   684     }
   685     if (ncolors > (palette->ncolors - firstcolor)) {
   686         ncolors = (palette->ncolors - firstcolor);
   687         status = -1;
   688     }
   689 
   690     if (colors != (palette->colors + firstcolor)) {
   691         SDL_memcpy(palette->colors + firstcolor, colors,
   692                    ncolors * sizeof(*colors));
   693     }
   694     ++palette->version;
   695     if (!palette->version) {
   696         palette->version = 1;
   697     }
   698 
   699     return status;
   700 }
   701 
   702 void
   703 SDL_FreePalette(SDL_Palette * palette)
   704 {
   705     if (!palette) {
   706         SDL_InvalidParamError("palette");
   707         return;
   708     }
   709     if (--palette->refcount > 0) {
   710         return;
   711     }
   712     SDL_free(palette->colors);
   713     SDL_free(palette);
   714 }
   715 
   716 /*
   717  * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
   718  */
   719 void
   720 SDL_DitherColors(SDL_Color * colors, int bpp)
   721 {
   722     int i;
   723     if (bpp != 8)
   724         return;                 /* only 8bpp supported right now */
   725 
   726     for (i = 0; i < 256; i++) {
   727         int r, g, b;
   728         /* map each bit field to the full [0, 255] interval,
   729            so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
   730         r = i & 0xe0;
   731         r |= r >> 3 | r >> 6;
   732         colors[i].r = r;
   733         g = (i << 3) & 0xe0;
   734         g |= g >> 3 | g >> 6;
   735         colors[i].g = g;
   736         b = i & 0x3;
   737         b |= b << 2;
   738         b |= b << 4;
   739         colors[i].b = b;
   740         colors[i].a = SDL_ALPHA_OPAQUE;
   741     }
   742 }
   743 
   744 /*
   745  * Calculate the pad-aligned scanline width of a surface
   746  */
   747 int
   748 SDL_CalculatePitch(SDL_Surface * surface)
   749 {
   750     int pitch;
   751 
   752     /* Surface should be 4-byte aligned for speed */
   753     pitch = surface->w * surface->format->BytesPerPixel;
   754     switch (surface->format->BitsPerPixel) {
   755     case 1:
   756         pitch = (pitch + 7) / 8;
   757         break;
   758     case 4:
   759         pitch = (pitch + 1) / 2;
   760         break;
   761     default:
   762         break;
   763     }
   764     pitch = (pitch + 3) & ~3;   /* 4-byte aligning */
   765     return (pitch);
   766 }
   767 
   768 /*
   769  * Match an RGB value to a particular palette index
   770  */
   771 Uint8
   772 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   773 {
   774     /* Do colorspace distance matching */
   775     unsigned int smallest;
   776     unsigned int distance;
   777     int rd, gd, bd, ad;
   778     int i;
   779     Uint8 pixel = 0;
   780 
   781     smallest = ~0;
   782     for (i = 0; i < pal->ncolors; ++i) {
   783         rd = pal->colors[i].r - r;
   784         gd = pal->colors[i].g - g;
   785         bd = pal->colors[i].b - b;
   786         ad = pal->colors[i].a - a;
   787         distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
   788         if (distance < smallest) {
   789             pixel = i;
   790             if (distance == 0) {        /* Perfect match! */
   791                 break;
   792             }
   793             smallest = distance;
   794         }
   795     }
   796     return (pixel);
   797 }
   798 
   799 /* Find the opaque pixel value corresponding to an RGB triple */
   800 Uint32
   801 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
   802 {
   803     if (format->palette == NULL) {
   804         return (r >> format->Rloss) << format->Rshift
   805             | (g >> format->Gloss) << format->Gshift
   806             | (b >> format->Bloss) << format->Bshift | format->Amask;
   807     } else {
   808         return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
   809     }
   810 }
   811 
   812 /* Find the pixel value corresponding to an RGBA quadruple */
   813 Uint32
   814 SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
   815             Uint8 a)
   816 {
   817     if (format->palette == NULL) {
   818         return (r >> format->Rloss) << format->Rshift
   819             | (g >> format->Gloss) << format->Gshift
   820             | (b >> format->Bloss) << format->Bshift
   821             | ((a >> format->Aloss) << format->Ashift & format->Amask);
   822     } else {
   823         return SDL_FindColor(format->palette, r, g, b, a);
   824     }
   825 }
   826 
   827 void
   828 SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
   829            Uint8 * b)
   830 {
   831     if (format->palette == NULL) {
   832         unsigned v;
   833         v = (pixel & format->Rmask) >> format->Rshift;
   834         *r = SDL_expand_byte[format->Rloss][v];
   835         v = (pixel & format->Gmask) >> format->Gshift;
   836         *g = SDL_expand_byte[format->Gloss][v];
   837         v = (pixel & format->Bmask) >> format->Bshift;
   838         *b = SDL_expand_byte[format->Bloss][v];
   839     } else {
   840         if (pixel < (unsigned)format->palette->ncolors) {
   841             *r = format->palette->colors[pixel].r;
   842             *g = format->palette->colors[pixel].g;
   843             *b = format->palette->colors[pixel].b;
   844         } else {
   845             *r = *g = *b = 0;
   846         }
   847     }
   848 }
   849 
   850 void
   851 SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
   852             Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
   853 {
   854     if (format->palette == NULL) {
   855         unsigned v;
   856         v = (pixel & format->Rmask) >> format->Rshift;
   857         *r = SDL_expand_byte[format->Rloss][v];
   858         v = (pixel & format->Gmask) >> format->Gshift;
   859         *g = SDL_expand_byte[format->Gloss][v];
   860         v = (pixel & format->Bmask) >> format->Bshift;
   861         *b = SDL_expand_byte[format->Bloss][v];
   862         v = (pixel & format->Amask) >> format->Ashift;
   863         *a = SDL_expand_byte[format->Aloss][v];
   864     } else {
   865         if (pixel < (unsigned)format->palette->ncolors) {
   866             *r = format->palette->colors[pixel].r;
   867             *g = format->palette->colors[pixel].g;
   868             *b = format->palette->colors[pixel].b;
   869             *a = format->palette->colors[pixel].a;
   870         } else {
   871             *r = *g = *b = *a = 0;
   872         }
   873     }
   874 }
   875 
   876 /* Map from Palette to Palette */
   877 static Uint8 *
   878 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
   879 {
   880     Uint8 *map;
   881     int i;
   882 
   883     if (identical) {
   884         if (src->ncolors <= dst->ncolors) {
   885             /* If an identical palette, no need to map */
   886             if (src == dst
   887                 ||
   888                 (SDL_memcmp
   889                  (src->colors, dst->colors,
   890                   src->ncolors * sizeof(SDL_Color)) == 0)) {
   891                 *identical = 1;
   892                 return (NULL);
   893             }
   894         }
   895         *identical = 0;
   896     }
   897     map = (Uint8 *) SDL_malloc(src->ncolors);
   898     if (map == NULL) {
   899         SDL_OutOfMemory();
   900         return (NULL);
   901     }
   902     for (i = 0; i < src->ncolors; ++i) {
   903         map[i] = SDL_FindColor(dst,
   904                                src->colors[i].r, src->colors[i].g,
   905                                src->colors[i].b, src->colors[i].a);
   906     }
   907     return (map);
   908 }
   909 
   910 /* Map from Palette to BitField */
   911 static Uint8 *
   912 Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
   913         SDL_PixelFormat * dst)
   914 {
   915     Uint8 *map;
   916     int i;
   917     int bpp;
   918     SDL_Palette *pal = src->palette;
   919 
   920     bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
   921     map = (Uint8 *) SDL_malloc(pal->ncolors * bpp);
   922     if (map == NULL) {
   923         SDL_OutOfMemory();
   924         return (NULL);
   925     }
   926 
   927     /* We memory copy to the pixel map so the endianness is preserved */
   928     for (i = 0; i < pal->ncolors; ++i) {
   929         Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
   930         Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
   931         Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
   932         Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
   933         ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
   934     }
   935     return (map);
   936 }
   937 
   938 /* Map from BitField to Dithered-Palette to Palette */
   939 static Uint8 *
   940 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
   941 {
   942     /* Generate a 256 color dither palette */
   943     SDL_Palette dithered;
   944     SDL_Color colors[256];
   945     SDL_Palette *pal = dst->palette;
   946 
   947     dithered.ncolors = 256;
   948     SDL_DitherColors(colors, 8);
   949     dithered.colors = colors;
   950     return (Map1to1(&dithered, pal, identical));
   951 }
   952 
   953 SDL_BlitMap *
   954 SDL_AllocBlitMap(void)
   955 {
   956     SDL_BlitMap *map;
   957 
   958     /* Allocate the empty map */
   959     map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
   960     if (map == NULL) {
   961         SDL_OutOfMemory();
   962         return (NULL);
   963     }
   964     map->info.r = 0xFF;
   965     map->info.g = 0xFF;
   966     map->info.b = 0xFF;
   967     map->info.a = 0xFF;
   968 
   969     /* It's ready to go */
   970     return (map);
   971 }
   972 
   973 void
   974 SDL_InvalidateMap(SDL_BlitMap * map)
   975 {
   976     if (!map) {
   977         return;
   978     }
   979     if (map->dst) {
   980         /* Release our reference to the surface - see the note below */
   981         if (--map->dst->refcount <= 0) {
   982             SDL_FreeSurface(map->dst);
   983         }
   984     }
   985     map->dst = NULL;
   986     map->src_palette_version = 0;
   987     map->dst_palette_version = 0;
   988     SDL_free(map->info.table);
   989     map->info.table = NULL;
   990 }
   991 
   992 int
   993 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
   994 {
   995     SDL_PixelFormat *srcfmt;
   996     SDL_PixelFormat *dstfmt;
   997     SDL_BlitMap *map;
   998 
   999     /* Clear out any previous mapping */
  1000     map = src->map;
  1001     if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
  1002         SDL_UnRLESurface(src, 1);
  1003     }
  1004     SDL_InvalidateMap(map);
  1005 
  1006     /* Figure out what kind of mapping we're doing */
  1007     map->identity = 0;
  1008     srcfmt = src->format;
  1009     dstfmt = dst->format;
  1010     if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
  1011         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1012             /* Palette --> Palette */
  1013             map->info.table =
  1014                 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
  1015             if (!map->identity) {
  1016                 if (map->info.table == NULL) {
  1017                     return (-1);
  1018                 }
  1019             }
  1020             if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
  1021                 map->identity = 0;
  1022         } else {
  1023             /* Palette --> BitField */
  1024             map->info.table =
  1025                 Map1toN(srcfmt, src->map->info.r, src->map->info.g,
  1026                         src->map->info.b, src->map->info.a, dstfmt);
  1027             if (map->info.table == NULL) {
  1028                 return (-1);
  1029             }
  1030         }
  1031     } else {
  1032         if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
  1033             /* BitField --> Palette */
  1034             map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
  1035             if (!map->identity) {
  1036                 if (map->info.table == NULL) {
  1037                     return (-1);
  1038                 }
  1039             }
  1040             map->identity = 0;  /* Don't optimize to copy */
  1041         } else {
  1042             /* BitField --> BitField */
  1043             if (srcfmt == dstfmt) {
  1044                 map->identity = 1;
  1045             }
  1046         }
  1047     }
  1048 
  1049     map->dst = dst;
  1050 
  1051     if (map->dst) {
  1052         /* Keep a reference to this surface so it doesn't get deleted
  1053            while we're still pointing at it.
  1054 
  1055            A better method would be for the destination surface to keep
  1056            track of surfaces that are mapped to it and automatically
  1057            invalidate them when it is freed, but this will do for now.
  1058         */
  1059         ++map->dst->refcount;
  1060     }
  1061 
  1062     if (dstfmt->palette) {
  1063         map->dst_palette_version = dstfmt->palette->version;
  1064     } else {
  1065         map->dst_palette_version = 0;
  1066     }
  1067 
  1068     if (srcfmt->palette) {
  1069         map->src_palette_version = srcfmt->palette->version;
  1070     } else {
  1071         map->src_palette_version = 0;
  1072     }
  1073 
  1074     /* Choose your blitters wisely */
  1075     return (SDL_CalculateBlit(src));
  1076 }
  1077 
  1078 void
  1079 SDL_FreeBlitMap(SDL_BlitMap * map)
  1080 {
  1081     if (map) {
  1082         SDL_InvalidateMap(map);
  1083         SDL_free(map);
  1084     }
  1085 }
  1086 
  1087 void
  1088 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
  1089 {
  1090     int i;
  1091 
  1092     /* Input validation */
  1093     if (gamma < 0.0f ) {
  1094       SDL_InvalidParamError("gamma");
  1095       return;
  1096     }
  1097     if (ramp == NULL) {
  1098       SDL_InvalidParamError("ramp");
  1099       return;
  1100     }
  1101 
  1102     /* 0.0 gamma is all black */
  1103     if (gamma == 0.0f) {
  1104         SDL_memset(ramp, 0, 256 * sizeof(Uint16));
  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: */