• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2012 Sam Lantinga
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 
19     Sam Lantinga
20     slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23 
24 #include "SDL_video.h"
25 #include "SDL_blit.h"
26 #include "SDL_sysvideo.h"
27 #include "SDL_endian.h"
28 
29 /* Functions to blit from 8-bit surfaces to other surfaces */
30 
Blit1to1(SDL_BlitInfo * info)31 static void 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->d_width;
42 	height = info->d_height;
43 	src = info->s_pixels;
44 	srcskip = info->s_skip;
45 	dst = info->d_pixels;
46 	dstskip = info->d_skip;
47 	map = info->table;
48 
49 	while ( height-- ) {
50 #ifdef USE_DUFFS_LOOP
51 		DUFFS_LOOP(
52 			{
53 			  *dst = map[*src];
54 			}
55 			dst++;
56 			src++;
57 		, width);
58 #else
59 		for ( c=width; c; --c ) {
60 		        *dst = map[*src];
61 			dst++;
62 			src++;
63 		}
64 #endif
65 		src += srcskip;
66 		dst += dstskip;
67 	}
68 }
69 /* This is now endian dependent */
70 #if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
71 #define HI	1
72 #define LO	0
73 #else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
74 #define HI	0
75 #define LO	1
76 #endif
Blit1to2(SDL_BlitInfo * info)77 static void Blit1to2(SDL_BlitInfo *info)
78 {
79 #ifndef USE_DUFFS_LOOP
80 	int c;
81 #endif
82 	int width, height;
83 	Uint8 *src, *dst;
84 	Uint16 *map;
85 	int srcskip, dstskip;
86 
87 	/* Set up some basic variables */
88 	width = info->d_width;
89 	height = info->d_height;
90 	src = info->s_pixels;
91 	srcskip = info->s_skip;
92 	dst = info->d_pixels;
93 	dstskip = info->d_skip;
94 	map = (Uint16 *)info->table;
95 
96 #ifdef USE_DUFFS_LOOP
97 	while ( height-- ) {
98 		DUFFS_LOOP(
99 		{
100 			*(Uint16 *)dst = map[*src++];
101 			dst += 2;
102 		},
103 		width);
104 		src += srcskip;
105 		dst += dstskip;
106 	}
107 #else
108 	/* Memory align at 4-byte boundary, if necessary */
109 	if ( (long)dst & 0x03 ) {
110 		/* Don't do anything if width is 0 */
111 		if ( width == 0 ) {
112 			return;
113 		}
114 		--width;
115 
116 		while ( height-- ) {
117 			/* Perform copy alignment */
118 			*(Uint16 *)dst = map[*src++];
119 			dst += 2;
120 
121 			/* Copy in 4 pixel chunks */
122 			for ( c=width/4; c; --c ) {
123 				*(Uint32 *)dst =
124 					(map[src[HI]]<<16)|(map[src[LO]]);
125 				src += 2;
126 				dst += 4;
127 				*(Uint32 *)dst =
128 					(map[src[HI]]<<16)|(map[src[LO]]);
129 				src += 2;
130 				dst += 4;
131 			}
132 			/* Get any leftovers */
133 			switch (width & 3) {
134 				case 3:
135 					*(Uint16 *)dst = map[*src++];
136 					dst += 2;
137 				case 2:
138 					*(Uint32 *)dst =
139 					  (map[src[HI]]<<16)|(map[src[LO]]);
140 					src += 2;
141 					dst += 4;
142 					break;
143 				case 1:
144 					*(Uint16 *)dst = map[*src++];
145 					dst += 2;
146 					break;
147 			}
148 			src += srcskip;
149 			dst += dstskip;
150 		}
151 	} else {
152 		while ( height-- ) {
153 			/* Copy in 4 pixel chunks */
154 			for ( c=width/4; c; --c ) {
155 				*(Uint32 *)dst =
156 					(map[src[HI]]<<16)|(map[src[LO]]);
157 				src += 2;
158 				dst += 4;
159 				*(Uint32 *)dst =
160 					(map[src[HI]]<<16)|(map[src[LO]]);
161 				src += 2;
162 				dst += 4;
163 			}
164 			/* Get any leftovers */
165 			switch (width & 3) {
166 				case 3:
167 					*(Uint16 *)dst = map[*src++];
168 					dst += 2;
169 				case 2:
170 					*(Uint32 *)dst =
171 					  (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 }
Blit1to3(SDL_BlitInfo * info)186 static void Blit1to3(SDL_BlitInfo *info)
187 {
188 #ifndef USE_DUFFS_LOOP
189 	int c;
190 #endif
191 	int o;
192 	int width, height;
193 	Uint8 *src, *map, *dst;
194 	int srcskip, dstskip;
195 
196 	/* Set up some basic variables */
197 	width = info->d_width;
198 	height = info->d_height;
199 	src = info->s_pixels;
200 	srcskip = info->s_skip;
201 	dst = info->d_pixels;
202 	dstskip = info->d_skip;
203 	map = info->table;
204 
205 	while ( height-- ) {
206 #ifdef USE_DUFFS_LOOP
207 		DUFFS_LOOP(
208 			{
209 				o = *src * 4;
210 				dst[0] = map[o++];
211 				dst[1] = map[o++];
212 				dst[2] = map[o++];
213 			}
214 			src++;
215 			dst += 3;
216 		, width);
217 #else
218 		for ( c=width; c; --c ) {
219 			o = *src * 4;
220 			dst[0] = map[o++];
221 			dst[1] = map[o++];
222 			dst[2] = map[o++];
223 			src++;
224 			dst += 3;
225 		}
226 #endif /* USE_DUFFS_LOOP */
227 		src += srcskip;
228 		dst += dstskip;
229 	}
230 }
Blit1to4(SDL_BlitInfo * info)231 static void Blit1to4(SDL_BlitInfo *info)
232 {
233 #ifndef USE_DUFFS_LOOP
234 	int c;
235 #endif
236 	int width, height;
237 	Uint8 *src;
238 	Uint32 *map, *dst;
239 	int srcskip, dstskip;
240 
241 	/* Set up some basic variables */
242 	width = info->d_width;
243 	height = info->d_height;
244 	src = info->s_pixels;
245 	srcskip = info->s_skip;
246 	dst = (Uint32 *)info->d_pixels;
247 	dstskip = info->d_skip/4;
248 	map = (Uint32 *)info->table;
249 
250 	while ( height-- ) {
251 #ifdef USE_DUFFS_LOOP
252 		DUFFS_LOOP(
253 			*dst++ = map[*src++];
254 		, width);
255 #else
256 		for ( c=width/4; c; --c ) {
257 			*dst++ = map[*src++];
258 			*dst++ = map[*src++];
259 			*dst++ = map[*src++];
260 			*dst++ = map[*src++];
261 		}
262 		switch ( width & 3 ) {
263 			case 3:
264 				*dst++ = map[*src++];
265 			case 2:
266 				*dst++ = map[*src++];
267 			case 1:
268 				*dst++ = map[*src++];
269 		}
270 #endif /* USE_DUFFS_LOOP */
271 		src += srcskip;
272 		dst += dstskip;
273 	}
274 }
275 
Blit1to1Key(SDL_BlitInfo * info)276 static void Blit1to1Key(SDL_BlitInfo *info)
277 {
278 	int width = info->d_width;
279 	int height = info->d_height;
280 	Uint8 *src = info->s_pixels;
281 	int srcskip = info->s_skip;
282 	Uint8 *dst = info->d_pixels;
283 	int dstskip = info->d_skip;
284 	Uint8 *palmap = info->table;
285 	Uint32 ckey = info->src->colorkey;
286 
287 	if ( palmap ) {
288 		while ( height-- ) {
289 			DUFFS_LOOP(
290 			{
291 				if ( *src != ckey ) {
292 				  *dst = palmap[*src];
293 				}
294 				dst++;
295 				src++;
296 			},
297 			width);
298 			src += srcskip;
299 			dst += dstskip;
300 		}
301 	} else {
302 		while ( height-- ) {
303 			DUFFS_LOOP(
304 			{
305 				if ( *src != ckey ) {
306 				  *dst = *src;
307 				}
308 				dst++;
309 				src++;
310 			},
311 			width);
312 			src += srcskip;
313 			dst += dstskip;
314 		}
315 	}
316 }
317 
Blit1to2Key(SDL_BlitInfo * info)318 static void Blit1to2Key(SDL_BlitInfo *info)
319 {
320 	int width = info->d_width;
321 	int height = info->d_height;
322 	Uint8 *src = info->s_pixels;
323 	int srcskip = info->s_skip;
324 	Uint16 *dstp = (Uint16 *)info->d_pixels;
325 	int dstskip = info->d_skip;
326 	Uint16 *palmap = (Uint16 *)info->table;
327 	Uint32 ckey = info->src->colorkey;
328 
329 	/* Set up some basic variables */
330 	dstskip /= 2;
331 
332 	while ( height-- ) {
333 		DUFFS_LOOP(
334 		{
335 			if ( *src != ckey ) {
336 				*dstp=palmap[*src];
337 			}
338 			src++;
339 			dstp++;
340 		},
341 		width);
342 		src += srcskip;
343 		dstp += dstskip;
344 	}
345 }
346 
Blit1to3Key(SDL_BlitInfo * info)347 static void Blit1to3Key(SDL_BlitInfo *info)
348 {
349 	int width = info->d_width;
350 	int height = info->d_height;
351 	Uint8 *src = info->s_pixels;
352 	int srcskip = info->s_skip;
353 	Uint8 *dst = info->d_pixels;
354 	int dstskip = info->d_skip;
355 	Uint8 *palmap = info->table;
356 	Uint32 ckey = info->src->colorkey;
357 	int o;
358 
359 	while ( height-- ) {
360 		DUFFS_LOOP(
361 		{
362 			if ( *src != ckey ) {
363 				o = *src * 4;
364 				dst[0] = palmap[o++];
365 				dst[1] = palmap[o++];
366 				dst[2] = palmap[o++];
367 			}
368 			src++;
369 			dst += 3;
370 		},
371 		width);
372 		src += srcskip;
373 		dst += dstskip;
374 	}
375 }
376 
Blit1to4Key(SDL_BlitInfo * info)377 static void Blit1to4Key(SDL_BlitInfo *info)
378 {
379 	int width = info->d_width;
380 	int height = info->d_height;
381 	Uint8 *src = info->s_pixels;
382 	int srcskip = info->s_skip;
383 	Uint32 *dstp = (Uint32 *)info->d_pixels;
384 	int dstskip = info->d_skip;
385 	Uint32 *palmap = (Uint32 *)info->table;
386 	Uint32 ckey = info->src->colorkey;
387 
388 	/* Set up some basic variables */
389 	dstskip /= 4;
390 
391 	while ( height-- ) {
392 		DUFFS_LOOP(
393 		{
394 			if ( *src != ckey ) {
395 				*dstp = palmap[*src];
396 			}
397 			src++;
398 			dstp++;
399 		},
400 		width);
401 		src += srcskip;
402 		dstp += dstskip;
403 	}
404 }
405 
Blit1toNAlpha(SDL_BlitInfo * info)406 static void Blit1toNAlpha(SDL_BlitInfo *info)
407 {
408 	int width = info->d_width;
409 	int height = info->d_height;
410 	Uint8 *src = info->s_pixels;
411 	int srcskip = info->s_skip;
412 	Uint8 *dst = info->d_pixels;
413 	int dstskip = info->d_skip;
414 	SDL_PixelFormat *dstfmt = info->dst;
415 	const SDL_Color *srcpal	= info->src->palette->colors;
416 	int dstbpp;
417 	const int A = info->src->alpha;
418 
419 	/* Set up some basic variables */
420 	dstbpp = dstfmt->BytesPerPixel;
421 
422 	while ( height-- ) {
423 	        int sR, sG, sB;
424 		int dR, dG, dB;
425 	    	DUFFS_LOOP4(
426 			{
427 			        Uint32 pixel;
428 				sR = srcpal[*src].r;
429 				sG = srcpal[*src].g;
430 				sB = srcpal[*src].b;
431 				DISEMBLE_RGB(dst, dstbpp, dstfmt,
432 					     pixel, dR, dG, dB);
433 				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
434 			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
435 				src++;
436 				dst += dstbpp;
437 			},
438 			width);
439 		src += srcskip;
440 		dst += dstskip;
441 	}
442 }
443 
Blit1toNAlphaKey(SDL_BlitInfo * info)444 static void Blit1toNAlphaKey(SDL_BlitInfo *info)
445 {
446 	int width = info->d_width;
447 	int height = info->d_height;
448 	Uint8 *src = info->s_pixels;
449 	int srcskip = info->s_skip;
450 	Uint8 *dst = info->d_pixels;
451 	int dstskip = info->d_skip;
452 	SDL_PixelFormat *srcfmt = info->src;
453 	SDL_PixelFormat *dstfmt = info->dst;
454 	const SDL_Color *srcpal	= info->src->palette->colors;
455 	Uint32 ckey = srcfmt->colorkey;
456 	int dstbpp;
457 	const int A = srcfmt->alpha;
458 
459 	/* Set up some basic variables */
460 	dstbpp = dstfmt->BytesPerPixel;
461 
462 	while ( height-- ) {
463 	        int sR, sG, sB;
464 		int dR, dG, dB;
465 		DUFFS_LOOP(
466 		{
467 			if ( *src != ckey ) {
468 			        Uint32 pixel;
469 				sR = srcpal[*src].r;
470 				sG = srcpal[*src].g;
471 				sB = srcpal[*src].b;
472 				DISEMBLE_RGB(dst, dstbpp, dstfmt,
473 							pixel, dR, dG, dB);
474 				ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB);
475 			  	ASSEMBLE_RGB(dst, dstbpp, dstfmt, dR, dG, dB);
476 			}
477 			src++;
478 			dst += dstbpp;
479 		},
480 		width);
481 		src += srcskip;
482 		dst += dstskip;
483 	}
484 }
485 
486 static SDL_loblit one_blit[] = {
487 	NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
488 };
489 
490 static SDL_loblit one_blitkey[] = {
491         NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
492 };
493 
SDL_CalculateBlit1(SDL_Surface * surface,int blit_index)494 SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int blit_index)
495 {
496 	int which;
497 	SDL_PixelFormat *dstfmt;
498 
499 	dstfmt = surface->map->dst->format;
500 	if ( dstfmt->BitsPerPixel < 8 ) {
501 		which = 0;
502 	} else {
503 		which = dstfmt->BytesPerPixel;
504 	}
505 	switch(blit_index) {
506 	case 0:			/* copy */
507 	    return one_blit[which];
508 
509 	case 1:			/* colorkey */
510 	    return one_blitkey[which];
511 
512 	case 2:			/* alpha */
513 	    /* Supporting 8bpp->8bpp alpha is doable but requires lots of
514 	       tables which consume space and takes time to precompute,
515 	       so is better left to the user */
516 	    return which >= 2 ? Blit1toNAlpha : NULL;
517 
518 	case 3:			/* alpha + colorkey */
519 	    return which >= 2 ? Blit1toNAlphaKey : NULL;
520 
521 	}
522 	return NULL;
523 }
524