Mercurial > sdl-ios-xcode
annotate src/video/SDL_blit.h @ 477:22581630aab7
Date: Tue, 27 Aug 2002 16:14:11 +0200
From: Denis Oliver Kropp
Subject: Palette support and 8bit color keying fix
This patch adds support for 8bit palette modes dropping
the RGB332 stuff. It also fixes color keying for 8bit.
testsprite (without -bpp >8) looks correct again.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 31 Aug 2002 04:06:37 +0000 |
parents | f6ffac90895c |
children | 917cc5c56176 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
163
diff
changeset
|
20 slouken@libsdl.org |
0 | 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 /* Functions found in SDL_blit.c */ | |
75 extern int SDL_CalculateBlit(SDL_Surface *surface); | |
76 | |
77 /* Functions found in SDL_blit_{0,1,N,A}.c */ | |
78 extern SDL_loblit SDL_CalculateBlit0(SDL_Surface *surface, int complex); | |
79 extern SDL_loblit SDL_CalculateBlit1(SDL_Surface *surface, int complex); | |
80 extern SDL_loblit SDL_CalculateBlitN(SDL_Surface *surface, int complex); | |
81 extern SDL_loblit SDL_CalculateAlphaBlit(SDL_Surface *surface, int complex); | |
82 | |
83 /* | |
84 * Useful macros for blitting routines | |
85 */ | |
86 | |
87 #define FORMAT_EQUAL(A, B) \ | |
88 ((A)->BitsPerPixel == (B)->BitsPerPixel \ | |
89 && ((A)->Rmask == (B)->Rmask) && ((A)->Amask == (B)->Amask)) | |
90 | |
91 /* Load pixel of the specified format from a buffer and get its R-G-B values */ | |
92 /* FIXME: rescale values to 0..255 here? */ | |
93 #define RGB_FROM_PIXEL(pixel, fmt, r, g, b) \ | |
94 { \ | |
95 r = (((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss); \ | |
96 g = (((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss); \ | |
97 b = (((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss); \ | |
98 } | |
99 #define RGB_FROM_RGB565(pixel, r, g, b) \ | |
100 { \ | |
101 r = (((pixel&0xF800)>>11)<<3); \ | |
102 g = (((pixel&0x07E0)>>5)<<2); \ | |
103 b = ((pixel&0x001F)<<3); \ | |
104 } | |
105 #define RGB_FROM_RGB555(pixel, r, g, b) \ | |
106 { \ | |
107 r = (((pixel&0x7C00)>>10)<<3); \ | |
108 g = (((pixel&0x03E0)>>5)<<3); \ | |
109 b = ((pixel&0x001F)<<3); \ | |
110 } | |
111 #define RGB_FROM_RGB888(pixel, r, g, b) \ | |
112 { \ | |
113 r = ((pixel&0xFF0000)>>16); \ | |
114 g = ((pixel&0xFF00)>>8); \ | |
115 b = (pixel&0xFF); \ | |
116 } | |
117 #define RETRIEVE_RGB_PIXEL(buf, bpp, pixel) \ | |
118 do { \ | |
119 switch (bpp) { \ | |
120 case 2: \ | |
121 pixel = *((Uint16 *)(buf)); \ | |
122 break; \ | |
123 \ | |
124 case 3: { \ | |
125 Uint8 *B = (Uint8 *)(buf); \ | |
126 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
127 pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ | |
128 } else { \ | |
129 pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ | |
130 } \ | |
131 } \ | |
132 break; \ | |
133 \ | |
134 case 4: \ | |
135 pixel = *((Uint32 *)(buf)); \ | |
136 break; \ | |
137 \ | |
138 default: \ | |
139 pixel = 0; /* appease gcc */ \ | |
140 break; \ | |
141 } \ | |
142 } while(0) | |
143 | |
144 #define DISEMBLE_RGB(buf, bpp, fmt, pixel, r, g, b) \ | |
145 do { \ | |
146 switch (bpp) { \ | |
147 case 2: \ | |
148 pixel = *((Uint16 *)(buf)); \ | |
149 break; \ | |
150 \ | |
151 case 3: { \ | |
152 Uint8 *B = (Uint8 *)buf; \ | |
153 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
154 pixel = B[0] + (B[1] << 8) + (B[2] << 16); \ | |
155 } else { \ | |
156 pixel = (B[0] << 16) + (B[1] << 8) + B[2]; \ | |
157 } \ | |
158 } \ | |
159 break; \ | |
160 \ | |
161 case 4: \ | |
162 pixel = *((Uint32 *)(buf)); \ | |
163 break; \ | |
164 \ | |
165 default: \ | |
166 pixel = 0; /* prevent gcc from complaining */ \ | |
167 break; \ | |
168 } \ | |
169 RGB_FROM_PIXEL(pixel, fmt, r, g, b); \ | |
170 } while(0) | |
171 | |
172 /* Assemble R-G-B values into a specified pixel format and store them */ | |
173 #define PIXEL_FROM_RGB(pixel, fmt, r, g, b) \ | |
174 { \ | |
175 pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ | |
176 ((g>>fmt->Gloss)<<fmt->Gshift)| \ | |
177 ((b>>fmt->Bloss)<<fmt->Bshift); \ | |
178 } | |
179 #define RGB565_FROM_RGB(pixel, r, g, b) \ | |
180 { \ | |
181 pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3); \ | |
182 } | |
183 #define RGB555_FROM_RGB(pixel, r, g, b) \ | |
184 { \ | |
185 pixel = ((r>>3)<<10)|((g>>3)<<5)|(b>>3); \ | |
186 } | |
187 #define RGB888_FROM_RGB(pixel, r, g, b) \ | |
188 { \ | |
189 pixel = (r<<16)|(g<<8)|b; \ | |
190 } | |
191 #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \ | |
192 { \ | |
193 switch (bpp) { \ | |
194 case 2: { \ | |
195 Uint16 pixel; \ | |
196 \ | |
197 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
198 *((Uint16 *)(buf)) = pixel; \ | |
199 } \ | |
200 break; \ | |
201 \ | |
202 case 3: { \ | |
203 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
204 *((buf)+fmt->Rshift/8) = r; \ | |
205 *((buf)+fmt->Gshift/8) = g; \ | |
206 *((buf)+fmt->Bshift/8) = b; \ | |
207 } else { \ | |
208 *((buf)+2-fmt->Rshift/8) = r; \ | |
209 *((buf)+2-fmt->Gshift/8) = g; \ | |
210 *((buf)+2-fmt->Bshift/8) = b; \ | |
211 } \ | |
212 } \ | |
213 break; \ | |
214 \ | |
215 case 4: { \ | |
216 Uint32 pixel; \ | |
217 \ | |
218 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
219 *((Uint32 *)(buf)) = pixel; \ | |
220 } \ | |
221 break; \ | |
222 } \ | |
223 } | |
224 #define ASSEMBLE_RGB_AMASK(buf, bpp, fmt, r, g, b, Amask) \ | |
225 { \ | |
226 switch (bpp) { \ | |
227 case 2: { \ | |
228 Uint16 *bufp; \ | |
229 Uint16 pixel; \ | |
230 \ | |
231 bufp = (Uint16 *)buf; \ | |
232 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
233 *bufp = pixel | (*bufp & Amask); \ | |
234 } \ | |
235 break; \ | |
236 \ | |
237 case 3: { \ | |
238 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
239 *((buf)+fmt->Rshift/8) = r; \ | |
240 *((buf)+fmt->Gshift/8) = g; \ | |
241 *((buf)+fmt->Bshift/8) = b; \ | |
242 } else { \ | |
243 *((buf)+2-fmt->Rshift/8) = r; \ | |
244 *((buf)+2-fmt->Gshift/8) = g; \ | |
245 *((buf)+2-fmt->Bshift/8) = b; \ | |
246 } \ | |
247 } \ | |
248 break; \ | |
249 \ | |
250 case 4: { \ | |
251 Uint32 *bufp; \ | |
252 Uint32 pixel; \ | |
253 \ | |
254 bufp = (Uint32 *)buf; \ | |
255 PIXEL_FROM_RGB(pixel, fmt, r, g, b); \ | |
256 *bufp = pixel | (*bufp & Amask); \ | |
257 } \ | |
258 break; \ | |
259 } \ | |
260 } | |
261 | |
262 /* FIXME: Should we rescale alpha into 0..255 here? */ | |
263 #define RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a) \ | |
264 { \ | |
265 r = ((pixel&fmt->Rmask)>>fmt->Rshift)<<fmt->Rloss; \ | |
266 g = ((pixel&fmt->Gmask)>>fmt->Gshift)<<fmt->Gloss; \ | |
267 b = ((pixel&fmt->Bmask)>>fmt->Bshift)<<fmt->Bloss; \ | |
268 a = ((pixel&fmt->Amask)>>fmt->Ashift)<<fmt->Aloss; \ | |
269 } | |
270 #define RGBA_FROM_8888(pixel, fmt, r, g, b, a) \ | |
271 { \ | |
272 r = (pixel&fmt->Rmask)>>fmt->Rshift; \ | |
273 g = (pixel&fmt->Gmask)>>fmt->Gshift; \ | |
274 b = (pixel&fmt->Bmask)>>fmt->Bshift; \ | |
275 a = (pixel&fmt->Amask)>>fmt->Ashift; \ | |
276 } | |
277 #define RGBA_FROM_RGBA8888(pixel, r, g, b, a) \ | |
278 { \ | |
279 r = (pixel>>24); \ | |
280 g = ((pixel>>16)&0xFF); \ | |
281 b = ((pixel>>8)&0xFF); \ | |
282 a = (pixel&0xFF); \ | |
283 } | |
284 #define RGBA_FROM_ARGB8888(pixel, r, g, b, a) \ | |
285 { \ | |
286 r = ((pixel>>16)&0xFF); \ | |
287 g = ((pixel>>8)&0xFF); \ | |
288 b = (pixel&0xFF); \ | |
289 a = (pixel>>24); \ | |
290 } | |
291 #define RGBA_FROM_ABGR8888(pixel, r, g, b, a) \ | |
292 { \ | |
293 r = (pixel&0xFF); \ | |
294 g = ((pixel>>8)&0xFF); \ | |
295 b = ((pixel>>16)&0xFF); \ | |
296 a = (pixel>>24); \ | |
297 } | |
298 #define DISEMBLE_RGBA(buf, bpp, fmt, pixel, r, g, b, a) \ | |
299 do { \ | |
300 switch (bpp) { \ | |
301 case 2: \ | |
302 pixel = *((Uint16 *)(buf)); \ | |
303 break; \ | |
304 \ | |
305 case 3: {/* FIXME: broken code (no alpha) */ \ | |
306 Uint8 *b = (Uint8 *)buf; \ | |
307 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
308 pixel = b[0] + (b[1] << 8) + (b[2] << 16); \ | |
309 } else { \ | |
310 pixel = (b[0] << 16) + (b[1] << 8) + b[2]; \ | |
311 } \ | |
312 } \ | |
313 break; \ | |
314 \ | |
315 case 4: \ | |
316 pixel = *((Uint32 *)(buf)); \ | |
317 break; \ | |
318 \ | |
319 default: \ | |
320 pixel = 0; /* stop gcc complaints */ \ | |
321 break; \ | |
322 } \ | |
323 RGBA_FROM_PIXEL(pixel, fmt, r, g, b, a); \ | |
324 pixel &= ~fmt->Amask; \ | |
325 } while(0) | |
326 | |
327 /* FIXME: this isn't correct, especially for Alpha (maximum != 255) */ | |
328 #define PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a) \ | |
329 { \ | |
330 pixel = ((r>>fmt->Rloss)<<fmt->Rshift)| \ | |
331 ((g>>fmt->Gloss)<<fmt->Gshift)| \ | |
332 ((b>>fmt->Bloss)<<fmt->Bshift)| \ | |
333 ((a<<fmt->Aloss)<<fmt->Ashift); \ | |
334 } | |
335 #define ASSEMBLE_RGBA(buf, bpp, fmt, r, g, b, a) \ | |
336 { \ | |
337 switch (bpp) { \ | |
338 case 2: { \ | |
339 Uint16 pixel; \ | |
340 \ | |
341 PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ | |
342 *((Uint16 *)(buf)) = pixel; \ | |
343 } \ | |
344 break; \ | |
345 \ | |
346 case 3: { /* FIXME: broken code (no alpha) */ \ | |
347 if(SDL_BYTEORDER == SDL_LIL_ENDIAN) { \ | |
348 *((buf)+fmt->Rshift/8) = r; \ | |
349 *((buf)+fmt->Gshift/8) = g; \ | |
350 *((buf)+fmt->Bshift/8) = b; \ | |
351 } else { \ | |
352 *((buf)+2-fmt->Rshift/8) = r; \ | |
353 *((buf)+2-fmt->Gshift/8) = g; \ | |
354 *((buf)+2-fmt->Bshift/8) = b; \ | |
355 } \ | |
356 } \ | |
357 break; \ | |
358 \ | |
359 case 4: { \ | |
360 Uint32 pixel; \ | |
361 \ | |
362 PIXEL_FROM_RGBA(pixel, fmt, r, g, b, a); \ | |
363 *((Uint32 *)(buf)) = pixel; \ | |
364 } \ | |
365 break; \ | |
366 } \ | |
367 } | |
368 | |
369 /* Blend the RGB values of two pixels based on a source alpha value */ | |
370 #define ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \ | |
371 do { \ | |
372 dR = (((sR-dR)*(A))>>8)+dR; \ | |
373 dG = (((sG-dG)*(A))>>8)+dG; \ | |
374 dB = (((sB-dB)*(A))>>8)+dB; \ | |
375 } while(0) | |
376 | |
377 /* This is a very useful loop for optimizing blitters */ | |
378 #define USE_DUFFS_LOOP | |
379 #ifdef USE_DUFFS_LOOP | |
380 | |
381 /* 8-times unrolled loop */ | |
382 #define DUFFS_LOOP8(pixel_copy_increment, width) \ | |
383 { int n = (width+7)/8; \ | |
91
e85e03f195b4
From: "Markus F.X.J. Oberhumer"
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
384 switch (width & 7) { \ |
0 | 385 case 0: do { pixel_copy_increment; \ |
386 case 7: pixel_copy_increment; \ | |
387 case 6: pixel_copy_increment; \ | |
388 case 5: pixel_copy_increment; \ | |
389 case 4: pixel_copy_increment; \ | |
390 case 3: pixel_copy_increment; \ | |
391 case 2: pixel_copy_increment; \ | |
392 case 1: pixel_copy_increment; \ | |
393 } while ( --n > 0 ); \ | |
394 } \ | |
395 } | |
396 | |
397 /* 4-times unrolled loop */ | |
398 #define DUFFS_LOOP4(pixel_copy_increment, width) \ | |
399 { int n = (width+3)/4; \ | |
91
e85e03f195b4
From: "Markus F.X.J. Oberhumer"
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
400 switch (width & 3) { \ |
0 | 401 case 0: do { pixel_copy_increment; \ |
402 case 3: pixel_copy_increment; \ | |
403 case 2: pixel_copy_increment; \ | |
404 case 1: pixel_copy_increment; \ | |
405 } while ( --n > 0 ); \ | |
406 } \ | |
407 } | |
408 | |
409 /* Use the 8-times version of the loop by default */ | |
410 #define DUFFS_LOOP(pixel_copy_increment, width) \ | |
411 DUFFS_LOOP8(pixel_copy_increment, width) | |
412 | |
413 #else | |
414 | |
415 /* Don't use Duff's device to unroll loops */ | |
416 #define DUFFS_LOOP(pixel_copy_increment, width) \ | |
417 { int n; \ | |
418 for ( n=width; n > 0; --n ) { \ | |
419 pixel_copy_increment; \ | |
420 } \ | |
421 } | |
422 #define DUFFS_LOOP8(pixel_copy_increment, width) \ | |
423 DUFFS_LOOP(pixel_copy_increment, width) | |
424 #define DUFFS_LOOP4(pixel_copy_increment, width) \ | |
425 DUFFS_LOOP(pixel_copy_increment, width) | |
426 | |
427 #endif /* USE_DUFFS_LOOP */ | |
428 | |
429 /* Prevent Visual C++ 6.0 from printing out stupid warnings */ | |
430 #if defined(_MSC_VER) && (_MSC_VER >= 600) | |
431 #pragma warning(disable: 4550) | |
432 #endif | |
433 | |
434 #endif /* _SDL_blit_h */ |