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