1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Pixel formats.
12  *
13  *      By Trent Gamblin.
14  *
15  *      See LICENSE.txt for copyright information.
16  */
17 
18 #include "allegro5/allegro.h"
19 #include "allegro5/internal/aintern_pixels.h"
20 
21 ALLEGRO_DEBUG_CHANNEL("pixels")
22 
23 
24 /* lookup table for scaling 8 bit integers up to floats [0.0, 1.0] */
25 #include "pixel_tables.inc"
26 
27 static int pixel_sizes[] = {
28    0, /* ALLEGRO_PIXEL_FORMAT_ANY */
29    0,
30    0,
31    2,
32    2,
33    2,
34    3,
35    4,
36    4,
37    4, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
38    4,
39    2,
40    3,
41    2,
42    2,
43    2,
44    2,
45    4,
46    4,
47    3,
48    2,
49    2,
50    4,
51    4,
52    16, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
53    4, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
54    2, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
55    1, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
56    0,
57    0,
58    0,
59 };
60 
61 static int pixel_bits[] = {
62    0, /* ALLEGRO_PIXEL_FORMAT_ANY */
63    0,
64    0,
65    15,
66    16,
67    16,
68    24,
69    32,
70    32,
71    32, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
72    32,
73    16,
74    24,
75    16,
76    15,
77    16,
78    16,
79    32,
80    32,
81    24,
82    16,
83    15,
84    32,
85    32,
86    128, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
87    32, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
88    16, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
89    8, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
90    0,
91    0,
92    0,
93 };
94 
95 static int pixel_block_widths[] = {
96    0, /* ALLEGRO_PIXEL_FORMAT_ANY */
97    0,
98    0,
99    1,
100    1,
101    1,
102    1,
103    1,
104    1,
105    1, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
106    1,
107    1,
108    1,
109    1,
110    1,
111    1,
112    1,
113    1,
114    1,
115    1,
116    1,
117    1,
118    1,
119    1,
120    1, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
121    1, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
122    1, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
123    1, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
124    4,
125    4,
126    4,
127 };
128 
129 static int pixel_block_heights[] = {
130    0, /* ALLEGRO_PIXEL_FORMAT_ANY */
131    0,
132    0,
133    1,
134    1,
135    1,
136    1,
137    1,
138    1,
139    1, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
140    1,
141    1,
142    1,
143    1,
144    1,
145    1,
146    1,
147    1,
148    1,
149    1,
150    1,
151    1,
152    1,
153    1,
154    1, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
155    1, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
156    1, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
157    1, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
158    4,
159    4,
160    4,
161 };
162 
163 static int pixel_block_sizes[] = {
164    0,  /* ALLEGRO_PIXEL_FORMAT_ANY */
165    0,
166    0,
167    2,
168    2,
169    2,
170    3,
171    4,
172    4,
173    4,  /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
174    4,
175    2,
176    3,
177    2,
178    2,
179    2,
180    2,
181    4,
182    4,
183    3,
184    2,
185    2,
186    4,
187    4,
188    16, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
189    4,  /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
190    2,  /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
191    1,  /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
192    8,
193    16,
194    16,
195 };
196 
197 static bool format_alpha_table[ALLEGRO_NUM_PIXEL_FORMATS] = {
198    false, /* neutral (ALLEGRO_PIXEL_FORMAT_ANY) */
199    false,
200    true,
201    false,
202    false,
203    true,
204    false,
205    false,
206    true,
207    true, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
208    true,
209    true,
210    false,
211    false,
212    false,
213    true,
214    true,
215    true,
216    false,
217    false,
218    false,
219    false,
220    false,
221    false,
222    true, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
223    true, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
224    true, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
225    false, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
226    true,
227    true,
228    true,
229 };
230 
231 static char const *pixel_format_names[ALLEGRO_NUM_PIXEL_FORMATS + 1] = {
232    "ANY",
233    "ANY_NO_ALPHA",
234    "ANY_WITH_ALPHA",
235    "ANY_15_NO_ALPHA",
236    "ANY_16_NO_ALPHA",
237    "ANY_16_WITH_ALPHA",
238    "ANY_24_NO_ALPHA",
239    "ANY_32_NO_ALPHA",
240    "ANY_32_WITH_ALPHA",
241    "ARGB_8888",
242    "RGBA_8888",
243    "ARGB_4444",
244    "RGB_888",
245    "RGB_565",
246    "RGB_555",
247    "RGBA_5551",
248    "ARGB_1555",
249    "ABGR_8888",
250    "XBGR_8888",
251    "BGR_888",
252    "BGR_565",
253    "BGR_555",
254    "RGBX_8888",
255    "XRGB_8888",
256    "ABGR_F32",
257    "ABGR_8888_LE",
258    "RGBA_4444",
259    "SINGLE_CHANNEL_8",
260    "RGBA_DXT1",
261    "RGBA_DXT3",
262    "RGBA_DXT5",
263    "INVALID"
264 };
265 
266 static bool format_is_real[ALLEGRO_NUM_PIXEL_FORMATS] =
267 {
268    false, /* ALLEGRO_PIXEL_FORMAT_ANY */
269    false,
270    false,
271    false,
272    false,
273    false,
274    false,
275    false,
276    false,
277    true, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
278    true,
279    true,
280    true,
281    true,
282    true,
283    true,
284    true,
285    true,
286    true,
287    true,
288    true,
289    true,
290    true,
291    true,
292    true, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
293    true, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
294    true, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
295    true, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
296    true,
297    true,
298    true,
299 };
300 
301 static bool format_is_video_only[ALLEGRO_NUM_PIXEL_FORMATS] =
302 {
303    false, /* ALLEGRO_PIXEL_FORMAT_ANY */
304    false,
305    false,
306    false,
307    false,
308    false,
309    false,
310    false,
311    false,
312    false, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
313    false,
314    false,
315    false,
316    false,
317    false,
318    false,
319    false,
320    false,
321    false,
322    false,
323    false,
324    false,
325    false,
326    false,
327    false, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
328    false, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
329    false, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
330    false, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
331    true,
332    true,
333    true,
334 };
335 
336 static bool format_is_compressed[ALLEGRO_NUM_PIXEL_FORMATS] =
337 {
338    false, /* ALLEGRO_PIXEL_FORMAT_ANY */
339    false,
340    false,
341    false,
342    false,
343    false,
344    false,
345    false,
346    false,
347    false, /* ALLEGRO_PIXEL_FORMAT_ARGB_8888 */
348    false,
349    false,
350    false,
351    false,
352    false,
353    false,
354    false,
355    false,
356    false,
357    false,
358    false,
359    false,
360    false,
361    false,
362    false, /* ALLEGRO_PIXEL_FORMAT_ABGR_F32 */
363    false, /* ALLEGRO_PIXEL_FORMAT_ABGR_LE */
364    false, /* ALLEGRO_PIXEL_FORMAT_RGBA_4444 */
365    false, /* ALLEGRO_PIXEL_FORMAT_SINGLE_CHANNEL_8 */
366    true,
367    true,
368    true,
369 };
370 
371 
372 /* Function: al_get_pixel_block_size
373  */
al_get_pixel_block_size(int format)374 int al_get_pixel_block_size(int format)
375 {
376    return pixel_block_sizes[format];
377 }
378 
379 
380 /* Function: al_get_pixel_block_width
381  */
al_get_pixel_block_width(int format)382 int al_get_pixel_block_width(int format)
383 {
384    return pixel_block_widths[format];
385 }
386 
387 
388 /* Function: al_get_pixel_block_height
389  */
al_get_pixel_block_height(int format)390 int al_get_pixel_block_height(int format)
391 {
392    return pixel_block_heights[format];
393 }
394 
395 
396 /* Function: al_get_pixel_size
397  */
al_get_pixel_size(int format)398 int al_get_pixel_size(int format)
399 {
400    return pixel_sizes[format];
401 }
402 
403 
404 /* Function: al_get_pixel_format_bits
405  */
al_get_pixel_format_bits(int format)406 int al_get_pixel_format_bits(int format)
407 {
408    return pixel_bits[format];
409 }
410 
411 
_al_pixel_format_has_alpha(int format)412 bool _al_pixel_format_has_alpha(int format)
413 {
414    return format_alpha_table[format];
415 }
416 
417 
_al_pixel_format_is_real(int format)418 bool _al_pixel_format_is_real(int format)
419 {
420    ASSERT(format >= 0);
421    ASSERT(format < ALLEGRO_NUM_PIXEL_FORMATS);
422 
423    return format_is_real[format];
424 }
425 
_al_pixel_format_is_video_only(int format)426 bool _al_pixel_format_is_video_only(int format)
427 {
428    ASSERT(format >= 0);
429    ASSERT(format < ALLEGRO_NUM_PIXEL_FORMATS);
430 
431    return format_is_video_only[format];
432 }
433 
_al_pixel_format_is_compressed(int format)434 bool _al_pixel_format_is_compressed(int format)
435 {
436    ASSERT(format >= 0);
437    ASSERT(format < ALLEGRO_NUM_PIXEL_FORMATS);
438 
439    return format_is_compressed[format];
440 }
441 
442 
443 /* We use al_get_display_format() as a hint for the preferred RGB ordering when
444  * nothing else is specified.
445  */
try_display_format(ALLEGRO_DISPLAY * display,int * format)446 static bool try_display_format(ALLEGRO_DISPLAY *display, int *format)
447 {
448    int best_format;
449    int bytes;
450 
451    if (!display) {
452       return false;
453    }
454 
455    best_format = al_get_display_format(display);
456    if (!_al_pixel_format_is_real(best_format))
457       return false;
458 
459    bytes = al_get_pixel_size(*format);
460    if (bytes && bytes != al_get_pixel_size(best_format))
461       return false;
462 
463    if (_al_pixel_format_has_alpha(*format) &&
464       !_al_pixel_format_has_alpha(best_format)) {
465       switch (best_format) {
466          case ALLEGRO_PIXEL_FORMAT_RGBX_8888:
467             *format = ALLEGRO_PIXEL_FORMAT_RGBA_8888;
468             return true;
469          case ALLEGRO_PIXEL_FORMAT_XRGB_8888:
470              *format = ALLEGRO_PIXEL_FORMAT_ARGB_8888;
471             return true;
472          case ALLEGRO_PIXEL_FORMAT_XBGR_8888:
473             *format = ALLEGRO_PIXEL_FORMAT_ABGR_8888;
474             return true;
475          default:
476             return false;
477       }
478    }
479    if (!_al_pixel_format_has_alpha(*format) &&
480       _al_pixel_format_has_alpha(best_format)) {
481       switch (best_format) {
482          case ALLEGRO_PIXEL_FORMAT_RGBA_8888:
483             *format = ALLEGRO_PIXEL_FORMAT_RGBX_8888;
484             return true;
485          case ALLEGRO_PIXEL_FORMAT_ARGB_8888:
486              *format = ALLEGRO_PIXEL_FORMAT_XRGB_8888;
487             return true;
488          case ALLEGRO_PIXEL_FORMAT_ABGR_8888:
489             *format = ALLEGRO_PIXEL_FORMAT_XBGR_8888;
490             return true;
491          default:
492             return false;
493       }
494    }
495    *format = best_format;
496    return true;
497 }
498 
499 
_al_get_real_pixel_format(ALLEGRO_DISPLAY * display,int format)500 int _al_get_real_pixel_format(ALLEGRO_DISPLAY *display, int format)
501 {
502    /* Pick an appropriate format if the user is vague */
503    switch (format) {
504       case ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA:
505       case ALLEGRO_PIXEL_FORMAT_ANY_32_NO_ALPHA:
506          if (!try_display_format(display, &format))
507             format = ALLEGRO_PIXEL_FORMAT_XRGB_8888;
508          break;
509       case ALLEGRO_PIXEL_FORMAT_ANY:
510       case ALLEGRO_PIXEL_FORMAT_ANY_WITH_ALPHA:
511       case ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA:
512          if (!try_display_format(display, &format))
513 #if defined ALLEGRO_CFG_OPENGLES // OPENGLES doesn't have ARGB_8888
514             format = ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE;
515 #else
516             format = ALLEGRO_PIXEL_FORMAT_ARGB_8888;
517 #endif
518          break;
519       case ALLEGRO_PIXEL_FORMAT_ANY_15_NO_ALPHA:
520          format = ALLEGRO_PIXEL_FORMAT_RGB_555;
521          break;
522       case ALLEGRO_PIXEL_FORMAT_ANY_16_NO_ALPHA:
523          if (!try_display_format(display, &format))
524             format = ALLEGRO_PIXEL_FORMAT_RGB_565;
525          break;
526       case ALLEGRO_PIXEL_FORMAT_ANY_16_WITH_ALPHA:
527          format = ALLEGRO_PIXEL_FORMAT_RGBA_4444;
528          break;
529       case ALLEGRO_PIXEL_FORMAT_ANY_24_NO_ALPHA:
530          format = ALLEGRO_PIXEL_FORMAT_RGB_888;
531          break;
532       default:
533          /* Already a real format - don't change it. */
534          break;
535    }
536 
537    ASSERT(_al_pixel_format_is_real(format));
538    return format;
539 }
540 
541 
_al_pixel_format_name(ALLEGRO_PIXEL_FORMAT format)542 char const *_al_pixel_format_name(ALLEGRO_PIXEL_FORMAT format)
543 {
544    if (format >= ALLEGRO_NUM_PIXEL_FORMATS) format = ALLEGRO_NUM_PIXEL_FORMATS;
545    return pixel_format_names[format];
546 }
547 
548 
549 /* Color mapping functions */
550 
551 /* Function: al_map_rgba
552  */
al_map_rgba(unsigned char r,unsigned char g,unsigned char b,unsigned char a)553 ALLEGRO_COLOR al_map_rgba(
554    unsigned char r, unsigned char g, unsigned char b, unsigned char a)
555 {
556    ALLEGRO_COLOR color;
557    _AL_MAP_RGBA(color, r, g, b, a);
558    return color;
559 }
560 
561 
562 /* Function: al_premul_rgba
563  */
al_premul_rgba(unsigned char r,unsigned char g,unsigned char b,unsigned char a)564 ALLEGRO_COLOR al_premul_rgba(
565    unsigned char r, unsigned char g, unsigned char b, unsigned char a)
566 {
567    ALLEGRO_COLOR color;
568    _AL_MAP_RGBA(color, r * a / 255, g * a / 255, b * a / 255, a);
569    return color;
570 }
571 
572 
573 /* Function: al_map_rgb
574  */
al_map_rgb(unsigned char r,unsigned char g,unsigned char b)575 ALLEGRO_COLOR al_map_rgb(
576    unsigned char r, unsigned char g, unsigned char b)
577 {
578    return al_map_rgba(r, g, b, 255);
579 }
580 
581 
582 /* Function: al_map_rgba_f
583  */
al_map_rgba_f(float r,float g,float b,float a)584 ALLEGRO_COLOR al_map_rgba_f(float r, float g, float b, float a)
585 {
586    ALLEGRO_COLOR color;
587    color.r = r;
588    color.g = g;
589    color.b = b;
590    color.a = a;
591    return color;
592 }
593 
594 
595 /* Function: al_premul_rgba_f
596  */
al_premul_rgba_f(float r,float g,float b,float a)597 ALLEGRO_COLOR al_premul_rgba_f(float r, float g, float b, float a)
598 {
599    ALLEGRO_COLOR color;
600    color.r = r * a;
601    color.g = g * a;
602    color.b = b * a;
603    color.a = a;
604    return color;
605 }
606 
607 
608 /* Function: al_map_rgb_f
609  */
al_map_rgb_f(float r,float g,float b)610 ALLEGRO_COLOR al_map_rgb_f(float r, float g, float b)
611 {
612    return al_map_rgba_f(r, g, b, 1.0f);
613 }
614 
615 
616 /* unmapping functions */
617 
618 
619 /* Function: al_unmap_rgba
620  */
al_unmap_rgba(ALLEGRO_COLOR color,unsigned char * r,unsigned char * g,unsigned char * b,unsigned char * a)621 void al_unmap_rgba(ALLEGRO_COLOR color,
622    unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a)
623 {
624    *r = color.r * 255.0f;
625    *g = color.g * 255.0f;
626    *b = color.b * 255.0f;
627    *a = color.a * 255.0f;
628 }
629 
630 
631 /* Function: al_unmap_rgb
632  */
al_unmap_rgb(ALLEGRO_COLOR color,unsigned char * r,unsigned char * g,unsigned char * b)633 void al_unmap_rgb(ALLEGRO_COLOR color,
634    unsigned char *r, unsigned char *g, unsigned char *b)
635 {
636    unsigned char tmp;
637 
638    al_unmap_rgba(color, r, g, b, &tmp);
639 }
640 
641 
642 /* Function: al_unmap_rgba_f
643  */
al_unmap_rgba_f(ALLEGRO_COLOR color,float * r,float * g,float * b,float * a)644 void al_unmap_rgba_f(ALLEGRO_COLOR color,
645    float *r, float *g, float *b, float *a)
646 {
647    *r = color.r;
648    *g = color.g;
649    *b = color.b;
650    *a = color.a;
651 }
652 
653 
654 /* Function: al_unmap_rgb_f
655  */
al_unmap_rgb_f(ALLEGRO_COLOR color,float * r,float * g,float * b)656 void al_unmap_rgb_f(ALLEGRO_COLOR color, float *r, float *g, float *b)
657 {
658    float tmp;
659 
660    al_unmap_rgba_f(color, r, g, b, &tmp);
661 }
662 
663 
664 /* vim: set sts=3 sw=3 et: */
665