SDL-1.2.14
[sdl_omap.git] / src / video / SDL_blit_1.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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
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
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 }
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 }
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
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
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
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
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
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
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
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 }