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