1 /*
2 
3 SDL_gfxBlitFunc.c: custom blitters
4 
5 Copyright (C) 2001-2012  Andreas Schiffler
6 
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any damages
9 arising from the use of this software.
10 
11 Permission is granted to anyone to use this software for any purpose,
12 including commercial applications, and to alter it and redistribute it
13 freely, subject to the following restrictions:
14 
15 1. The origin of this software must not be misrepresented; you must not
16 claim that you wrote the original software. If you use this software
17 in a product, an acknowledgment in the product documentation would be
18 appreciated but is not required.
19 
20 2. Altered source versions must be plainly marked as such, and must not be
21 misrepresented as being the original software.
22 
23 3. This notice may not be removed or altered from any source
24 distribution.
25 
26 Andreas Schiffler -- aschiffler at ferzkopp dot net
27 
28 */
29 
30 #include "SDL_gfxBlitFunc.h"
31 
32 /*!
33 \brief Alpha adjustment table for custom blitter.
34 
35 The table provides values for a modified, non-linear
36 transfer function which maintain brightness.
37 
38 */
39 const unsigned int GFX_ALPHA_ADJUST_ARRAY[256] = {
40 	0,  /* 0 */
41 	15,  /* 1 */
42 	22,  /* 2 */
43 	27,  /* 3 */
44 	31,  /* 4 */
45 	35,  /* 5 */
46 	39,  /* 6 */
47 	42,  /* 7 */
48 	45,  /* 8 */
49 	47,  /* 9 */
50 	50,  /* 10 */
51 	52,  /* 11 */
52 	55,  /* 12 */
53 	57,  /* 13 */
54 	59,  /* 14 */
55 	61,  /* 15 */
56 	63,  /* 16 */
57 	65,  /* 17 */
58 	67,  /* 18 */
59 	69,  /* 19 */
60 	71,  /* 20 */
61 	73,  /* 21 */
62 	74,  /* 22 */
63 	76,  /* 23 */
64 	78,  /* 24 */
65 	79,  /* 25 */
66 	81,  /* 26 */
67 	82,  /* 27 */
68 	84,  /* 28 */
69 	85,  /* 29 */
70 	87,  /* 30 */
71 	88,  /* 31 */
72 	90,  /* 32 */
73 	91,  /* 33 */
74 	93,  /* 34 */
75 	94,  /* 35 */
76 	95,  /* 36 */
77 	97,  /* 37 */
78 	98,  /* 38 */
79 	99,  /* 39 */
80 	100,  /* 40 */
81 	102,  /* 41 */
82 	103,  /* 42 */
83 	104,  /* 43 */
84 	105,  /* 44 */
85 	107,  /* 45 */
86 	108,  /* 46 */
87 	109,  /* 47 */
88 	110,  /* 48 */
89 	111,  /* 49 */
90 	112,  /* 50 */
91 	114,  /* 51 */
92 	115,  /* 52 */
93 	116,  /* 53 */
94 	117,  /* 54 */
95 	118,  /* 55 */
96 	119,  /* 56 */
97 	120,  /* 57 */
98 	121,  /* 58 */
99 	122,  /* 59 */
100 	123,  /* 60 */
101 	124,  /* 61 */
102 	125,  /* 62 */
103 	126,  /* 63 */
104 	127,  /* 64 */
105 	128,  /* 65 */
106 	129,  /* 66 */
107 	130,  /* 67 */
108 	131,  /* 68 */
109 	132,  /* 69 */
110 	133,  /* 70 */
111 	134,  /* 71 */
112 	135,  /* 72 */
113 	136,  /* 73 */
114 	137,  /* 74 */
115 	138,  /* 75 */
116 	139,  /* 76 */
117 	140,  /* 77 */
118 	141,  /* 78 */
119 	141,  /* 79 */
120 	142,  /* 80 */
121 	143,  /* 81 */
122 	144,  /* 82 */
123 	145,  /* 83 */
124 	146,  /* 84 */
125 	147,  /* 85 */
126 	148,  /* 86 */
127 	148,  /* 87 */
128 	149,  /* 88 */
129 	150,  /* 89 */
130 	151,  /* 90 */
131 	152,  /* 91 */
132 	153,  /* 92 */
133 	153,  /* 93 */
134 	154,  /* 94 */
135 	155,  /* 95 */
136 	156,  /* 96 */
137 	157,  /* 97 */
138 	158,  /* 98 */
139 	158,  /* 99 */
140 	159,  /* 100 */
141 	160,  /* 101 */
142 	161,  /* 102 */
143 	162,  /* 103 */
144 	162,  /* 104 */
145 	163,  /* 105 */
146 	164,  /* 106 */
147 	165,  /* 107 */
148 	165,  /* 108 */
149 	166,  /* 109 */
150 	167,  /* 110 */
151 	168,  /* 111 */
152 	168,  /* 112 */
153 	169,  /* 113 */
154 	170,  /* 114 */
155 	171,  /* 115 */
156 	171,  /* 116 */
157 	172,  /* 117 */
158 	173,  /* 118 */
159 	174,  /* 119 */
160 	174,  /* 120 */
161 	175,  /* 121 */
162 	176,  /* 122 */
163 	177,  /* 123 */
164 	177,  /* 124 */
165 	178,  /* 125 */
166 	179,  /* 126 */
167 	179,  /* 127 */
168 	180,  /* 128 */
169 	181,  /* 129 */
170 	182,  /* 130 */
171 	182,  /* 131 */
172 	183,  /* 132 */
173 	184,  /* 133 */
174 	184,  /* 134 */
175 	185,  /* 135 */
176 	186,  /* 136 */
177 	186,  /* 137 */
178 	187,  /* 138 */
179 	188,  /* 139 */
180 	188,  /* 140 */
181 	189,  /* 141 */
182 	190,  /* 142 */
183 	190,  /* 143 */
184 	191,  /* 144 */
185 	192,  /* 145 */
186 	192,  /* 146 */
187 	193,  /* 147 */
188 	194,  /* 148 */
189 	194,  /* 149 */
190 	195,  /* 150 */
191 	196,  /* 151 */
192 	196,  /* 152 */
193 	197,  /* 153 */
194 	198,  /* 154 */
195 	198,  /* 155 */
196 	199,  /* 156 */
197 	200,  /* 157 */
198 	200,  /* 158 */
199 	201,  /* 159 */
200 	201,  /* 160 */
201 	202,  /* 161 */
202 	203,  /* 162 */
203 	203,  /* 163 */
204 	204,  /* 164 */
205 	205,  /* 165 */
206 	205,  /* 166 */
207 	206,  /* 167 */
208 	206,  /* 168 */
209 	207,  /* 169 */
210 	208,  /* 170 */
211 	208,  /* 171 */
212 	209,  /* 172 */
213 	210,  /* 173 */
214 	210,  /* 174 */
215 	211,  /* 175 */
216 	211,  /* 176 */
217 	212,  /* 177 */
218 	213,  /* 178 */
219 	213,  /* 179 */
220 	214,  /* 180 */
221 	214,  /* 181 */
222 	215,  /* 182 */
223 	216,  /* 183 */
224 	216,  /* 184 */
225 	217,  /* 185 */
226 	217,  /* 186 */
227 	218,  /* 187 */
228 	218,  /* 188 */
229 	219,  /* 189 */
230 	220,  /* 190 */
231 	220,  /* 191 */
232 	221,  /* 192 */
233 	221,  /* 193 */
234 	222,  /* 194 */
235 	222,  /* 195 */
236 	223,  /* 196 */
237 	224,  /* 197 */
238 	224,  /* 198 */
239 	225,  /* 199 */
240 	225,  /* 200 */
241 	226,  /* 201 */
242 	226,  /* 202 */
243 	227,  /* 203 */
244 	228,  /* 204 */
245 	228,  /* 205 */
246 	229,  /* 206 */
247 	229,  /* 207 */
248 	230,  /* 208 */
249 	230,  /* 209 */
250 	231,  /* 210 */
251 	231,  /* 211 */
252 	232,  /* 212 */
253 	233,  /* 213 */
254 	233,  /* 214 */
255 	234,  /* 215 */
256 	234,  /* 216 */
257 	235,  /* 217 */
258 	235,  /* 218 */
259 	236,  /* 219 */
260 	236,  /* 220 */
261 	237,  /* 221 */
262 	237,  /* 222 */
263 	238,  /* 223 */
264 	238,  /* 224 */
265 	239,  /* 225 */
266 	240,  /* 226 */
267 	240,  /* 227 */
268 	241,  /* 228 */
269 	241,  /* 229 */
270 	242,  /* 230 */
271 	242,  /* 231 */
272 	243,  /* 232 */
273 	243,  /* 233 */
274 	244,  /* 234 */
275 	244,  /* 235 */
276 	245,  /* 236 */
277 	245,  /* 237 */
278 	246,  /* 238 */
279 	246,  /* 239 */
280 	247,  /* 240 */
281 	247,  /* 241 */
282 	248,  /* 242 */
283 	248,  /* 243 */
284 	249,  /* 244 */
285 	249,  /* 245 */
286 	250,  /* 246 */
287 	250,  /* 247 */
288 	251,  /* 248 */
289 	251,  /* 249 */
290 	252,  /* 250 */
291 	252,  /* 251 */
292 	253,  /* 252 */
293 	253,  /* 253 */
294 	254,  /* 254 */
295 	255   /* 255 */
296 };
297 
298 /*!
299 \brief Internal blitter using adjusted destination alpha during RGBA->RGBA blits.
300 
301 Performs the blit based on the 'info' structure and applies the transfer function
302 to the destination 'a' values.
303 
304 \param info The blit info to use.
305 */
_SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo * info)306 void _SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo * info)
307 {
308 	int       width = info->d_width;
309 	int       height = info->d_height;
310 	Uint8    *src = info->s_pixels;
311 	int       srcskip = info->s_skip;
312 	Uint8    *dst = info->d_pixels;
313 	int       dstskip = info->d_skip;
314 	SDL_PixelFormat *srcfmt = info->src;
315 	SDL_PixelFormat *dstfmt = info->dst;
316 	Uint8       srcbpp = srcfmt->BytesPerPixel;
317 	Uint8       dstbpp = dstfmt->BytesPerPixel;
318 
319 	while (height--) {
320 		GFX_DUFFS_LOOP4( {
321 			Uint32 pixel;
322 			unsigned sR;
323 			unsigned sG;
324 			unsigned sB;
325 			unsigned sA;
326 			unsigned dR;
327 			unsigned dG;
328 			unsigned dB;
329 			unsigned dA;
330 			unsigned sAA;
331 			GFX_DISASSEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA);
332 			GFX_DISASSEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
333 			sAA=GFX_ALPHA_ADJUST_ARRAY[sA & 255];
334 			GFX_ALPHA_BLEND(sR, sG, sB, sAA, dR, dG, dB);
335 			dA |= sAA;
336 			GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
337 			src += srcbpp; dst += dstbpp;
338 		}, width);
339 		src += srcskip;
340 		dst += dstskip;
341 	}
342 }
343 
344 /*!
345 \brief Internal blitter setup wrapper for RGBA->RGBA blits.
346 
347 Sets up the blitter info based on the 'src' and 'dst' surfaces and rectangles.
348 
349 \param src The source surface.
350 \param srcrect The source rectangle.
351 \param dst The destination surface.
352 \param dstrect The destination rectangle.
353 
354 \returns Returns 1 if blit was performed, 0 otherwise.
355 */
_SDL_gfxBlitRGBACall(SDL_Surface * src,SDL_Rect * srcrect,SDL_Surface * dst,SDL_Rect * dstrect)356 int _SDL_gfxBlitRGBACall(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect)
357 {
358 	/*
359 	* Set up source and destination buffer pointers, then blit
360 	*/
361 	if (srcrect->w && srcrect->h) {
362 		SDL_gfxBlitInfo info;
363 
364 		/*
365 		* Set up the blit information
366 		*/
367 #if (SDL_MINOR_VERSION == 3)
368 		info.s_pixels = (Uint8 *) src->pixels               + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel;
369 #else
370 		info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel;
371 #endif
372 		info.s_width = srcrect->w;
373 		info.s_height = srcrect->h;
374 		info.s_skip = (int)(src->pitch - info.s_width * src->format->BytesPerPixel);
375 #if (SDL_MINOR_VERSION == 3)
376 		info.d_pixels = (Uint8 *) dst->pixels               + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel;
377 #else
378 		info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel;
379 #endif
380 		info.d_width = dstrect->w;
381 		info.d_height = dstrect->h;
382 		info.d_skip = (int)(dst->pitch - info.d_width * dst->format->BytesPerPixel);
383 		info.aux_data = NULL;
384 		info.src = src->format;
385 		info.table = NULL;
386 		info.dst = dst->format;
387 
388 		/*
389 		* Run the actual software blitter
390 		*/
391 		_SDL_gfxBlitBlitterRGBA(&info);
392 		return 1;
393 	}
394 
395 	return (0);
396 }
397 
398 /*!
399 \brief Blitter for RGBA->RGBA blits with alpha adjustment.
400 
401 Verifies the input 'src' and 'dst' surfaces and rectangles and performs blit.
402 The destination clip rectangle is honored.
403 
404 \param src The source surface.
405 \param srcrect The source rectangle.
406 \param dst The destination surface.
407 \param dstrect The destination rectangle.
408 
409 \returns Returns 1 if blit was performed, 0 otherwise, or -1 if an error occured.
410 */
SDL_gfxBlitRGBA(SDL_Surface * src,SDL_Rect * srcrect,SDL_Surface * dst,SDL_Rect * dstrect)411 int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect)
412 {
413 	SDL_Rect  sr, dr;
414 	int       srcx, srcy, w, h;
415 
416 	/*
417 	* Make sure the surfaces aren't locked
418 	*/
419 	if (!src || !dst) {
420 		SDL_SetError("SDL_UpperBlit: passed a NULL surface");
421 		return (-1);
422 	}
423 	if ((src->locked) || (dst->locked)) {
424 		SDL_SetError("Surfaces must not be locked during blit");
425 		return (-1);
426 	}
427 
428 	/*
429 	* If the destination rectangle is NULL, use the entire dest surface
430 	*/
431 	if (dstrect == NULL) {
432 		dr.x = dr.y = 0;
433 		dr.w = dst->w;
434 		dr.h = dst->h;
435 	} else {
436 		dr = *dstrect;
437 	}
438 
439 	/*
440 	* Clip the source rectangle to the source surface
441 	*/
442 	if (srcrect) {
443 		int       maxw, maxh;
444 
445 		srcx = srcrect->x;
446 		w = srcrect->w;
447 		if (srcx < 0) {
448 			w += srcx;
449 			dr.x -= srcx;
450 			srcx = 0;
451 		}
452 		maxw = src->w - srcx;
453 		if (maxw < w)
454 			w = maxw;
455 
456 		srcy = srcrect->y;
457 		h = srcrect->h;
458 		if (srcy < 0) {
459 			h += srcy;
460 			dr.y -= srcy;
461 			srcy = 0;
462 		}
463 		maxh = src->h - srcy;
464 		if (maxh < h)
465 			h = maxh;
466 
467 	} else {
468 		srcx = srcy = 0;
469 		w = src->w;
470 		h = src->h;
471 	}
472 
473 	/*
474 	* Clip the destination rectangle against the clip rectangle
475 	*/
476 	{
477 		SDL_Rect *clip = &dst->clip_rect;
478 		int       dx, dy;
479 
480 		dx = clip->x - dr.x;
481 		if (dx > 0) {
482 			w -= dx;
483 			dr.x += dx;
484 			srcx += dx;
485 		}
486 		dx = dr.x + w - clip->x - clip->w;
487 		if (dx > 0)
488 			w -= dx;
489 
490 		dy = clip->y - dr.y;
491 		if (dy > 0) {
492 			h -= dy;
493 			dr.y += dy;
494 			srcy += dy;
495 		}
496 		dy = dr.y + h - clip->y - clip->h;
497 		if (dy > 0)
498 			h -= dy;
499 	}
500 
501 	if (w > 0 && h > 0) {
502 		sr.x = srcx;
503 		sr.y = srcy;
504 		sr.w = dr.w = w;
505 		sr.h = dr.h = h;
506 		return (_SDL_gfxBlitRGBACall(src, &sr, dst, &dr));
507 	}
508 
509 	return 0;
510 }
511 
512 /*!
513 \brief Sets the alpha channel in a 32 bit surface.
514 
515 Helper function that sets the alpha channel in a 32 bit surface
516 to a constant value.
517 Only 32 bit surfaces can be used with this function.
518 
519 \param src Pointer to the target surface to change.
520 \param a The alpha value to set.
521 
522 \return Returns 1 if alpha was changed, -1 otherwise.
523 */
SDL_gfxSetAlpha(SDL_Surface * src,Uint8 a)524 int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a)
525 {
526 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
527 	const int alpha_offset = 0;
528 #else
529 	const int alpha_offset = 3;
530 #endif
531 	int i, j, row_skip;
532 	Uint8 *pixels;
533 
534 	/* Check if we have a 32bit surface */
535 	if ( (src==NULL) ||
536 		(src->format==NULL) ||
537 		(src->format->BytesPerPixel!=4) ) {
538 			SDL_SetError("SDL_gfxSetAlpha: Invalid input surface.");
539 			return -1;
540 	}
541 
542 	/*
543 	* Lock the surface
544 	*/
545 	if (SDL_MUSTLOCK(src)) {
546 		if (SDL_LockSurface(src) < 0) {
547 			return (-1);
548 		}
549 	}
550 
551 	/* Process */
552 	pixels = (Uint8 *)src->pixels;
553 	row_skip = (src->pitch - (4*src->w));
554 	pixels += alpha_offset;
555 	for ( i=0; i<src->h; i++ ) {
556 		for ( j=0; j<src->w; j++  ) {
557 			*pixels = a;
558 			pixels += 4;
559 		}
560 		pixels += row_skip;
561 	}
562 
563 	/*
564 	* Unlock surface
565 	*/
566 	if (SDL_MUSTLOCK(src)) {
567 		SDL_UnlockSurface(src);
568 	}
569 
570 	return 1;
571 }
572 
573 /*!
574 \brief Multiply the alpha channel in a 32bit surface.
575 
576 Helper function that multiplies the alpha channel in a 32 bit surface
577 with a constant value. The final alpha is always scaled to the range
578 0-255 (i.e. the factor is a/256).
579 
580 Only 32 bit surfaces can be used with this function.
581 
582 \param src Pointer to the target surface to change.
583 \param a The alpha value to multiply with. When a is 255, this function is a NoOp.
584 
585 \return Returns 1 if alpha was changed, 0 otherwise. Returns -1 if input surface is invalid.
586 */
SDL_gfxMultiplyAlpha(SDL_Surface * src,Uint8 a)587 int SDL_gfxMultiplyAlpha(SDL_Surface *src, Uint8 a)
588 {
589 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
590 	const int alpha_offset = 0;
591 #else
592 	const int alpha_offset = 3;
593 #endif
594 	int i, j, row_skip;
595 	Uint8 *pixels;
596 
597 	/* Check if we have a 32bit surface */
598 	if ( (src==NULL) ||
599 		(src->format==NULL) ||
600 		(src->format->BytesPerPixel!=4) ) {
601 			SDL_SetError("SDL_gfxMultiplyAlpha: Invalid input surface.");
602 			return -1;
603 	}
604 
605 	/* Check if multiplication is needed */
606 	if (a==255) {
607 		return 0;
608 	}
609 
610 	/*
611 	* Lock the surface
612 	*/
613 	if (SDL_MUSTLOCK(src)) {
614 		if (SDL_LockSurface(src) < 0) {
615 			return (-1);
616 		}
617 	}
618 
619 	/* Process */
620 	pixels = (Uint8 *)src->pixels;
621 	row_skip = (src->pitch - (4*src->w));
622 	pixels += alpha_offset;
623 	for ( i=0; i<src->h; i++ ) {
624 		for ( j=0; j<src->w; j++  ) {
625 			*pixels = (Uint8)(((int)(*pixels)*a)>>8);
626 			pixels += 4;
627 		}
628 		pixels += row_skip;
629 	}
630 
631 	/*
632 	* Unlock surface
633 	*/
634 	if (SDL_MUSTLOCK(src)) {
635 		SDL_UnlockSurface(src);
636 	}
637 
638 	return 1;
639 }
640