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
32static void
33Blit1to1(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
84static void
85Blit1to2(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
191static void
192Blit1to3(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
240static void
241Blit1to4(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
288static void
289Blit1to1Key(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
335static void
336Blit1to2Key(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
367static void
368Blit1to3Key(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
400static void
401Blit1to4Key(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
432static void
433Blit1toNAlpha(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
472static void
473Blit1toNAlphaKey(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
515static const SDL_BlitFunc one_blit[] = {
516 (SDL_BlitFunc) NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
517};
518
519static const SDL_BlitFunc one_blitkey[] = {
520 (SDL_BlitFunc) NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
521};
522
523SDL_BlitFunc
524SDL_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