Fix SSMS issue
[platform/upstream/SDL.git] / src / video / SDL_pixels.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 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 #define SDL_CallocNumber 256
33
34 /* Lookup tables to expand partial bytes to the full 0..255 range */
35
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
38 };
39
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
42 };
43
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
46 };
47
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
50 };
51
52 static Uint8 lookup_4[] = {
53 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255
54 };
55
56 static Uint8 lookup_5[] = {
57 0, 36, 72, 109, 145, 182, 218, 255
58 };
59
60 static Uint8 lookup_6[] = {
61 0, 85, 170, 255
62 };
63
64 static Uint8 lookup_7[] = {
65 0, 255
66 };
67
68 static Uint8 lookup_8[] = {
69 255
70 };
71
72 Uint8* SDL_expand_byte[9] = {
73     lookup_0,
74     lookup_1,
75     lookup_2,
76     lookup_3,
77     lookup_4,
78     lookup_5,
79     lookup_6,
80     lookup_7,
81     lookup_8
82 };
83
84 /* Helper functions */
85
86 const char*
87 SDL_GetPixelFormatName(Uint32 format)
88 {
89     switch (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)
129 #undef CASE
130     default:
131         return "SDL_PIXELFORMAT_UNKNOWN";
132     }
133 }
134
135 SDL_bool
136 SDL_PixelFormatEnumToMasks(Uint32 format, int *bpp, Uint32 * Rmask,
137                            Uint32 * Gmask, Uint32 * Bmask, Uint32 * Amask)
138 {
139     Uint32 masks[4];
140
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");
144         return SDL_FALSE;
145     }
146
147     /* Initialize the values here */
148     if (SDL_BYTESPERPIXEL(format) <= 2) {
149         *bpp = SDL_BITSPERPIXEL(format);
150     } else {
151         *bpp = SDL_BYTESPERPIXEL(format) * 8;
152     }
153     *Rmask = *Gmask = *Bmask = *Amask = 0;
154
155     if (format == SDL_PIXELFORMAT_RGB24) {
156 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
157         *Rmask = 0x00FF0000;
158         *Gmask = 0x0000FF00;
159         *Bmask = 0x000000FF;
160 #else
161         *Rmask = 0x000000FF;
162         *Gmask = 0x0000FF00;
163         *Bmask = 0x00FF0000;
164 #endif
165         return SDL_TRUE;
166     }
167
168     if (format == SDL_PIXELFORMAT_BGR24) {
169 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
170         *Rmask = 0x000000FF;
171         *Gmask = 0x0000FF00;
172         *Bmask = 0x00FF0000;
173 #else
174         *Rmask = 0x00FF0000;
175         *Gmask = 0x0000FF00;
176         *Bmask = 0x000000FF;
177 #endif
178         return SDL_TRUE;
179     }
180
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 */
185         return SDL_TRUE;
186     }
187
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;
194         break;
195     case SDL_PACKEDLAYOUT_4444:
196         masks[0] = 0x0000F000;
197         masks[1] = 0x00000F00;
198         masks[2] = 0x000000F0;
199         masks[3] = 0x0000000F;
200         break;
201     case SDL_PACKEDLAYOUT_1555:
202         masks[0] = 0x00008000;
203         masks[1] = 0x00007C00;
204         masks[2] = 0x000003E0;
205         masks[3] = 0x0000001F;
206         break;
207     case SDL_PACKEDLAYOUT_5551:
208         masks[0] = 0x0000F800;
209         masks[1] = 0x000007C0;
210         masks[2] = 0x0000003E;
211         masks[3] = 0x00000001;
212         break;
213     case SDL_PACKEDLAYOUT_565:
214         masks[0] = 0x00000000;
215         masks[1] = 0x0000F800;
216         masks[2] = 0x000007E0;
217         masks[3] = 0x0000001F;
218         break;
219     case SDL_PACKEDLAYOUT_8888:
220         masks[0] = 0xFF000000;
221         masks[1] = 0x00FF0000;
222         masks[2] = 0x0000FF00;
223         masks[3] = 0x000000FF;
224         break;
225     case SDL_PACKEDLAYOUT_2101010:
226         masks[0] = 0xC0000000;
227         masks[1] = 0x3FF00000;
228         masks[2] = 0x000FFC00;
229         masks[3] = 0x000003FF;
230         break;
231     case SDL_PACKEDLAYOUT_1010102:
232         masks[0] = 0xFFC00000;
233         masks[1] = 0x003FF000;
234         masks[2] = 0x00000FFC;
235         masks[3] = 0x00000003;
236         break;
237     default:
238         SDL_SetError("Unknown pixel format");
239         return SDL_FALSE;
240     }
241
242     switch (SDL_PIXELORDER(format)) {
243     case SDL_PACKEDORDER_XRGB:
244         *Rmask = masks[1];
245         *Gmask = masks[2];
246         *Bmask = masks[3];
247         break;
248     case SDL_PACKEDORDER_RGBX:
249         *Rmask = masks[0];
250         *Gmask = masks[1];
251         *Bmask = masks[2];
252         break;
253     case SDL_PACKEDORDER_ARGB:
254         *Amask = masks[0];
255         *Rmask = masks[1];
256         *Gmask = masks[2];
257         *Bmask = masks[3];
258         break;
259     case SDL_PACKEDORDER_RGBA:
260         *Rmask = masks[0];
261         *Gmask = masks[1];
262         *Bmask = masks[2];
263         *Amask = masks[3];
264         break;
265     case SDL_PACKEDORDER_XBGR:
266         *Bmask = masks[1];
267         *Gmask = masks[2];
268         *Rmask = masks[3];
269         break;
270     case SDL_PACKEDORDER_BGRX:
271         *Bmask = masks[0];
272         *Gmask = masks[1];
273         *Rmask = masks[2];
274         break;
275     case SDL_PACKEDORDER_BGRA:
276         *Bmask = masks[0];
277         *Gmask = masks[1];
278         *Rmask = masks[2];
279         *Amask = masks[3];
280         break;
281     case SDL_PACKEDORDER_ABGR:
282         *Amask = masks[0];
283         *Bmask = masks[1];
284         *Gmask = masks[2];
285         *Rmask = masks[3];
286         break;
287     default:
288         SDL_SetError("Unknown pixel format");
289         return SDL_FALSE;
290     }
291     return SDL_TRUE;
292 }
293
294 Uint32
295 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
296                            Uint32 Amask)
297 {
298     switch (bpp) {
299     case 1:
300         /* SDL defaults to MSB ordering */
301         return SDL_PIXELFORMAT_INDEX1MSB;
302     case 4:
303         /* SDL defaults to MSB ordering */
304         return SDL_PIXELFORMAT_INDEX4MSB;
305     case 8:
306         if (Rmask == 0) {
307             return SDL_PIXELFORMAT_INDEX8;
308         }
309         if (Rmask == 0xE0 &&
310             Gmask == 0x1C &&
311             Bmask == 0x03 &&
312             Amask == 0x00) {
313             return SDL_PIXELFORMAT_RGB332;
314         }
315         break;
316     case 12:
317         if (Rmask == 0) {
318             return SDL_PIXELFORMAT_RGB444;
319         }
320         if (Rmask == 0x0F00 &&
321             Gmask == 0x00F0 &&
322             Bmask == 0x000F &&
323             Amask == 0x0000) {
324             return SDL_PIXELFORMAT_RGB444;
325         }
326         if (Rmask == 0x000F &&
327             Gmask == 0x00F0 &&
328             Bmask == 0x0F00 &&
329             Amask == 0x0000) {
330             return SDL_PIXELFORMAT_BGR444;
331         }
332         break;
333     case 15:
334         if (Rmask == 0) {
335             return SDL_PIXELFORMAT_RGB555;
336         }
337     /* fallthrough */
338     case 16:
339         if (Rmask == 0) {
340             return SDL_PIXELFORMAT_RGB565;
341         }
342         if (Rmask == 0x7C00 &&
343             Gmask == 0x03E0 &&
344             Bmask == 0x001F &&
345             Amask == 0x0000) {
346             return SDL_PIXELFORMAT_RGB555;
347         }
348         if (Rmask == 0x001F &&
349             Gmask == 0x03E0 &&
350             Bmask == 0x7C00 &&
351             Amask == 0x0000) {
352             return SDL_PIXELFORMAT_BGR555;
353         }
354         if (Rmask == 0x0F00 &&
355             Gmask == 0x00F0 &&
356             Bmask == 0x000F &&
357             Amask == 0xF000) {
358             return SDL_PIXELFORMAT_ARGB4444;
359         }
360         if (Rmask == 0xF000 &&
361             Gmask == 0x0F00 &&
362             Bmask == 0x00F0 &&
363             Amask == 0x000F) {
364             return SDL_PIXELFORMAT_RGBA4444;
365         }
366         if (Rmask == 0x000F &&
367             Gmask == 0x00F0 &&
368             Bmask == 0x0F00 &&
369             Amask == 0xF000) {
370             return SDL_PIXELFORMAT_ABGR4444;
371         }
372         if (Rmask == 0x00F0 &&
373             Gmask == 0x0F00 &&
374             Bmask == 0xF000 &&
375             Amask == 0x000F) {
376             return SDL_PIXELFORMAT_BGRA4444;
377         }
378         if (Rmask == 0x7C00 &&
379             Gmask == 0x03E0 &&
380             Bmask == 0x001F &&
381             Amask == 0x8000) {
382             return SDL_PIXELFORMAT_ARGB1555;
383         }
384         if (Rmask == 0xF800 &&
385             Gmask == 0x07C0 &&
386             Bmask == 0x003E &&
387             Amask == 0x0001) {
388             return SDL_PIXELFORMAT_RGBA5551;
389         }
390         if (Rmask == 0x001F &&
391             Gmask == 0x03E0 &&
392             Bmask == 0x7C00 &&
393             Amask == 0x8000) {
394             return SDL_PIXELFORMAT_ABGR1555;
395         }
396         if (Rmask == 0x003E &&
397             Gmask == 0x07C0 &&
398             Bmask == 0xF800 &&
399             Amask == 0x0001) {
400             return SDL_PIXELFORMAT_BGRA5551;
401         }
402         if (Rmask == 0xF800 &&
403             Gmask == 0x07E0 &&
404             Bmask == 0x001F &&
405             Amask == 0x0000) {
406             return SDL_PIXELFORMAT_RGB565;
407         }
408         if (Rmask == 0x001F &&
409             Gmask == 0x07E0 &&
410             Bmask == 0xF800 &&
411             Amask == 0x0000) {
412             return SDL_PIXELFORMAT_BGR565;
413         }
414         if (Rmask == 0x003F &&
415             Gmask == 0x07C0 &&
416             Bmask == 0xF800 &&
417             Amask == 0x0000) {
418             /* Technically this would be BGR556, but Witek says this works in bug 3158 */
419             return SDL_PIXELFORMAT_RGB565;
420         }
421         break;
422     case 24:
423         switch (Rmask) {
424         case 0:
425         case 0x00FF0000:
426 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
427             return SDL_PIXELFORMAT_RGB24;
428 #else
429             return SDL_PIXELFORMAT_BGR24;
430 #endif
431         case 0x000000FF:
432 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
433             return SDL_PIXELFORMAT_BGR24;
434 #else
435             return SDL_PIXELFORMAT_RGB24;
436 #endif
437         }
438     case 32:
439         if (Rmask == 0) {
440             return SDL_PIXELFORMAT_RGB888;
441         }
442         if (Rmask == 0x00FF0000 &&
443             Gmask == 0x0000FF00 &&
444             Bmask == 0x000000FF &&
445             Amask == 0x00000000) {
446             return SDL_PIXELFORMAT_RGB888;
447         }
448         if (Rmask == 0xFF000000 &&
449             Gmask == 0x00FF0000 &&
450             Bmask == 0x0000FF00 &&
451             Amask == 0x00000000) {
452             return SDL_PIXELFORMAT_RGBX8888;
453         }
454         if (Rmask == 0x000000FF &&
455             Gmask == 0x0000FF00 &&
456             Bmask == 0x00FF0000 &&
457             Amask == 0x00000000) {
458             return SDL_PIXELFORMAT_BGR888;
459         }
460         if (Rmask == 0x0000FF00 &&
461             Gmask == 0x00FF0000 &&
462             Bmask == 0xFF000000 &&
463             Amask == 0x00000000) {
464             return SDL_PIXELFORMAT_BGRX8888;
465         }
466         if (Rmask == 0x00FF0000 &&
467             Gmask == 0x0000FF00 &&
468             Bmask == 0x000000FF &&
469             Amask == 0xFF000000) {
470             return SDL_PIXELFORMAT_ARGB8888;
471         }
472         if (Rmask == 0xFF000000 &&
473             Gmask == 0x00FF0000 &&
474             Bmask == 0x0000FF00 &&
475             Amask == 0x000000FF) {
476             return SDL_PIXELFORMAT_RGBA8888;
477         }
478         if (Rmask == 0x000000FF &&
479             Gmask == 0x0000FF00 &&
480             Bmask == 0x00FF0000 &&
481             Amask == 0xFF000000) {
482             return SDL_PIXELFORMAT_ABGR8888;
483         }
484         if (Rmask == 0x0000FF00 &&
485             Gmask == 0x00FF0000 &&
486             Bmask == 0xFF000000 &&
487             Amask == 0x000000FF) {
488             return SDL_PIXELFORMAT_BGRA8888;
489         }
490         if (Rmask == 0x3FF00000 &&
491             Gmask == 0x000FFC00 &&
492             Bmask == 0x000003FF &&
493             Amask == 0xC0000000) {
494             return SDL_PIXELFORMAT_ARGB2101010;
495         }
496     }
497     return SDL_PIXELFORMAT_UNKNOWN;
498 }
499
500 static SDL_PixelFormat *formats;
501 static SDL_SpinLock formats_lock = 0;
502
503 SDL_PixelFormat *
504 SDL_AllocFormat(Uint32 pixel_format)
505 {
506     SDL_PixelFormat *format;
507
508     SDL_AtomicLock(&formats_lock);
509
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) {
513             ++format->refcount;
514             SDL_AtomicUnlock(&formats_lock);
515             return format;
516         }
517     }
518
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);
523         SDL_OutOfMemory();
524         return NULL;
525     }
526     if (SDL_InitFormat(format, pixel_format) < 0) {
527         SDL_AtomicUnlock(&formats_lock);
528         SDL_free(format);
529         SDL_InvalidParamError("format");
530         return NULL;
531     }
532
533     if (!SDL_ISPIXELFORMAT_INDEXED(pixel_format)) {
534         /* Cache the RGB formats */
535         format->next = formats;
536         formats = format;
537     }
538
539     SDL_AtomicUnlock(&formats_lock);
540
541     return format;
542 }
543
544 int
545 SDL_InitFormat(SDL_PixelFormat * format, Uint32 pixel_format)
546 {
547     int bpp;
548     Uint32 Rmask, Gmask, Bmask, Amask;
549     Uint32 mask;
550
551     if (!SDL_PixelFormatEnumToMasks(pixel_format, &bpp,
552                                     &Rmask, &Gmask, &Bmask, &Amask)) {
553         return -1;
554     }
555
556     /* Set up the format */
557     SDL_zerop(format);
558     format->format = pixel_format;
559     format->BitsPerPixel = bpp;
560     format->BytesPerPixel = (bpp + 7) / 8;
561
562     format->Rmask = Rmask;
563     format->Rshift = 0;
564     format->Rloss = 8;
565     if (Rmask) {
566         for (mask = Rmask; !(mask & 0x01); mask >>= 1)
567             ++format->Rshift;
568         for (; (mask & 0x01); mask >>= 1)
569             --format->Rloss;
570     }
571
572     format->Gmask = Gmask;
573     format->Gshift = 0;
574     format->Gloss = 8;
575     if (Gmask) {
576         for (mask = Gmask; !(mask & 0x01); mask >>= 1)
577             ++format->Gshift;
578         for (; (mask & 0x01); mask >>= 1)
579             --format->Gloss;
580     }
581
582     format->Bmask = Bmask;
583     format->Bshift = 0;
584     format->Bloss = 8;
585     if (Bmask) {
586         for (mask = Bmask; !(mask & 0x01); mask >>= 1)
587             ++format->Bshift;
588         for (; (mask & 0x01); mask >>= 1)
589             --format->Bloss;
590     }
591
592     format->Amask = Amask;
593     format->Ashift = 0;
594     format->Aloss = 8;
595     if (Amask) {
596         for (mask = Amask; !(mask & 0x01); mask >>= 1)
597             ++format->Ashift;
598         for (; (mask & 0x01); mask >>= 1)
599             --format->Aloss;
600     }
601
602     format->palette = NULL;
603     format->refcount = 1;
604     format->next = NULL;
605
606     return 0;
607 }
608
609 void
610 SDL_FreeFormat(SDL_PixelFormat *format)
611 {
612     SDL_PixelFormat *prev;
613
614     if (!format) {
615         SDL_InvalidParamError("format");
616         return;
617     }
618
619     SDL_AtomicLock(&formats_lock);
620
621     if (--format->refcount > 0) {
622         SDL_AtomicUnlock(&formats_lock);
623         return;
624     }
625
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;
633                 break;
634             }
635         }
636     }
637
638     SDL_AtomicUnlock(&formats_lock);
639
640     if (format->palette) {
641         SDL_FreePalette(format->palette);
642     }
643     SDL_free(format);
644 }
645
646 SDL_Palette *
647 SDL_AllocPalette(int ncolors)
648 {
649     SDL_Palette *palette;
650
651     /* Input validation */
652     if (ncolors < 1) {
653       SDL_InvalidParamError("ncolors");
654       return NULL;
655     }
656
657     palette = (SDL_Palette *) SDL_malloc(sizeof(*palette));
658     if (!palette) {
659         SDL_OutOfMemory();
660         return NULL;
661     }
662     palette->colors =
663         (SDL_Color *) SDL_malloc(ncolors * sizeof(*palette->colors));
664     if (!palette->colors) {
665         SDL_free(palette);
666         return NULL;
667     }
668     palette->ncolors = ncolors;
669     palette->version = 1;
670     palette->refcount = 1;
671
672     SDL_memset(palette->colors, 0xFF, ncolors * sizeof(*palette->colors));
673
674     return palette;
675 }
676
677 int
678 SDL_SetPixelFormatPalette(SDL_PixelFormat * format, SDL_Palette *palette)
679 {
680     if (!format) {
681         return SDL_SetError("SDL_SetPixelFormatPalette() passed NULL format");
682     }
683
684     if (palette && palette->ncolors > (1 << format->BitsPerPixel)) {
685         return SDL_SetError("SDL_SetPixelFormatPalette() passed a palette that doesn't match the format");
686     }
687
688     if (format->palette == palette) {
689         return 0;
690     }
691
692     if (format->palette) {
693         SDL_FreePalette(format->palette);
694     }
695
696     format->palette = palette;
697
698     if (format->palette) {
699         ++format->palette->refcount;
700     }
701
702     return 0;
703 }
704
705 int
706 SDL_SetPaletteColors(SDL_Palette * palette, const SDL_Color * colors,
707                      int firstcolor, int ncolors)
708 {
709     int status = 0;
710
711     /* Verify the parameters */
712     if (!palette) {
713         return -1;
714     }
715     if (ncolors > (palette->ncolors - firstcolor)) {
716         ncolors = (palette->ncolors - firstcolor);
717         status = -1;
718     }
719
720     if (colors != (palette->colors + firstcolor)) {
721         SDL_memcpy(palette->colors + firstcolor, colors,
722                    ncolors * sizeof(*colors));
723     }
724     ++palette->version;
725     if (!palette->version) {
726         palette->version = 1;
727     }
728
729     return status;
730 }
731
732 void
733 SDL_FreePalette(SDL_Palette * palette)
734 {
735     if (!palette) {
736         SDL_InvalidParamError("palette");
737         return;
738     }
739     if (--palette->refcount > 0) {
740         return;
741     }
742     SDL_free(palette->colors);
743     SDL_free(palette);
744 }
745
746 /*
747  * Calculate an 8-bit (3 red, 3 green, 2 blue) dithered palette of colors
748  */
749 void
750 SDL_DitherColors(SDL_Color * colors, int bpp)
751 {
752     int i;
753     if (bpp != 8)
754         return;                 /* only 8bpp supported right now */
755
756     for (i = 0; i < 256; i++) {
757         int r, g, b;
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) */
760         r = i & 0xe0;
761         r |= r >> 3 | r >> 6;
762         colors[i].r = r;
763         g = (i << 3) & 0xe0;
764         g |= g >> 3 | g >> 6;
765         colors[i].g = g;
766         b = i & 0x3;
767         b |= b << 2;
768         b |= b << 4;
769         colors[i].b = b;
770         colors[i].a = SDL_ALPHA_OPAQUE;
771     }
772 }
773
774 /*
775  * Match an RGB value to a particular palette index
776  */
777 Uint8
778 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
779 {
780     /* Do colorspace distance matching */
781     unsigned int smallest;
782     unsigned int distance;
783     int rd, gd, bd, ad;
784     int i;
785     Uint8 pixel = 0;
786
787     smallest = ~0;
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) {
795             pixel = i;
796             if (distance == 0) {        /* Perfect match! */
797                 break;
798             }
799             smallest = distance;
800         }
801     }
802     return (pixel);
803 }
804
805 /* Tell whether palette is opaque, and if it has an alpha_channel */
806 void
807 SDL_DetectPalette(SDL_Palette *pal, SDL_bool *is_opaque, SDL_bool *has_alpha_channel)
808 {
809     int i;
810
811     {
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;
817                 break;
818             }
819         }
820
821         if (all_opaque) {
822             /* Palette is opaque, with an alpha channel */
823             *is_opaque = SDL_TRUE;
824             *has_alpha_channel = SDL_TRUE;
825             return;
826         }
827     }
828
829     {
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;
835                 break;
836             }
837         }
838
839         if (all_transparent) {
840             /* Palette is opaque, without an alpha channel */
841             *is_opaque = SDL_TRUE;
842             *has_alpha_channel = SDL_FALSE;
843             return;
844         }
845     }
846
847     /* Palette has alpha values */
848     *is_opaque = SDL_FALSE;
849     *has_alpha_channel = SDL_TRUE;
850 }
851
852
853 /* Find the opaque pixel value corresponding to an RGB triple */
854 Uint32
855 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b)
856 {
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;
861     } else {
862         return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
863     }
864 }
865
866 /* Find the pixel value corresponding to an RGBA quadruple */
867 Uint32
868 SDL_MapRGBA(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b,
869             Uint8 a)
870 {
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);
876     } else {
877         return SDL_FindColor(format->palette, r, g, b, a);
878     }
879 }
880
881 void
882 SDL_GetRGB(Uint32 pixel, const SDL_PixelFormat * format, Uint8 * r, Uint8 * g,
883            Uint8 * b)
884 {
885     if (format->palette == NULL) {
886         unsigned v;
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];
893     } else {
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;
898         } else {
899             *r = *g = *b = 0;
900         }
901     }
902 }
903
904 void
905 SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormat * format,
906             Uint8 * r, Uint8 * g, Uint8 * b, Uint8 * a)
907 {
908     if (format->palette == NULL) {
909         unsigned v;
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];
918     } else {
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;
924         } else {
925             *r = *g = *b = *a = 0;
926         }
927     }
928 }
929
930 /* Map from Palette to Palette */
931 static Uint8 *
932 Map1to1(SDL_Palette * src, SDL_Palette * dst, int *identical)
933 {
934     Uint8 *map;
935     int i;
936
937     if (identical) {
938         if (src->ncolors <= dst->ncolors) {
939             /* If an identical palette, no need to map */
940             if (src == dst
941                 ||
942                 (SDL_memcmp
943                  (src->colors, dst->colors,
944                   src->ncolors * sizeof(SDL_Color)) == 0)) {
945                 *identical = 1;
946                 return (NULL);
947             }
948         }
949         *identical = 0;
950     }
951     map = (Uint8 *) SDL_calloc(SDL_CallocNumber, sizeof(Uint8));
952     if (map == NULL) {
953         SDL_OutOfMemory();
954         return (NULL);
955     }
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);
960     }
961     return (map);
962 }
963
964 /* Map from Palette to BitField */
965 static Uint8 *
966 Map1toN(SDL_PixelFormat * src, Uint8 Rmod, Uint8 Gmod, Uint8 Bmod, Uint8 Amod,
967         SDL_PixelFormat * dst)
968 {
969     Uint8 *map;
970     int i;
971     int bpp;
972     SDL_Palette *pal = src->palette;
973
974     bpp = ((dst->BytesPerPixel == 3) ? 4 : dst->BytesPerPixel);
975     map = (Uint8 *) SDL_calloc(SDL_CallocNumber, bpp);
976     if (map == NULL) {
977         SDL_OutOfMemory();
978         return (NULL);
979     }
980
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);
988     }
989     return (map);
990 }
991
992 /* Map from BitField to Dithered-Palette to Palette */
993 static Uint8 *
994 MapNto1(SDL_PixelFormat * src, SDL_PixelFormat * dst, int *identical)
995 {
996     /* Generate a 256 color dither palette */
997     SDL_Palette dithered;
998     SDL_Color colors[256];
999     SDL_Palette *pal = dst->palette;
1000
1001     dithered.ncolors = 256;
1002     SDL_DitherColors(colors, 8);
1003     dithered.colors = colors;
1004     return (Map1to1(&dithered, pal, identical));
1005 }
1006
1007 SDL_BlitMap *
1008 SDL_AllocBlitMap(void)
1009 {
1010     SDL_BlitMap *map;
1011
1012     /* Allocate the empty map */
1013     map = (SDL_BlitMap *) SDL_calloc(1, sizeof(*map));
1014     if (map == NULL) {
1015         SDL_OutOfMemory();
1016         return (NULL);
1017     }
1018     map->info.r = 0xFF;
1019     map->info.g = 0xFF;
1020     map->info.b = 0xFF;
1021     map->info.a = 0xFF;
1022
1023     /* It's ready to go */
1024     return (map);
1025 }
1026
1027
1028 typedef struct SDL_ListNode
1029 {
1030     void *entry;
1031     struct SDL_ListNode *next;
1032 } SDL_ListNode;
1033
1034 void
1035 SDL_InvalidateAllBlitMap(SDL_Surface *surface)
1036 {
1037     SDL_ListNode *l = surface->list_blitmap;
1038
1039     surface->list_blitmap = NULL;
1040
1041     while (l) {
1042         SDL_ListNode *tmp = l;
1043         SDL_InvalidateMap((SDL_BlitMap *)l->entry);
1044         l = l->next;
1045         SDL_free(tmp);
1046     }
1047 }
1048
1049 static void SDL_ListAdd(SDL_ListNode **head, void *ent);
1050 static void SDL_ListRemove(SDL_ListNode **head, void *ent);
1051
1052 void
1053 SDL_ListAdd(SDL_ListNode **head, void *ent)
1054 {
1055     SDL_ListNode *node = SDL_malloc(sizeof (*node));
1056
1057     if (node == NULL) {
1058         SDL_OutOfMemory();
1059         return;
1060     }
1061
1062     node->entry = ent;
1063     node->next = *head;
1064     *head = node;
1065 }
1066
1067 void
1068 SDL_ListRemove(SDL_ListNode **head, void *ent)
1069 {
1070     SDL_ListNode **ptr = head;
1071
1072     while (*ptr) {
1073         if ((*ptr)->entry == ent) {
1074             SDL_ListNode *tmp = *ptr;
1075             *ptr = (*ptr)->next;
1076             SDL_free(tmp);
1077             return;
1078         }
1079         ptr = &(*ptr)->next;
1080     }
1081 }
1082
1083 void
1084 SDL_InvalidateMap(SDL_BlitMap * map)
1085 {
1086     if (!map) {
1087         return;
1088     }
1089     if (map->dst) {
1090         /* Un-register from the destination surface */
1091         SDL_ListRemove((SDL_ListNode **)&(map->dst->list_blitmap), map);
1092     }
1093     map->dst = NULL;
1094     map->src_palette_version = 0;
1095     map->dst_palette_version = 0;
1096     SDL_free(map->info.table);
1097     map->info.table = NULL;
1098 }
1099
1100 int
1101 SDL_MapSurface(SDL_Surface * src, SDL_Surface * dst)
1102 {
1103     SDL_PixelFormat *srcfmt;
1104     SDL_PixelFormat *dstfmt;
1105     SDL_BlitMap *map;
1106
1107     /* Clear out any previous mapping */
1108     map = src->map;
1109 #if SDL_HAVE_RLE
1110     if ((src->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
1111         SDL_UnRLESurface(src, 1);
1112     }
1113 #endif
1114     SDL_InvalidateMap(map);
1115
1116     /* Figure out what kind of mapping we're doing */
1117     map->identity = 0;
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 */
1123             map->info.table =
1124                 Map1to1(srcfmt->palette, dstfmt->palette, &map->identity);
1125             if (!map->identity) {
1126                 if (map->info.table == NULL) {
1127                     return (-1);
1128                 }
1129             }
1130             if (srcfmt->BitsPerPixel != dstfmt->BitsPerPixel)
1131                 map->identity = 0;
1132         } else {
1133             /* Palette --> BitField */
1134             map->info.table =
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) {
1138                 return (-1);
1139             }
1140         }
1141     } else {
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) {
1147                     return (-1);
1148                 }
1149             }
1150             map->identity = 0;  /* Don't optimize to copy */
1151         } else {
1152             /* BitField --> BitField */
1153             if (srcfmt == dstfmt) {
1154                 map->identity = 1;
1155             }
1156         }
1157     }
1158
1159     map->dst = dst;
1160
1161     if (map->dst) {
1162         /* Register BlitMap to the destination surface, to be invalidated when needed */
1163         SDL_ListAdd((SDL_ListNode **)&(map->dst->list_blitmap), map);
1164     }
1165
1166     if (dstfmt->palette) {
1167         map->dst_palette_version = dstfmt->palette->version;
1168     } else {
1169         map->dst_palette_version = 0;
1170     }
1171
1172     if (srcfmt->palette) {
1173         map->src_palette_version = srcfmt->palette->version;
1174     } else {
1175         map->src_palette_version = 0;
1176     }
1177
1178     /* Choose your blitters wisely */
1179     return (SDL_CalculateBlit(src));
1180 }
1181
1182 void
1183 SDL_FreeBlitMap(SDL_BlitMap * map)
1184 {
1185     if (map) {
1186         SDL_InvalidateMap(map);
1187         SDL_free(map);
1188     }
1189 }
1190
1191 void
1192 SDL_CalculateGammaRamp(float gamma, Uint16 * ramp)
1193 {
1194     int i;
1195
1196     /* Input validation */
1197     if (gamma < 0.0f ) {
1198       SDL_InvalidParamError("gamma");
1199       return;
1200     }
1201     if (ramp == NULL) {
1202       SDL_InvalidParamError("ramp");
1203       return;
1204     }
1205
1206     /* 0.0 gamma is all black */
1207     if (gamma == 0.0f) {
1208         SDL_memset(ramp, 0, 256 * sizeof(Uint16));
1209         return;
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;
1214         }
1215         return;
1216     } else {
1217         /* Calculate a real gamma ramp */
1218         int value;
1219         gamma = 1.0f / gamma;
1220         for (i = 0; i < 256; ++i) {
1221             value =
1222                 (int) (SDL_pow((double) i / 256.0, gamma) * 65535.0 + 0.5);
1223             if (value > 65535) {
1224                 value = 65535;
1225             }
1226             ramp[i] = (Uint16) value;
1227         }
1228     }
1229 }
1230
1231 /* vi: set ts=4 sw=4 expandtab: */