1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Asm routines for software color conversion.
12  *      Suggestions to make it faster are welcome :)
13  *
14  *      By Isaac Cruz.
15  *
16  *      24-bit color support and non MMX routines by Eric Botcazou.
17  *
18  *      Support for rectangles of any width, 8-bit destination color
19  *      and cross-conversion between 15-bit and 16-bit colors,
20  *      additional MMX and color copy routines by Robert J. Ohannessian.
21  *
22  *      See readme.txt for copyright information.
23  */
24 
25 
26 #include "allegro.h"
27 #include "allegro/internal/aintern.h"
28 
29 
30 int *_colorconv_indexed_palette = NULL;    /* for conversion from 8-bit */
31 int *_colorconv_rgb_scale_5x35 = NULL;     /* for conversion from 15/16-bit */
32 unsigned char *_colorconv_rgb_map = NULL;  /* for conversion from 8/12-bit to 8-bit */
33 
34 static int indexed_palette_depth;          /* target depth of the indexed palette */
35 static int indexed_palette_size;           /* size of the indexed palette */
36 
37 
38 
39 /* build_rgb_scale_5235_table:
40  *  Builds pre-calculated tables for 15-bit to truecolor conversion.
41  */
build_rgb_scale_5235_table(int to_depth)42 static void build_rgb_scale_5235_table(int to_depth)
43 {
44    int i, color, red, green, blue;
45 
46    if (to_depth == 24)
47       /* 6 contiguous 256-entry tables (6k) */
48       _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*1536);
49    else if (to_depth == 32)
50       /* 2 contiguous 256-entry tables (2k) */
51       _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*512);
52 
53    /* 1st table: r5g2 to r8g8b0 */
54    for (i=0; i<128; i++) {
55       red = _rgb_scale_5[i>>2];
56       green=((i&3)<<6)+((i&3)<<1);
57 
58       color = (red<<16) | (green<<8);
59       _colorconv_rgb_scale_5x35[i] = color;
60 
61       if (to_depth == 24) {
62          _colorconv_rgb_scale_5x35[ 512+i] = (color>>8)+((color&0xff)<<24);
63          _colorconv_rgb_scale_5x35[1024+i] = (color>>16)+((color&0xffff)<<16);
64       }
65    }
66 
67    /* 2nd table: g3b5 to r0g8b8 */
68    for (i=0; i<256; i++) {
69       blue = _rgb_scale_5[i&0x1f];
70       green=(i>>5)<<3;
71 
72       if (green == 0x38)
73           green++;
74 
75       color = (green<<8) | blue;
76       _colorconv_rgb_scale_5x35[256+i] = color;
77 
78       if (to_depth == 24) {
79          _colorconv_rgb_scale_5x35[ 512+256+i] = (color>>8)+((color&0xff)<<24);
80          _colorconv_rgb_scale_5x35[1024+256+i] = (color>>16)+((color&0xffff)<<16);
81       }
82    }
83 }
84 
85 
86 
87 /* build_rgb_scale_5335_table:
88  *  Builds pre-calculated tables for 16-bit to truecolor conversion.
89  */
build_rgb_scale_5335_table(int to_depth)90 static void build_rgb_scale_5335_table(int to_depth)
91 {
92    int i, color, red, green, blue;
93 
94    if (to_depth == 24)
95       /* 6 contiguous 256-entry tables (6k) */
96       _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*1536);
97    else if (to_depth == 32)
98       /* 2 contiguous 256-entry tables (2k) */
99       _colorconv_rgb_scale_5x35 = _AL_MALLOC_ATOMIC(sizeof(int)*512);
100 
101    /* 1st table: r5g3 to r8g8b0 */
102    for (i=0; i<256; i++) {
103       red = _rgb_scale_5[i>>3];
104       green=(i&7)<<5;
105 
106       if (green >= 68)
107            green++;
108 
109        if (green >= 160)
110            green++;
111 
112       color = (red<<16) | (green<<8);
113       _colorconv_rgb_scale_5x35[i] = color;
114 
115       if (to_depth == 24) {
116          _colorconv_rgb_scale_5x35[ 512+i] = (color>>8)+((color&0xff)<<24);
117          _colorconv_rgb_scale_5x35[1024+i] = (color>>16)+((color&0xffff)<<16);
118       }
119    }
120 
121    /* 2nd table: g3b5 to r0g8b8 */
122    for (i=0; i<256; i++) {
123       blue = _rgb_scale_5[i&0x1f];
124       green=(i>>5)<<2;
125 
126       if (green == 0x1c)
127           green++;
128 
129       color = (green<<8) | blue;
130       _colorconv_rgb_scale_5x35[256+i] = color;
131 
132       if (to_depth == 24) {
133          _colorconv_rgb_scale_5x35[ 512+256+i] = (color>>8)+((color&0xff)<<24);
134          _colorconv_rgb_scale_5x35[1024+256+i] = (color>>16)+((color&0xffff)<<16);
135       }
136    }
137 }
138 
139 
140 
141 /* create_indexed_palette:
142  *  Reserves storage for the 8-bit palette.
143  */
create_indexed_palette(int to_depth)144 static void create_indexed_palette(int to_depth)
145 {
146    switch (to_depth) {
147 
148       case 15:
149       case 16:
150          indexed_palette_size = PAL_SIZE*2;
151          break;
152 
153       case 24:
154          indexed_palette_size = PAL_SIZE*4;
155          break;
156 
157       case 32:
158          indexed_palette_size = PAL_SIZE;
159          break;
160    }
161 
162    indexed_palette_depth = to_depth;
163    _colorconv_indexed_palette = _AL_MALLOC_ATOMIC(sizeof(int) * indexed_palette_size);
164 }
165 
166 
167 
168 /* _set_colorconv_palette:
169  *  Updates 8-bit palette entries.
170  */
_set_colorconv_palette(AL_CONST struct RGB * p,int from,int to)171 void _set_colorconv_palette(AL_CONST struct RGB *p, int from, int to)
172 {
173    int n, color;
174 
175    if (!indexed_palette_size)
176       return;
177 
178    for (n = from; n <= to; n++) {
179       color = makecol_depth(indexed_palette_depth,
180                             (p[n].r << 2) | ((p[n].r & 0x30) >> 4),
181                             (p[n].g << 2) | ((p[n].g & 0x30) >> 4),
182                             (p[n].b << 2) | ((p[n].b & 0x30) >> 4));
183 
184       _colorconv_indexed_palette[n] = color;
185 
186       if ((indexed_palette_depth == 15) || (indexed_palette_depth == 16)) {
187          /* 2 pre-calculated shift tables (2k) */
188          _colorconv_indexed_palette[PAL_SIZE+n] = color<<16;
189       }
190       else if (indexed_palette_depth == 24) {
191          /* 4 pre-calculated shift tables (4k) */
192          _colorconv_indexed_palette[PAL_SIZE+n]   = (color>>8)+((color&0xff)<<24);
193          _colorconv_indexed_palette[PAL_SIZE*2+n] = (color>>16)+((color&0xffff)<<16);
194          _colorconv_indexed_palette[PAL_SIZE*3+n] = color<<8;
195       }
196    }
197 }
198 
199 
200 
201 /* create_rgb_map:
202  *  Reserves storage for the rgb map to 8-bit.
203  */
create_rgb_map(int from_depth)204 static void create_rgb_map(int from_depth)
205 {
206    int rgb_map_size = 0;
207 
208    switch (from_depth) {
209       case 8:
210          rgb_map_size = 256;  /* 8-bit */
211          break;
212 
213       case 15:
214       case 16:
215       case 24:
216       case 32:
217          rgb_map_size = 4096;  /* 12-bit */
218          break;
219    }
220 
221    _colorconv_rgb_map = _AL_MALLOC_ATOMIC(sizeof(int) * rgb_map_size);
222 }
223 
224 
225 
226 /* _get_colorconv_map:
227  *  Retrieves a handle to the rgb map.
228  */
_get_colorconv_map(void)229 unsigned char *_get_colorconv_map(void)
230 {
231    return _colorconv_rgb_map;
232 }
233 
234 
235 
236 /* _get_colorconv_blitter:
237  *  Returns the blitter function matching the specified depths.
238  */
_get_colorconv_blitter(int from_depth,int to_depth)239 COLORCONV_BLITTER_FUNC *_get_colorconv_blitter(int from_depth, int to_depth)
240 {
241    switch (from_depth) {
242 
243 #ifdef ALLEGRO_COLOR8
244       case 8:
245          switch (to_depth) {
246 
247             case 8:
248                create_rgb_map(8);
249                return &_colorconv_blit_8_to_8;
250 
251             case 15:
252                create_indexed_palette(15);
253                return &_colorconv_blit_8_to_15;
254 
255             case 16:
256                create_indexed_palette(16);
257                return &_colorconv_blit_8_to_16;
258 
259             case 24:
260                create_indexed_palette(24);
261                return &_colorconv_blit_8_to_24;
262 
263             case 32:
264                create_indexed_palette(32);
265                return &_colorconv_blit_8_to_32;
266          }
267          break;
268 #endif
269 
270 #ifdef ALLEGRO_COLOR16
271       case 15:
272          switch (to_depth) {
273 
274             case 8:
275                create_rgb_map(15);
276                return &_colorconv_blit_15_to_8;
277 
278             case 15:
279 #ifndef ALLEGRO_NO_COLORCOPY
280                return &_colorcopy_blit_15_to_15;
281 #else
282                return NULL;
283 #endif
284 
285             case 16:
286                return &_colorconv_blit_15_to_16;
287 
288             case 24:
289                build_rgb_scale_5235_table(24);
290                return &_colorconv_blit_15_to_24;
291 
292             case 32:
293                build_rgb_scale_5235_table(32);
294                return &_colorconv_blit_15_to_32;
295          }
296          break;
297 
298       case 16:
299          switch (to_depth) {
300 
301             case 8:
302                create_rgb_map(16);
303                return &_colorconv_blit_16_to_8;
304 
305             case 15:
306                return &_colorconv_blit_16_to_15;
307 
308             case 16:
309 #ifndef ALLEGRO_NO_COLORCOPY
310                return &_colorcopy_blit_16_to_16;
311 #else
312                return NULL;
313 #endif
314 
315             case 24:
316                build_rgb_scale_5335_table(24);
317                return &_colorconv_blit_16_to_24;
318 
319             case 32:
320                build_rgb_scale_5335_table(32);
321                return &_colorconv_blit_16_to_32;
322          }
323          break;
324 #endif
325 
326 #ifdef ALLEGRO_COLOR24
327       case 24:
328          switch (to_depth) {
329 
330             case 8:
331                create_rgb_map(24);
332                return &_colorconv_blit_24_to_8;
333 
334             case 15:
335                return &_colorconv_blit_24_to_15;
336 
337             case 16:
338                return &_colorconv_blit_24_to_16;
339 
340             case 24:
341 #ifndef ALLEGRO_NO_COLORCOPY
342                return &_colorcopy_blit_24_to_24;
343 #else
344                return NULL;
345 #endif
346 
347             case 32:
348                return &_colorconv_blit_24_to_32;
349          }
350          break;
351 #endif
352 
353 #ifdef ALLEGRO_COLOR32
354       case 32:
355          switch (to_depth) {
356 
357             case 8:
358                create_rgb_map(32);
359                return &_colorconv_blit_32_to_8;
360 
361             case 15:
362                return &_colorconv_blit_32_to_15;
363 
364             case 16:
365                return &_colorconv_blit_32_to_16;
366 
367             case 24:
368                return &_colorconv_blit_32_to_24;
369 
370             case 32:
371 #ifndef ALLEGRO_NO_COLORCOPY
372                return &_colorcopy_blit_32_to_32;
373 #else
374                return NULL;
375 #endif
376          }
377          break;
378 #endif
379    }
380 
381    return NULL;
382 }
383 
384 
385 
386 /* _release_colorconv_blitter:
387  *  Frees previously allocated resources.
388  */
_release_colorconv_blitter(COLORCONV_BLITTER_FUNC * blitter)389 void _release_colorconv_blitter(COLORCONV_BLITTER_FUNC *blitter)
390 {
391    /* destroy the 8-bit palette */
392    if (_colorconv_indexed_palette) {
393       _AL_FREE(_colorconv_indexed_palette);
394       _colorconv_indexed_palette = NULL;
395       indexed_palette_size = 0;
396    }
397 
398    /* destroy the shift table */
399    if (_colorconv_rgb_scale_5x35) {
400       _AL_FREE(_colorconv_rgb_scale_5x35);
401       _colorconv_rgb_scale_5x35 = NULL;
402    }
403 
404    /* destroy the rgb map to 8-bit */
405    if (_colorconv_rgb_map) {
406       _AL_FREE(_colorconv_rgb_map);
407       _colorconv_rgb_map = NULL;
408    }
409 }
410 
411