d905656cad71dc2f02230d9dd3986cf88ce009a7
[platform/upstream/SDL.git] / src / video / SDL_pixels.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 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: */