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