Mercurial > sdl-ios-xcode
comparison src/video/SDL_blit.h @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | e85e03f195b4 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:74212992fb08 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 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 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@devolution.com | |
21 */ | |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #ifndef _SDL_blit_h | |
29 #define _SDL_blit_h | |
30 | |
31 #include "SDL_endian.h" | |
32 | |
33 /* The structure passed to the low level blit functions */ | |
34 typedef struct { | |
35 Uint8 *s_pixels; | |
36 int s_width; | |
37 int s_height; | |
38 int s_skip; | |
39 Uint8 *d_pixels; | |
40 int d_width; | |
41 int d_height; | |
42 int d_skip; | |
43 void *aux_data; | |
44 SDL_PixelFormat *src; | |
45 Uint8 *table; | |
46 SDL_PixelFormat *dst; | |
47 } SDL_BlitInfo; | |
48 | |
49 /* The type definition for the low level blit functions */ | |
50 typedef void (*SDL_loblit)(SDL_BlitInfo *info); | |
51 | |
52 /* This is the private info structure for software accelerated blits */ | |
53 struct private_swaccel { | |
54 SDL_loblit blit; | |
55 void *aux_data; | |
56 }; | |
57 | |
58 /* Blit mapping definition */ | |
59 typedef struct SDL_BlitMap { | |
60 SDL_Surface *dst; | |
61 int identity; | |
62 Uint8 *table; | |
63 SDL_blit hw_blit; | |
64 SDL_blit sw_blit; | |
65 struct private_hwaccel *hw_data; | |
66 struct private_swaccel *sw_data; | |
67 | |
68 /* the version count matches the destination; mismatch indicates | |
69 an invalid mapping */ | |
70 unsigned int format_version; | |
71 } SDL_BlitMap; | |
72 | |
73 | |
74 /* Definitions for special global blit functions */ | |
75 #include "SDL_blit_A.h" | |
76 | |
77 /* Functions found in SDL_blit.c */ | |
78 extern int SDL_CalculateBlit(SDL_Surface *surface); | |
79 | |
80 /* Functions found in SDL_blit_{0,1,N,A}.c */ | |
81 extern SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int complex); | |
82 extern SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int complex); | |
83 extern SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex); | |
84 extern SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int complex); | |
85 | |
86 /* | |
87 * Useful macros for blitting routines | |
88 */ | |
89 | |
90 #define FORMAT_EQUAL(A, B) \ | |
91 ((A)->BitsPerPixel == (B)->BitsPerPixel \ | |
92 && ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask)) | |
93 | |
94 /* Load pixel of the specified format from a buffer and get its R-G-B values */ | |
95 /* FIXME: rescale values to 0..255 here? */ | |
96 #define RGB_FROM_PIXEL(pixel, fmt, r, g, b) \ | |
97 { \ | |
98 r = (((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); \ | |
99 g = (((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); \ | |
100 b = (((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); \ | |
101 } | |
102 #define RGB_FROM_RGB565(pixel, r, g, b) \ | |
103 { \ | |
104 r = (((pixel&0xF800)>>11)<<3); \ | |
105 g = (((pixel&0x07E0)>>5)<<2); \ | |
106 b = ((pixel&0x001F)<<3); \ | |
107 } | |
108 #define RGB_FROM_RGB555(pixel, r, g, b) \ | |
109 { \ | |
110 r = (((pixel&0x7C00)>>10)<<3); \ | |
111 g = (((pixel&0x03E0)>>5)<<3); \ | |
112 b = ((pixel&0x001F)<<3); \ | |
113 } | |
114 #define RGB_FROM_RGB888(pixel, r, g, b) \ | |
115 { \ | |
116 r = ((pixel&0xFF0000)>>16); \ | |
117 g = ((pixel&0xFF00)>>8); \ | |
118 b = (pixel&0xFF); \ | |
119 } | |
120 #define RETRIEVE_RGB_PIXEL(buf, bpp, pixel) \ | |
121 do { \ | |
122 switch (bpp) { \ | |
123 case 2: \ | |
124 pixel = *((Uint16 *)(buf)); \ | |
125 break; \ | |
126 \ | |
127 case 3: { \ | |
128 Uint8 *B = (Uint8 *)(buf); \ | |
129 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
130 pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ | |
131 } else { \ | |
132 pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ | |
133 } \ | |
134 } \ | |
135 break; \ | |
136 \ | |
137 case 4: \ | |
138 pixel = *((Uint32 *)(buf)); \ | |
139 break; \ | |
140 \ | |
141 default: \ | |
142 pixel = 0; /* appease gcc */ \ | |
143 break; \ | |
144 } \ | |
145 } while(0) | |
146 | |
147 #define DISEMBLE_RGB(buf, bpp, fmt, pixel, r, g, b) \ | |
148 do { \ | |
149 switch (bpp) { \ | |
150 case 2: \ | |
151 pixel = *((Uint16 *)(buf)); \ | |
152 break; \ | |
153 \ | |
154 case 3: { \ | |
155 Uint8 *B = (Uint8 *)buf; \ | |
156 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
157 pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ | |
158 } else { \ | |
159 pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ | |
160 } \ | |
161 } \ | |
162 break; \ | |
163 \ | |
164 case 4: \ | |
165 pixel = *((Uint32 *)(buf)); \ | |
166 break; \ | |
167 \ | |
168 default: \ | |
169 pixel = 0; /* prevent gcc from complaining */ \ | |
170 break; \ | |
171 } \ | |
172 RGB_FROM_PIXEL(pixel, fmt, r, g, b); \ | |
173 } while(0) | |
174 | |
175 /* Assemble R-G-B values into a specified pixel format and store them */ | |
176 #define PIXEL_FROM_RGB(pixel, fmt, r, g, b) \ | |
177 { \ | |
178 pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ | |
179 ((g>>fmt->Gloss)<<fmt->Gshift)| \ | |
180 ((b>>fmt->Bloss)<<fmt->Bshift); \ | |
181 } | |
182 #define RGB565_FROM_RGB(pixel, r, g, b) \ | |
183 { \ | |
184 pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3); \ | |
185 } | |
186 #define RGB555_FROM_RGB(pixel, r, g, b) \ | |
187 { \ | |
188 pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3); \ | |
189 } | |
190 #define RGB888_FROM_RGB(pixel, r, g, b) \ | |
191 { \ | |
192 pixel = (r<<16)|(g<<8)|b; \ | |
193 } | |
194 #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \ | |
195 { \ | |
196 switch (bpp) { \ | |
197 case 2: { \ | |
198 Uint16 pixel; \ | |
199 \ | |
200 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
201 *((Uint16 *)(buf)) = pixel; \ | |
202 } \ | |
203 break; \ | |
204 \ | |
205 case 3: { \ | |
206 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
207 *((buf)+fmt->Rshift/8) = r; \ | |
208 *((buf)+fmt->Gshift/8) = g; \ | |
209 *((buf)+fmt->Bshift/8) = b; \ | |
210 } else { \ | |
211 *((buf)+2-fmt->Rshift/8) = r; \ | |
212 *((buf)+2-fmt->Gshift/8) = g; \ | |
213 *((buf)+2-fmt->Bshift/8) = b; \ | |
214 } \ | |
215 } \ | |
216 break; \ | |
217 \ | |
218 case 4: { \ | |
219 Uint32 pixel; \ | |
220 \ | |
221 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
222 *((Uint32 *)(buf)) = pixel; \ | |
223 } \ | |
224 break; \ | |
225 } \ | |
226 } | |
227 #define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask) \ | |
228 { \ | |
229 switch (bpp) { \ | |
230 case 2: { \ | |
231 Uint16 *bufp; \ | |
232 Uint16 pixel; \ | |
233 \ | |
234 bufp = (Uint16 *)buf; \ | |
235 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
236 *bufp = pixel | (*bufp & Amask); \ | |
237 } \ | |
238 break; \ | |
239 \ | |
240 case 3: { \ | |
241 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
242 *((buf)+fmt->Rshift/8) = r; \ | |
243 *((buf)+fmt->Gshift/8) = g; \ | |
244 *((buf)+fmt->Bshift/8) = b; \ | |
245 } else { \ | |
246 *((buf)+2-fmt->Rshift/8) = r; \ | |
247 *((buf)+2-fmt->Gshift/8) = g; \ | |
248 *((buf)+2-fmt->Bshift/8) = b; \ | |
249 } \ | |
250 } \ | |
251 break; \ | |
252 \ | |
253 case 4: { \ | |
254 Uint32 *bufp; \ | |
255 Uint32 pixel; \ | |
256 \ | |
257 bufp = (Uint32 *)buf; \ | |
258 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
259 *bufp = pixel | (*bufp & Amask); \ | |
260 } \ | |
261 break; \ | |
262 } \ | |
263 } | |
264 | |
265 /* FIXME: Should we rescale alpha into 0..255 here? */ | |
266 #define RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a) \ | |
267 { \ | |
268 r = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; \ | |
269 g = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; \ | |
270 b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \ | |
271 a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \ | |
272 } | |
273 #define RGBA_FROM_8888(pixel, fmt, r, g, b, a) \ | |
274 { \ | |
275 r = (pixel&fmt->Rmask)>>fmt->Rshift; \ | |
276 g = (pixel&fmt->Gmask)>>fmt->Gshift; \ | |
277 b = (pixel&fmt->Bmask)>>fmt->Bshift; \ | |
278 a = (pixel&fmt->Amask)>>fmt->Ashift; \ | |
279 } | |
280 #define RGBA_FROM_RGBA8888(pixel, r, g, b, a) \ | |
281 { \ | |
282 r = (pixel>>24); \ | |
283 g = ((pixel>>16)&0xFF); \ | |
284 b = ((pixel>>8)&0xFF); \ | |
285 a = (pixel&0xFF); \ | |
286 } | |
287 #define RGBA_FROM_ARGB8888(pixel, r, g, b, a) \ | |
288 { \ | |
289 r = ((pixel>>16)&0xFF); \ | |
290 g = ((pixel>>8)&0xFF); \ | |
291 b = (pixel&0xFF); \ | |
292 a = (pixel>>24); \ | |
293 } | |
294 #define RGBA_FROM_ABGR8888(pixel, r, g, b, a) \ | |
295 { \ | |
296 r = (pixel&0xFF); \ | |
297 g = ((pixel>>8)&0xFF); \ | |
298 b = ((pixel>>16)&0xFF); \ | |
299 a = (pixel>>24); \ | |
300 } | |
301 #define DISEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a) \ | |
302 do { \ | |
303 switch (bpp) { \ | |
304 case 2: \ | |
305 pixel = *((Uint16 *)(buf)); \ | |
306 break; \ | |
307 \ | |
308 case 3: {/* FIXME: broken code (no alpha) */ \ | |
309 Uint8 *b = (Uint8 *)buf; \ | |
310 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
311 pixel = b[0] + (b[1] << 8) + (b[2] << 16); \ | |
312 } else { \ | |
313 pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \ | |
314 } \ | |
315 } \ | |
316 break; \ | |
317 \ | |
318 case 4: \ | |
319 pixel = *((Uint32 *)(buf)); \ | |
320 break; \ | |
321 \ | |
322 default: \ | |
323 pixel = 0; /* stop gcc complaints */ \ | |
324 break; \ | |
325 } \ | |
326 RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \ | |
327 pixel &= ~fmt->Amask; \ | |
328 } while(0) | |
329 | |
330 /* FIXME: this isn't correct, especially for Alpha (maximum != 255) */ | |
331 #define PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a) \ | |
332 { \ | |
333 pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ | |
334 ((g>>fmt->Gloss)<<fmt->Gshift)| \ | |
335 ((b>>fmt->Bloss)<<fmt->Bshift)| \ | |
336 ((a<<fmt->Aloss)<<fmt->Ashift); \ | |
337 } | |
338 #define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ | |
339 { \ | |
340 switch (bpp) { \ | |
341 case 2: { \ | |
342 Uint16 pixel; \ | |
343 \ | |
344 PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ | |
345 *((Uint16 *)(buf)) = pixel; \ | |
346 } \ | |
347 break; \ | |
348 \ | |
349 case 3: { /* FIXME: broken code (no alpha) */ \ | |
350 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
351 *((buf)+fmt->Rshift/8) = r; \ | |
352 *((buf)+fmt->Gshift/8) = g; \ | |
353 *((buf)+fmt->Bshift/8) = b; \ | |
354 } else { \ | |
355 *((buf)+2-fmt->Rshift/8) = r; \ | |
356 *((buf)+2-fmt->Gshift/8) = g; \ | |
357 *((buf)+2-fmt->Bshift/8) = b; \ | |
358 } \ | |
359 } \ | |
360 break; \ | |
361 \ | |
362 case 4: { \ | |
363 Uint32 pixel; \ | |
364 \ | |
365 PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ | |
366 *((Uint32 *)(buf)) = pixel; \ | |
367 } \ | |
368 break; \ | |
369 } \ | |
370 } | |
371 | |
372 /* Blend the RGB values of two pixels based on a source alpha value */ | |
373 #define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ | |
374 do { \ | |
375 dR = (((sR-dR)*(A))>>8)+dR; \ | |
376 dG = (((sG-dG)*(A))>>8)+dG; \ | |
377 dB = (((sB-dB)*(A))>>8)+dB; \ | |
378 } while(0) | |
379 | |
380 /* This is a very useful loop for optimizing blitters */ | |
381 #define USE_DUFFS_LOOP | |
382 #ifdef USE_DUFFS_LOOP | |
383 | |
384 /* 8-times unrolled loop */ | |
385 #define DUFFS_LOOP8(pixel_copy_increment, width) \ | |
386 { int n = (width+7)/8; \ | |
387 switch (width % 8) { \ | |
388 case 0: do { pixel_copy_increment; \ | |
389 case 7: pixel_copy_increment; \ | |
390 case 6: pixel_copy_increment; \ | |
391 case 5: pixel_copy_increment; \ | |
392 case 4: pixel_copy_increment; \ | |
393 case 3: pixel_copy_increment; \ | |
394 case 2: pixel_copy_increment; \ | |
395 case 1: pixel_copy_increment; \ | |
396 } while ( --n > 0 ); \ | |
397 } \ | |
398 } | |
399 | |
400 /* 4-times unrolled loop */ | |
401 #define DUFFS_LOOP4(pixel_copy_increment, width) \ | |
402 { int n = (width+3)/4; \ | |
403 switch (width % 4) { \ | |
404 case 0: do { pixel_copy_increment; \ | |
405 case 3: pixel_copy_increment; \ | |
406 case 2: pixel_copy_increment; \ | |
407 case 1: pixel_copy_increment; \ | |
408 } while ( --n > 0 ); \ | |
409 } \ | |
410 } | |
411 | |
412 /* Use the 8-times version of the loop by default */ | |
413 #define DUFFS_LOOP(pixel_copy_increment, width) \ | |
414 DUFFS_LOOP8(pixel_copy_increment, width) | |
415 | |
416 #else | |
417 | |
418 /* Don't use Duff's device to unroll loops */ | |
419 #define DUFFS_LOOP(pixel_copy_increment, width) \ | |
420 { int n; \ | |
421 for ( n=width; n > 0; --n ) { \ | |
422 pixel_copy_increment; \ | |
423 } \ | |
424 } | |
425 #define DUFFS_LOOP8(pixel_copy_increment, width) \ | |
426 DUFFS_LOOP(pixel_copy_increment, width) | |
427 #define DUFFS_LOOP4(pixel_copy_increment, width) \ | |
428 DUFFS_LOOP(pixel_copy_increment, width) | |
429 | |
430 #endif /* USE_DUFFS_LOOP */ | |
431 | |
432 /* Prevent Visual C++ 6.0 from printing out stupid warnings */ | |
433 #if defined(_MSC_VER) && (_MSC_VER >= 600) | |
434 #pragma warning(disable: 4550) | |
435 #endif | |
436 | |
437 #endif /* _SDL_blit_h */ |