2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../SDL_internal.h"
23 /* General (mostly internal) pixel/color manipulation routines for SDL */
25 #include "SDL_endian.h"
26 #include "SDL_video.h"
27 #include "SDL_sysvideo.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_RLEaccel_c.h"
32 #define SDL_CallocNumber 256
34 /* Lookup tables to expand partial bytes to the full 0..255 range */
36 static Uint8 lookup_0[] = {
37 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
40 static Uint8 lookup_1[] = {
41 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
44 static Uint8 lookup_2[] = {
45 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
48 static Uint8 lookup_3[] = {
49 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
52 static Uint8 lookup_4[] = {
53 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
56 static Uint8 lookup_5[] = {
57 0, 36, 72, 109, 145, 182, 218, 255
60 static Uint8 lookup_6[] = {
64 static Uint8 lookup_7[] = {
68 static Uint8 lookup_8[] = {
72 Uint8* SDL_expand_byte[9] = {
84 /* Helper functions */
87 SDL_GetPixelFormatName(Uint32 format)
90 #define CASE(X) case X: return #X;
91 CASE(SDL_PIXELFORMAT_INDEX1LSB)
92 CASE(SDL_PIXELFORMAT_INDEX1MSB)
93 CASE(SDL_PIXELFORMAT_INDEX4LSB)
94 CASE(SDL_PIXELFORMAT_INDEX4MSB)
95 CASE(SDL_PIXELFORMAT_INDEX8)
96 CASE(SDL_PIXELFORMAT_RGB332)
97 CASE(SDL_PIXELFORMAT_RGB444)
98 CASE(SDL_PIXELFORMAT_BGR444)
99 CASE(SDL_PIXELFORMAT_RGB555)
100 CASE(SDL_PIXELFORMAT_BGR555)
101 CASE(SDL_PIXELFORMAT_ARGB4444)
102 CASE(SDL_PIXELFORMAT_RGBA4444)
103 CASE(SDL_PIXELFORMAT_ABGR4444)
104 CASE(SDL_PIXELFORMAT_BGRA4444)
105 CASE(SDL_PIXELFORMAT_ARGB1555)
106 CASE(SDL_PIXELFORMAT_RGBA5551)
107 CASE(SDL_PIXELFORMAT_ABGR1555)
108 CASE(SDL_PIXELFORMAT_BGRA5551)
109 CASE(SDL_PIXELFORMAT_RGB565)
110 CASE(SDL_PIXELFORMAT_BGR565)
111 CASE(SDL_PIXELFORMAT_RGB24)
112 CASE(SDL_PIXELFORMAT_BGR24)
113 CASE(SDL_PIXELFORMAT_RGB888)
114 CASE(SDL_PIXELFORMAT_RGBX8888)
115 CASE(SDL_PIXELFORMAT_BGR888)
116 CASE(SDL_PIXELFORMAT_BGRX8888)
117 CASE(SDL_PIXELFORMAT_ARGB8888)
118 CASE(SDL_PIXELFORMAT_RGBA8888)
119 CASE(SDL_PIXELFORMAT_ABGR8888)
120 CASE(SDL_PIXELFORMAT_BGRA8888)
121 CASE(SDL_PIXELFORMAT_ARGB2101010)
122 CASE(SDL_PIXELFORMAT_YV12)
123 CASE(SDL_PIXELFORMAT_IYUV)
124 CASE(SDL_PIXELFORMAT_YUY2)
125 CASE(SDL_PIXELFORMAT_UYVY)
126 CASE(SDL_PIXELFORMAT_YVYU)
127 CASE(SDL_PIXELFORMAT_NV12)
128 CASE(SDL_PIXELFORMAT_NV21)
131 return "SDL_PIXELFORMAT_UNKNOWN";
136 SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask,
137 Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
141 /* This function doesn't work with FourCC pixel formats */
142 if (SDL_ISPIXELFORMAT_FOURCC(format)) {
143 SDL_SetError("FOURCC pixel formats are not supported");
147 /* Initialize the values here */
148 if (SDL_BYTESPERPIXEL(format) <= 2) {
149 *bpp = SDL_BITSPERPIXEL(format);
151 *bpp = SDL_BYTESPERPIXEL(format) * 8;
153 *Rmask = *Gmask = *Bmask = *Amask = 0;
155 if (format == SDL_PIXELFORMAT_RGB24) {
156 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
168 if (format == SDL_PIXELFORMAT_BGR24) {
169 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
181 if (SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED8 &&
182 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED16 &&
183 SDL_PIXELTYPE(format) != SDL_PIXELTYPE_PACKED32) {
184 /* Not a format that uses masks */
188 switch (SDL_PIXELLAYOUT(format)) {
189 case SDL_PACKEDLAYOUT_332:
190 masks[0] = 0x00000000;
191 masks[1] = 0x000000E0;
192 masks[2] = 0x0000001C;
193 masks[3] = 0x00000003;
195 case SDL_PACKEDLAYOUT_4444:
196 masks[0] = 0x0000F000;
197 masks[1] = 0x00000F00;
198 masks[2] = 0x000000F0;
199 masks[3] = 0x0000000F;
201 case SDL_PACKEDLAYOUT_1555:
202 masks[0] = 0x00008000;
203 masks[1] = 0x00007C00;
204 masks[2] = 0x000003E0;
205 masks[3] = 0x0000001F;
207 case SDL_PACKEDLAYOUT_5551:
208 masks[0] = 0x0000F800;
209 masks[1] = 0x000007C0;
210 masks[2] = 0x0000003E;
211 masks[3] = 0x00000001;
213 case SDL_PACKEDLAYOUT_565:
214 masks[0] = 0x00000000;
215 masks[1] = 0x0000F800;
216 masks[2] = 0x000007E0;
217 masks[3] = 0x0000001F;
219 case SDL_PACKEDLAYOUT_8888:
220 masks[0] = 0xFF000000;
221 masks[1] = 0x00FF0000;
222 masks[2] = 0x0000FF00;
223 masks[3] = 0x000000FF;
225 case SDL_PACKEDLAYOUT_2101010:
226 masks[0] = 0xC0000000;
227 masks[1] = 0x3FF00000;
228 masks[2] = 0x000FFC00;
229 masks[3] = 0x000003FF;
231 case SDL_PACKEDLAYOUT_1010102:
232 masks[0] = 0xFFC00000;
233 masks[1] = 0x003FF000;
234 masks[2] = 0x00000FFC;
235 masks[3] = 0x00000003;
238 SDL_SetError("Unknown pixel format");
242 switch (SDL_PIXELORDER(format)) {
243 case SDL_PACKEDORDER_XRGB:
248 case SDL_PACKEDORDER_RGBX:
253 case SDL_PACKEDORDER_ARGB:
259 case SDL_PACKEDORDER_RGBA:
265 case SDL_PACKEDORDER_XBGR:
270 case SDL_PACKEDORDER_BGRX:
275 case SDL_PACKEDORDER_BGRA:
281 case SDL_PACKEDORDER_ABGR:
288 SDL_SetError("Unknown pixel format");
295 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
300 /* SDL defaults to MSB ordering */
301 return SDL_PIXELFORMAT_INDEX1MSB;
303 /* SDL defaults to MSB ordering */
304 return SDL_PIXELFORMAT_INDEX4MSB;
307 return SDL_PIXELFORMAT_INDEX8;
313 return SDL_PIXELFORMAT_RGB332;
318 return SDL_PIXELFORMAT_RGB444;
320 if (Rmask == 0x0F00 &&
324 return SDL_PIXELFORMAT_RGB444;
326 if (Rmask == 0x000F &&
330 return SDL_PIXELFORMAT_BGR444;
335 return SDL_PIXELFORMAT_RGB555;
340 return SDL_PIXELFORMAT_RGB565;
342 if (Rmask == 0x7C00 &&
346 return SDL_PIXELFORMAT_RGB555;
348 if (Rmask == 0x001F &&
352 return SDL_PIXELFORMAT_BGR555;
354 if (Rmask == 0x0F00 &&
358 return SDL_PIXELFORMAT_ARGB4444;
360 if (Rmask == 0xF000 &&
364 return SDL_PIXELFORMAT_RGBA4444;
366 if (Rmask == 0x000F &&
370 return SDL_PIXELFORMAT_ABGR4444;
372 if (Rmask == 0x00F0 &&
376 return SDL_PIXELFORMAT_BGRA4444;
378 if (Rmask == 0x7C00 &&
382 return SDL_PIXELFORMAT_ARGB1555;
384 if (Rmask == 0xF800 &&
388 return SDL_PIXELFORMAT_RGBA5551;
390 if (Rmask == 0x001F &&
394 return SDL_PIXELFORMAT_ABGR1555;
396 if (Rmask == 0x003E &&
400 return SDL_PIXELFORMAT_BGRA5551;
402 if (Rmask == 0xF800 &&
406 return SDL_PIXELFORMAT_RGB565;
408 if (Rmask == 0x001F &&
412 return SDL_PIXELFORMAT_BGR565;
414 if (Rmask == 0x003F &&
418 /* Technically this would be BGR556, but Witek says this works in bug 3158 */
419 return SDL_PIXELFORMAT_RGB565;
426 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
427 return SDL_PIXELFORMAT_RGB24;
429 return SDL_PIXELFORMAT_BGR24;
432 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
433 return SDL_PIXELFORMAT_BGR24;
435 return SDL_PIXELFORMAT_RGB24;
440 return SDL_PIXELFORMAT_RGB888;
442 if (Rmask == 0x00FF0000 &&
443 Gmask == 0x0000FF00 &&
444 Bmask == 0x000000FF &&
445 Amask == 0x00000000) {
446 return SDL_PIXELFORMAT_RGB888;
448 if (Rmask == 0xFF000000 &&
449 Gmask == 0x00FF0000 &&
450 Bmask == 0x0000FF00 &&
451 Amask == 0x00000000) {
452 return SDL_PIXELFORMAT_RGBX8888;
454 if (Rmask == 0x000000FF &&
455 Gmask == 0x0000FF00 &&
456 Bmask == 0x00FF0000 &&
457 Amask == 0x00000000) {
458 return SDL_PIXELFORMAT_BGR888;
460 if (Rmask == 0x0000FF00 &&
461 Gmask == 0x00FF0000 &&
462 Bmask == 0xFF000000 &&
463 Amask == 0x00000000) {
464 return SDL_PIXELFORMAT_BGRX8888;
466 if (Rmask == 0x00FF0000 &&
467 Gmask == 0x0000FF00 &&
468 Bmask == 0x000000FF &&
469 Amask == 0xFF000000) {
470 return SDL_PIXELFORMAT_ARGB8888;
472 if (Rmask == 0xFF000000 &&
473 Gmask == 0x00FF0000 &&
474 Bmask == 0x0000FF00 &&
475 Amask == 0x000000FF) {
476 return SDL_PIXELFORMAT_RGBA8888;
478 if (Rmask == 0x000000FF &&
479 Gmask == 0x0000FF00 &&
480 Bmask == 0x00FF0000 &&
481 Amask == 0xFF000000) {
482 return SDL_PIXELFORMAT_ABGR8888;
484 if (Rmask == 0x0000FF00 &&
485 Gmask == 0x00FF0000 &&
486 Bmask == 0xFF000000 &&
487 Amask == 0x000000FF) {
488 return SDL_PIXELFORMAT_BGRA8888;
490 if (Rmask == 0x3FF00000 &&
491 Gmask == 0x000FFC00 &&
492 Bmask == 0x000003FF &&
493 Amask == 0xC0000000) {
494 return SDL_PIXELFORMAT_ARGB2101010;
497 return SDL_PIXELFORMAT_UNKNOWN;
500 static SDL_PixelFormat *formats;
501 static SDL_SpinLock formats_lock = 0;
504 SDL_AllocFormat(Uint32 pixel_format)
506 SDL_PixelFormat *format;
508 SDL_AtomicLock(&formats_lock);
510 /* Look it up in our list of previously allocated formats */
511 for (format = formats; format; format = format->next) {
512 if (pixel_format == format->format) {
514 SDL_AtomicUnlock(&formats_lock);
519 /* Allocate an empty pixel format structure, and initialize it */
520 format = SDL_malloc(sizeof(*format));
521 if (format == NULL) {
522 SDL_AtomicUnlock(&formats_lock);
526 if (SDL_InitFormat(format, pixel_format) < 0) {
527 SDL_AtomicUnlock(&formats_lock);
529 SDL_InvalidParamError("format");
533 if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
534 /* Cache the RGB formats */
535 format->next = formats;
539 SDL_AtomicUnlock(&formats_lock);
545 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
548 Uint32 Rmask, Gmask, Bmask, Amask;
551 if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
552 &Rmask, &Gmask, &Bmask, &Amask)) {
556 /* Set up the format */
558 format->format = pixel_format;
559 format->BitsPerPixel = bpp;
560 format->BytesPerPixel = (bpp + 7) / 8;
562 format->Rmask = Rmask;
566 for (mask = Rmask; !(mask & 0x01); mask >>= 1)
568 for (; (mask & 0x01); mask >>= 1)
572 format->Gmask = Gmask;
576 for (mask = Gmask; !(mask & 0x01); mask >>= 1)
578 for (; (mask & 0x01); mask >>= 1)
582 format->Bmask = Bmask;
586 for (mask = Bmask; !(mask & 0x01); mask >>= 1)
588 for (; (mask & 0x01); mask >>= 1)
592 format->Amask = Amask;
596 for (mask = Amask; !(mask & 0x01); mask >>= 1)
598 for (; (mask & 0x01); mask >>= 1)
602 format->palette = NULL;
603 format->refcount = 1;
610 SDL_FreeFormat(SDL_PixelFormat *format)
612 SDL_PixelFormat *prev;
615 SDL_InvalidParamError("format");
619 SDL_AtomicLock(&formats_lock);
621 if (--format->refcount > 0) {
622 SDL_AtomicUnlock(&formats_lock);
626 /* Remove this format from our list */
627 if (format == formats) {
628 formats = format->next;
629 } else if (formats) {
630 for (prev = formats; prev->next; prev = prev->next) {
631 if (prev->next == format) {
632 prev->next = format->next;
638 SDL_AtomicUnlock(&formats_lock);
640 if (format->palette) {
641 SDL_FreePalette(format->palette);
647 SDL_AllocPalette(int ncolors)
649 SDL_Palette *palette;
651 /* Input validation */
653 SDL_InvalidParamError("ncolors");
657 palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
663 (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
664 if (!palette->colors) {
668 palette->ncolors = ncolors;
669 palette->version = 1;
670 palette->refcount = 1;
672 SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
678 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
681 return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
684 if (palette && palette->ncolors > (1 << format->BitsPerPixel)) {
685 return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
688 if (format->palette == palette) {
692 if (format->palette) {
693 SDL_FreePalette(format->palette);
696 format->palette = palette;
698 if (format->palette) {
699 ++format->palette->refcount;
706 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
707 int firstcolor, int ncolors)
711 /* Verify the parameters */
715 if (ncolors > (palette->ncolors - firstcolor)) {
716 ncolors = (palette->ncolors - firstcolor);
720 if (colors != (palette->colors + firstcolor)) {
721 SDL_memcpy(palette->colors + firstcolor, colors,
722 ncolors * sizeof(*colors));
725 if (!palette->version) {
726 palette->version = 1;
733 SDL_FreePalette(SDL_Palette * palette)
736 SDL_InvalidParamError("palette");
739 if (--palette->refcount > 0) {
742 SDL_free(palette->colors);
747 * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
750 SDL_DitherColors(SDL_Color * colors, int bpp)
754 return; /* only 8bpp supported right now */
756 for (i = 0; i < 256; i++) {
758 /* map each bit field to the full [0, 255] interval,
759 so 0 is mapped to (0, 0, 0) and 255 to (255, 255, 255) */
761 r |= r >> 3 | r >> 6;
764 g |= g >> 3 | g >> 6;
770 colors[i].a = SDL_ALPHA_OPAQUE;
775 * Match an RGB value to a particular palette index
778 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
780 /* Do colorspace distance matching */
781 unsigned int smallest;
782 unsigned int distance;
788 for (i = 0; i < pal->ncolors; ++i) {
789 rd = pal->colors[i].r - r;
790 gd = pal->colors[i].g - g;
791 bd = pal->colors[i].b - b;
792 ad = pal->colors[i].a - a;
793 distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
794 if (distance < smallest) {
796 if (distance == 0) { /* Perfect match! */
805 /* Tell whether palette is opaque, and if it has an alpha_channel */
807 SDL_DetectPalette(SDL_Palette *pal, SDL_bool *is_opaque, SDL_bool *has_alpha_channel)
812 SDL_bool all_opaque = SDL_TRUE;
813 for (i = 0; i < pal->ncolors; i++) {
814 Uint8 alpha_value = pal->colors[i].a;
815 if (alpha_value != SDL_ALPHA_OPAQUE) {
816 all_opaque = SDL_FALSE;
822 /* Palette is opaque, with an alpha channel */
823 *is_opaque = SDL_TRUE;
824 *has_alpha_channel = SDL_TRUE;
830 SDL_bool all_transparent = SDL_TRUE;
831 for (i = 0; i < pal->ncolors; i++) {
832 Uint8 alpha_value = pal->colors[i].a;
833 if (alpha_value != SDL_ALPHA_TRANSPARENT) {
834 all_transparent = SDL_FALSE;
839 if (all_transparent) {
840 /* Palette is opaque, without an alpha channel */
841 *is_opaque = SDL_TRUE;
842 *has_alpha_channel = SDL_FALSE;
847 /* Palette has alpha values */
848 *is_opaque = SDL_FALSE;
849 *has_alpha_channel = SDL_TRUE;
853 /* Find the opaque pixel value corresponding to an RGB triple */
855 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
857 if (format->palette == NULL) {
858 return (r >> format->Rloss) << format->Rshift
859 | (g >> format->Gloss) << format->Gshift
860 | (b >> format->Bloss) << format->Bshift | format->Amask;
862 return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
866 /* Find the pixel value corresponding to an RGBA quadruple */
868 SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
871 if (format->palette == NULL) {
872 return (r >> format->Rloss) << format->Rshift
873 | (g >> format->Gloss) << format->Gshift
874 | (b >> format->Bloss) << format->Bshift
875 | ((a >> format->Aloss) << format->Ashift & format->Amask);
877 return SDL_FindColor(format->palette, r, g, b, a);
882 SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
885 if (format->palette == NULL) {
887 v = (pixel & format->Rmask) >> format->Rshift;
888 *r = SDL_expand_byte[format->Rloss][v];
889 v = (pixel & format->Gmask) >> format->Gshift;
890 *g = SDL_expand_byte[format->Gloss][v];
891 v = (pixel & format->Bmask) >> format->Bshift;
892 *b = SDL_expand_byte[format->Bloss][v];
894 if (pixel < (unsigned)format->palette->ncolors) {
895 *r = format->palette->colors[pixel].r;
896 *g = format->palette->colors[pixel].g;
897 *b = format->palette->colors[pixel].b;
905 SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
906 Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
908 if (format->palette == NULL) {
910 v = (pixel & format->Rmask) >> format->Rshift;
911 *r = SDL_expand_byte[format->Rloss][v];
912 v = (pixel & format->Gmask) >> format->Gshift;
913 *g = SDL_expand_byte[format->Gloss][v];
914 v = (pixel & format->Bmask) >> format->Bshift;
915 *b = SDL_expand_byte[format->Bloss][v];
916 v = (pixel & format->Amask) >> format->Ashift;
917 *a = SDL_expand_byte[format->Aloss][v];
919 if (pixel < (unsigned)format->palette->ncolors) {
920 *r = format->palette->colors[pixel].r;
921 *g = format->palette->colors[pixel].g;
922 *b = format->palette->colors[pixel].b;
923 *a = format->palette->colors[pixel].a;
925 *r = *g = *b = *a = 0;
930 /* Map from Palette to Palette */
932 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
938 if (src->ncolors <= dst->ncolors) {
939 /* If an identical palette, no need to map */
943 (src->colors, dst->colors,
944 src->ncolors * sizeof(SDL_Color)) == 0)) {
951 map = (Uint8 *) SDL_calloc(SDL_CallocNumber, sizeof(Uint8));
956 for (i = 0; i < src->ncolors; ++i) {
957 map[i] = SDL_FindColor(dst,
958 src->colors[i].r, src->colors[i].g,
959 src->colors[i].b, src->colors[i].a);
964 /* Map from Palette to BitField */
966 Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
967 SDL_PixelFormat * dst)
972 SDL_Palette *pal = src->palette;
974 bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
975 map = (Uint8 *) SDL_calloc(SDL_CallocNumber, bpp);
981 /* We memory copy to the pixel map so the endianness is preserved */
982 for (i = 0; i < pal->ncolors; ++i) {
983 Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
984 Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
985 Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
986 Uint8 A = (Uint8) ((pal->colors[i].a * Amod) / 255);
987 ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
992 /* Map from BitField to Dithered-Palette to Palette */
994 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
996 /* Generate a 256 color dither palette */
997 SDL_Palette dithered;
998 SDL_Color colors[256];
999 SDL_Palette *pal = dst->palette;
1001 dithered.ncolors = 256;
1002 SDL_DitherColors(colors, 8);
1003 dithered.colors = colors;
1004 return (Map1to1(&dithered, pal, identical));
1008 SDL_AllocBlitMap(void)
1012 /* Allocate the empty map */
1013 map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
1023 /* It's ready to go */
1028 typedef struct SDL_ListNode
1031 struct SDL_ListNode *next;
1035 SDL_InvalidateAllBlitMap(SDL_Surface *surface)
1037 SDL_ListNode *l = surface->list_blitmap;
1039 surface->list_blitmap = NULL;
1042 SDL_ListNode *tmp = l;
1043 SDL_InvalidateMap((SDL_BlitMap *)l->entry);
1049 static void SDL_ListAdd(SDL_ListNode **head, void *ent);
1050 static void SDL_ListRemove(SDL_ListNode **head, void *ent);
1053 SDL_ListAdd(SDL_ListNode **head, void *ent)
1055 SDL_ListNode *node = SDL_malloc(sizeof (*node));
1068 SDL_ListRemove(SDL_ListNode **head, void *ent)
1070 SDL_ListNode **ptr = head;
1073 if ((*ptr)->entry == ent) {
1074 SDL_ListNode *tmp = *ptr;
1075 *ptr = (*ptr)->next;
1079 ptr = &(*ptr)->next;
1084 SDL_InvalidateMap(SDL_BlitMap * map)
1090 /* Un-register from the destination surface */
1091 SDL_ListRemove((SDL_ListNode **)&(map->dst->list_blitmap), map);
1094 map->src_palette_version = 0;
1095 map->dst_palette_version = 0;
1096 SDL_free(map->info.table);
1097 map->info.table = NULL;
1101 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
1103 SDL_PixelFormat *srcfmt;
1104 SDL_PixelFormat *dstfmt;
1107 /* Clear out any previous mapping */
1110 if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
1111 SDL_UnRLESurface(src, 1);
1114 SDL_InvalidateMap(map);
1116 /* Figure out what kind of mapping we're doing */
1118 srcfmt = src->format;
1119 dstfmt = dst->format;
1120 if (SDL_ISPIXELFORMAT_INDEXED(srcfmt->format)) {
1121 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
1122 /* Palette --> Palette */
1124 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
1125 if (!map->identity) {
1126 if (map->info.table == NULL) {
1130 if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
1133 /* Palette --> BitField */
1135 Map1toN(srcfmt, src->map->info.r, src->map->info.g,
1136 src->map->info.b, src->map->info.a, dstfmt);
1137 if (map->info.table == NULL) {
1142 if (SDL_ISPIXELFORMAT_INDEXED(dstfmt->format)) {
1143 /* BitField --> Palette */
1144 map->info.table = MapNto1(srcfmt, dstfmt, &map->identity);
1145 if (!map->identity) {
1146 if (map->info.table == NULL) {
1150 map->identity = 0; /* Don't optimize to copy */
1152 /* BitField --> BitField */
1153 if (srcfmt == dstfmt) {
1162 /* Register BlitMap to the destination surface, to be invalidated when needed */
1163 SDL_ListAdd((SDL_ListNode **)&(map->dst->list_blitmap), map);
1166 if (dstfmt->palette) {
1167 map->dst_palette_version = dstfmt->palette->version;
1169 map->dst_palette_version = 0;
1172 if (srcfmt->palette) {
1173 map->src_palette_version = srcfmt->palette->version;
1175 map->src_palette_version = 0;
1178 /* Choose your blitters wisely */
1179 return (SDL_CalculateBlit(src));
1183 SDL_FreeBlitMap(SDL_BlitMap * map)
1186 SDL_InvalidateMap(map);
1192 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
1196 /* Input validation */
1197 if (gamma < 0.0f ) {
1198 SDL_InvalidParamError("gamma");
1202 SDL_InvalidParamError("ramp");
1206 /* 0.0 gamma is all black */
1207 if (gamma == 0.0f) {
1208 SDL_memset(ramp, 0, 256 * sizeof(Uint16));
1210 } else if (gamma == 1.0f) {
1211 /* 1.0 gamma is identity */
1212 for (i = 0; i < 256; ++i) {
1213 ramp[i] = (i << 8) | i;
1217 /* Calculate a real gamma ramp */
1219 gamma = 1.0f / gamma;
1220 for (i = 0; i < 256; ++i) {
1222 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
1223 if (value > 65535) {
1226 ramp[i] = (Uint16) value;
1231 /* vi: set ts=4 sw=4 expandtab: */