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 | #if SDL_HAVE_BLIT_1 |
24 | |
25 | #include "SDL_video.h" |
26 | #include "SDL_blit.h" |
27 | #include "SDL_sysvideo.h" |
28 | #include "SDL_endian.h" |
29 | |
30 | /* Functions to blit from 8-bit surfaces to other surfaces */ |
31 | |
32 | static void |
33 | Blit1to1(SDL_BlitInfo * info) |
34 | { |
35 | #ifndef USE_DUFFS_LOOP |
36 | int c; |
37 | #endif |
38 | int width, height; |
39 | Uint8 *src, *map, *dst; |
40 | int srcskip, dstskip; |
41 | |
42 | /* Set up some basic variables */ |
43 | width = info->dst_w; |
44 | height = info->dst_h; |
45 | src = info->src; |
46 | srcskip = info->src_skip; |
47 | dst = info->dst; |
48 | dstskip = info->dst_skip; |
49 | map = info->table; |
50 | |
51 | while (height--) { |
52 | #ifdef USE_DUFFS_LOOP |
53 | /* *INDENT-OFF* */ |
54 | DUFFS_LOOP( |
55 | { |
56 | *dst = map[*src]; |
57 | } |
58 | dst++; |
59 | src++; |
60 | , width); |
61 | /* *INDENT-ON* */ |
62 | #else |
63 | for (c = width; c; --c) { |
64 | *dst = map[*src]; |
65 | dst++; |
66 | src++; |
67 | } |
68 | #endif |
69 | src += srcskip; |
70 | dst += dstskip; |
71 | } |
72 | } |
73 | |
74 | /* This is now endian dependent */ |
75 | #ifndef USE_DUFFS_LOOP |
76 | # if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) |
77 | # define HI 1 |
78 | # define LO 0 |
79 | # else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */ |
80 | # define HI 0 |
81 | # define LO 1 |
82 | # endif |
83 | #endif |
84 | static void |
85 | Blit1to2(SDL_BlitInfo * info) |
86 | { |
87 | #ifndef USE_DUFFS_LOOP |
88 | int c; |
89 | #endif |
90 | int width, height; |
91 | Uint8 *src, *dst; |
92 | Uint16 *map; |
93 | int srcskip, dstskip; |
94 | |
95 | /* Set up some basic variables */ |
96 | width = info->dst_w; |
97 | height = info->dst_h; |
98 | src = info->src; |
99 | srcskip = info->src_skip; |
100 | dst = info->dst; |
101 | dstskip = info->dst_skip; |
102 | map = (Uint16 *) info->table; |
103 | |
104 | #ifdef USE_DUFFS_LOOP |
105 | while (height--) { |
106 | /* *INDENT-OFF* */ |
107 | DUFFS_LOOP( |
108 | { |
109 | *(Uint16 *)dst = map[*src++]; |
110 | dst += 2; |
111 | }, |
112 | width); |
113 | /* *INDENT-ON* */ |
114 | src += srcskip; |
115 | dst += dstskip; |
116 | } |
117 | #else |
118 | /* Memory align at 4-byte boundary, if necessary */ |
119 | if ((long) dst & 0x03) { |
120 | /* Don't do anything if width is 0 */ |
121 | if (width == 0) { |
122 | return; |
123 | } |
124 | --width; |
125 | |
126 | while (height--) { |
127 | /* Perform copy alignment */ |
128 | *(Uint16 *) dst = map[*src++]; |
129 | dst += 2; |
130 | |
131 | /* Copy in 4 pixel chunks */ |
132 | for (c = width / 4; c; --c) { |
133 | *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); |
134 | src += 2; |
135 | dst += 4; |
136 | *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); |
137 | src += 2; |
138 | dst += 4; |
139 | } |
140 | /* Get any leftovers */ |
141 | switch (width & 3) { |
142 | case 3: |
143 | *(Uint16 *) dst = map[*src++]; |
144 | dst += 2; |
145 | case 2: |
146 | *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); |
147 | src += 2; |
148 | dst += 4; |
149 | break; |
150 | case 1: |
151 | *(Uint16 *) dst = map[*src++]; |
152 | dst += 2; |
153 | break; |
154 | } |
155 | src += srcskip; |
156 | dst += dstskip; |
157 | } |
158 | } else { |
159 | while (height--) { |
160 | /* Copy in 4 pixel chunks */ |
161 | for (c = width / 4; c; --c) { |
162 | *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); |
163 | src += 2; |
164 | dst += 4; |
165 | *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); |
166 | src += 2; |
167 | dst += 4; |
168 | } |
169 | /* Get any leftovers */ |
170 | switch (width & 3) { |
171 | case 3: |
172 | *(Uint16 *) dst = map[*src++]; |
173 | dst += 2; |
174 | case 2: |
175 | *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]); |
176 | src += 2; |
177 | dst += 4; |
178 | break; |
179 | case 1: |
180 | *(Uint16 *) dst = map[*src++]; |
181 | dst += 2; |
182 | break; |
183 | } |
184 | src += srcskip; |
185 | dst += dstskip; |
186 | } |
187 | } |
188 | #endif /* USE_DUFFS_LOOP */ |
189 | } |
190 | |
191 | static void |
192 | Blit1to3(SDL_BlitInfo * info) |
193 | { |
194 | #ifndef USE_DUFFS_LOOP |
195 | int c; |
196 | #endif |
197 | int o; |
198 | int width, height; |
199 | Uint8 *src, *map, *dst; |
200 | int srcskip, dstskip; |
201 | |
202 | /* Set up some basic variables */ |
203 | width = info->dst_w; |
204 | height = info->dst_h; |
205 | src = info->src; |
206 | srcskip = info->src_skip; |
207 | dst = info->dst; |
208 | dstskip = info->dst_skip; |
209 | map = info->table; |
210 | |
211 | while (height--) { |
212 | #ifdef USE_DUFFS_LOOP |
213 | /* *INDENT-OFF* */ |
214 | DUFFS_LOOP( |
215 | { |
216 | o = *src * 4; |
217 | dst[0] = map[o++]; |
218 | dst[1] = map[o++]; |
219 | dst[2] = map[o++]; |
220 | } |
221 | src++; |
222 | dst += 3; |
223 | , width); |
224 | /* *INDENT-ON* */ |
225 | #else |
226 | for (c = width; c; --c) { |
227 | o = *src * 4; |
228 | dst[0] = map[o++]; |
229 | dst[1] = map[o++]; |
230 | dst[2] = map[o++]; |
231 | src++; |
232 | dst += 3; |
233 | } |
234 | #endif /* USE_DUFFS_LOOP */ |
235 | src += srcskip; |
236 | dst += dstskip; |
237 | } |
238 | } |
239 | |
240 | static void |
241 | Blit1to4(SDL_BlitInfo * info) |
242 | { |
243 | #ifndef USE_DUFFS_LOOP |
244 | int c; |
245 | #endif |
246 | int width, height; |
247 | Uint8 *src; |
248 | Uint32 *map, *dst; |
249 | int srcskip, dstskip; |
250 | |
251 | /* Set up some basic variables */ |
252 | width = info->dst_w; |
253 | height = info->dst_h; |
254 | src = info->src; |
255 | srcskip = info->src_skip; |
256 | dst = (Uint32 *) info->dst; |
257 | dstskip = info->dst_skip / 4; |
258 | map = (Uint32 *) info->table; |
259 | |
260 | while (height--) { |
261 | #ifdef USE_DUFFS_LOOP |
262 | /* *INDENT-OFF* */ |
263 | DUFFS_LOOP( |
264 | *dst++ = map[*src++]; |
265 | , width); |
266 | /* *INDENT-ON* */ |
267 | #else |
268 | for (c = width / 4; c; --c) { |
269 | *dst++ = map[*src++]; |
270 | *dst++ = map[*src++]; |
271 | *dst++ = map[*src++]; |
272 | *dst++ = map[*src++]; |
273 | } |
274 | switch (width & 3) { |
275 | case 3: |
276 | *dst++ = map[*src++]; |
277 | case 2: |
278 | *dst++ = map[*src++]; |
279 | case 1: |
280 | *dst++ = map[*src++]; |
281 | } |
282 | #endif /* USE_DUFFS_LOOP */ |
283 | src += srcskip; |
284 | dst += dstskip; |
285 | } |
286 | } |
287 | |
288 | static void |
289 | Blit1to1Key(SDL_BlitInfo * info) |
290 | { |
291 | int width = info->dst_w; |
292 | int height = info->dst_h; |
293 | Uint8 *src = info->src; |
294 | int srcskip = info->src_skip; |
295 | Uint8 *dst = info->dst; |
296 | int dstskip = info->dst_skip; |
297 | Uint8 *palmap = info->table; |
298 | Uint32 ckey = info->colorkey; |
299 | |
300 | if (palmap) { |
301 | while (height--) { |
302 | /* *INDENT-OFF* */ |
303 | DUFFS_LOOP( |
304 | { |
305 | if ( *src != ckey ) { |
306 | *dst = palmap[*src]; |
307 | } |
308 | dst++; |
309 | src++; |
310 | }, |
311 | width); |
312 | /* *INDENT-ON* */ |
313 | src += srcskip; |
314 | dst += dstskip; |
315 | } |
316 | } else { |
317 | while (height--) { |
318 | /* *INDENT-OFF* */ |
319 | DUFFS_LOOP( |
320 | { |
321 | if ( *src != ckey ) { |
322 | *dst = *src; |
323 | } |
324 | dst++; |
325 | src++; |
326 | }, |
327 | width); |
328 | /* *INDENT-ON* */ |
329 | src += srcskip; |
330 | dst += dstskip; |
331 | } |
332 | } |
333 | } |
334 | |
335 | static void |
336 | Blit1to2Key(SDL_BlitInfo * info) |
337 | { |
338 | int width = info->dst_w; |
339 | int height = info->dst_h; |
340 | Uint8 *src = info->src; |
341 | int srcskip = info->src_skip; |
342 | Uint16 *dstp = (Uint16 *) info->dst; |
343 | int dstskip = info->dst_skip; |
344 | Uint16 *palmap = (Uint16 *) info->table; |
345 | Uint32 ckey = info->colorkey; |
346 | |
347 | /* Set up some basic variables */ |
348 | dstskip /= 2; |
349 | |
350 | while (height--) { |
351 | /* *INDENT-OFF* */ |
352 | DUFFS_LOOP( |
353 | { |
354 | if ( *src != ckey ) { |
355 | *dstp=palmap[*src]; |
356 | } |
357 | src++; |
358 | dstp++; |
359 | }, |
360 | width); |
361 | /* *INDENT-ON* */ |
362 | src += srcskip; |
363 | dstp += dstskip; |
364 | } |
365 | } |
366 | |
367 | static void |
368 | Blit1to3Key(SDL_BlitInfo * info) |
369 | { |
370 | int width = info->dst_w; |
371 | int height = info->dst_h; |
372 | Uint8 *src = info->src; |
373 | int srcskip = info->src_skip; |
374 | Uint8 *dst = info->dst; |
375 | int dstskip = info->dst_skip; |
376 | Uint8 *palmap = info->table; |
377 | Uint32 ckey = info->colorkey; |
378 | int o; |
379 | |
380 | while (height--) { |
381 | /* *INDENT-OFF* */ |
382 | DUFFS_LOOP( |
383 | { |
384 | if ( *src != ckey ) { |
385 | o = *src * 4; |
386 | dst[0] = palmap[o++]; |
387 | dst[1] = palmap[o++]; |
388 | dst[2] = palmap[o++]; |
389 | } |
390 | src++; |
391 | dst += 3; |
392 | }, |
393 | width); |
394 | /* *INDENT-ON* */ |
395 | src += srcskip; |
396 | dst += dstskip; |
397 | } |
398 | } |
399 | |
400 | static void |
401 | Blit1to4Key(SDL_BlitInfo * info) |
402 | { |
403 | int width = info->dst_w; |
404 | int height = info->dst_h; |
405 | Uint8 *src = info->src; |
406 | int srcskip = info->src_skip; |
407 | Uint32 *dstp = (Uint32 *) info->dst; |
408 | int dstskip = info->dst_skip; |
409 | Uint32 *palmap = (Uint32 *) info->table; |
410 | Uint32 ckey = info->colorkey; |
411 | |
412 | /* Set up some basic variables */ |
413 | dstskip /= 4; |
414 | |
415 | while (height--) { |
416 | /* *INDENT-OFF* */ |
417 | DUFFS_LOOP( |
418 | { |
419 | if ( *src != ckey ) { |
420 | *dstp = palmap[*src]; |
421 | } |
422 | src++; |
423 | dstp++; |
424 | }, |
425 | width); |
426 | /* *INDENT-ON* */ |
427 | src += srcskip; |
428 | dstp += dstskip; |
429 | } |
430 | } |
431 | |
432 | static void |
433 | Blit1toNAlpha(SDL_BlitInfo * info) |
434 | { |
435 | int width = info->dst_w; |
436 | int height = info->dst_h; |
437 | Uint8 *src = info->src; |
438 | int srcskip = info->src_skip; |
439 | Uint8 *dst = info->dst; |
440 | int dstskip = info->dst_skip; |
441 | SDL_PixelFormat *dstfmt = info->dst_fmt; |
442 | const SDL_Color *srcpal = info->src_fmt->palette->colors; |
443 | int dstbpp; |
444 | Uint32 pixel; |
445 | unsigned sR, sG, sB; |
446 | unsigned dR, dG, dB, dA; |
447 | const unsigned A = info->a; |
448 | |
449 | /* Set up some basic variables */ |
450 | dstbpp = dstfmt->BytesPerPixel; |
451 | |
452 | while (height--) { |
453 | /* *INDENT-OFF* */ |
454 | DUFFS_LOOP4( |
455 | { |
456 | sR = srcpal[*src].r; |
457 | sG = srcpal[*src].g; |
458 | sB = srcpal[*src].b; |
459 | DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); |
460 | ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); |
461 | ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); |
462 | src++; |
463 | dst += dstbpp; |
464 | }, |
465 | width); |
466 | /* *INDENT-ON* */ |
467 | src += srcskip; |
468 | dst += dstskip; |
469 | } |
470 | } |
471 | |
472 | static void |
473 | Blit1toNAlphaKey(SDL_BlitInfo * info) |
474 | { |
475 | int width = info->dst_w; |
476 | int height = info->dst_h; |
477 | Uint8 *src = info->src; |
478 | int srcskip = info->src_skip; |
479 | Uint8 *dst = info->dst; |
480 | int dstskip = info->dst_skip; |
481 | SDL_PixelFormat *dstfmt = info->dst_fmt; |
482 | const SDL_Color *srcpal = info->src_fmt->palette->colors; |
483 | Uint32 ckey = info->colorkey; |
484 | int dstbpp; |
485 | Uint32 pixel; |
486 | unsigned sR, sG, sB; |
487 | unsigned dR, dG, dB, dA; |
488 | const unsigned A = info->a; |
489 | |
490 | /* Set up some basic variables */ |
491 | dstbpp = dstfmt->BytesPerPixel; |
492 | |
493 | while (height--) { |
494 | /* *INDENT-OFF* */ |
495 | DUFFS_LOOP( |
496 | { |
497 | if ( *src != ckey ) { |
498 | sR = srcpal[*src].r; |
499 | sG = srcpal[*src].g; |
500 | sB = srcpal[*src].b; |
501 | DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA); |
502 | ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA); |
503 | ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA); |
504 | } |
505 | src++; |
506 | dst += dstbpp; |
507 | }, |
508 | width); |
509 | /* *INDENT-ON* */ |
510 | src += srcskip; |
511 | dst += dstskip; |
512 | } |
513 | } |
514 | |
515 | static const SDL_BlitFunc one_blit[] = { |
516 | (SDL_BlitFunc) NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4 |
517 | }; |
518 | |
519 | static const SDL_BlitFunc one_blitkey[] = { |
520 | (SDL_BlitFunc) NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key |
521 | }; |
522 | |
523 | SDL_BlitFunc |
524 | SDL_CalculateBlit1(SDL_Surface * surface) |
525 | { |
526 | int which; |
527 | SDL_PixelFormat *dstfmt; |
528 | |
529 | dstfmt = surface->map->dst->format; |
530 | if (dstfmt->BitsPerPixel < 8) { |
531 | which = 0; |
532 | } else { |
533 | which = dstfmt->BytesPerPixel; |
534 | } |
535 | switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) { |
536 | case 0: |
537 | return one_blit[which]; |
538 | |
539 | case SDL_COPY_COLORKEY: |
540 | return one_blitkey[which]; |
541 | |
542 | case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: |
543 | /* Supporting 8bpp->8bpp alpha is doable but requires lots of |
544 | tables which consume space and takes time to precompute, |
545 | so is better left to the user */ |
546 | return which >= 2 ? Blit1toNAlpha : (SDL_BlitFunc) NULL; |
547 | |
548 | case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND: |
549 | return which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc) NULL; |
550 | } |
551 | return (SDL_BlitFunc) NULL; |
552 | } |
553 | |
554 | #endif /* SDL_HAVE_BLIT_1 */ |
555 | |
556 | /* vi: set ts=4 sw=4 expandtab: */ |
557 | |