change SDL 1.2 to SDL 2.0
[platform/upstream/SDL.git] / src / video / SDL_blit_1.c
1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22
23 #include "SDL_video.h"
24 #include "SDL_blit.h"
25 #include "SDL_sysvideo.h"
26 #include "SDL_endian.h"
27
28 /* Functions to blit from 8-bit surfaces to other surfaces */
29
30 static void
31 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->dst_w;
42     height = info->dst_h;
43     src = info->src;
44     srcskip = info->src_skip;
45     dst = info->dst;
46     dstskip = info->dst_skip;
47     map = info->table;
48
49     while (height--) {
50 #ifdef USE_DUFFS_LOOP
51         /* *INDENT-OFF* */
52                 DUFFS_LOOP(
53                         {
54                           *dst = map[*src];
55                         }
56                         dst++;
57                         src++;
58                 , width);
59         /* *INDENT-ON* */
60 #else
61         for (c = width; c; --c) {
62             *dst = map[*src];
63             dst++;
64             src++;
65         }
66 #endif
67         src += srcskip;
68         dst += dstskip;
69     }
70 }
71
72 /* This is now endian dependent */
73 #if ( SDL_BYTEORDER == SDL_LIL_ENDIAN )
74 #define HI      1
75 #define LO      0
76 #else /* ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) */
77 #define HI      0
78 #define LO      1
79 #endif
80 static void
81 Blit1to2(SDL_BlitInfo * info)
82 {
83 #ifndef USE_DUFFS_LOOP
84     int c;
85 #endif
86     int width, height;
87     Uint8 *src, *dst;
88     Uint16 *map;
89     int srcskip, dstskip;
90
91     /* Set up some basic variables */
92     width = info->dst_w;
93     height = info->dst_h;
94     src = info->src;
95     srcskip = info->src_skip;
96     dst = info->dst;
97     dstskip = info->dst_skip;
98     map = (Uint16 *) info->table;
99
100 #ifdef USE_DUFFS_LOOP
101     while (height--) {
102                 /* *INDENT-OFF* */
103                 DUFFS_LOOP(
104                 {
105                         *(Uint16 *)dst = map[*src++];
106                         dst += 2;
107                 },
108                 width);
109                 /* *INDENT-ON* */
110         src += srcskip;
111         dst += dstskip;
112     }
113 #else
114     /* Memory align at 4-byte boundary, if necessary */
115     if ((long) dst & 0x03) {
116         /* Don't do anything if width is 0 */
117         if (width == 0) {
118             return;
119         }
120         --width;
121
122         while (height--) {
123             /* Perform copy alignment */
124             *(Uint16 *) dst = map[*src++];
125             dst += 2;
126
127             /* Copy in 4 pixel chunks */
128             for (c = width / 4; c; --c) {
129                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
130                 src += 2;
131                 dst += 4;
132                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
133                 src += 2;
134                 dst += 4;
135             }
136             /* Get any leftovers */
137             switch (width & 3) {
138             case 3:
139                 *(Uint16 *) dst = map[*src++];
140                 dst += 2;
141             case 2:
142                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
143                 src += 2;
144                 dst += 4;
145                 break;
146             case 1:
147                 *(Uint16 *) dst = map[*src++];
148                 dst += 2;
149                 break;
150             }
151             src += srcskip;
152             dst += dstskip;
153         }
154     } else {
155         while (height--) {
156             /* Copy in 4 pixel chunks */
157             for (c = width / 4; c; --c) {
158                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
159                 src += 2;
160                 dst += 4;
161                 *(Uint32 *) dst = (map[src[HI]] << 16) | (map[src[LO]]);
162                 src += 2;
163                 dst += 4;
164             }
165             /* Get any leftovers */
166             switch (width & 3) {
167             case 3:
168                 *(Uint16 *) dst = map[*src++];
169                 dst += 2;
170             case 2:
171                 *(Uint32 *) dst = (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
187 static void
188 Blit1to3(SDL_BlitInfo * info)
189 {
190 #ifndef USE_DUFFS_LOOP
191     int c;
192 #endif
193     int o;
194     int width, height;
195     Uint8 *src, *map, *dst;
196     int srcskip, dstskip;
197
198     /* Set up some basic variables */
199     width = info->dst_w;
200     height = info->dst_h;
201     src = info->src;
202     srcskip = info->src_skip;
203     dst = info->dst;
204     dstskip = info->dst_skip;
205     map = info->table;
206
207     while (height--) {
208 #ifdef USE_DUFFS_LOOP
209                 /* *INDENT-OFF* */
210                 DUFFS_LOOP(
211                         {
212                                 o = *src * 4;
213                                 dst[0] = map[o++];
214                                 dst[1] = map[o++];
215                                 dst[2] = map[o++];
216                         }
217                         src++;
218                         dst += 3;
219                 , width);
220                 /* *INDENT-ON* */
221 #else
222         for (c = width; c; --c) {
223             o = *src * 4;
224             dst[0] = map[o++];
225             dst[1] = map[o++];
226             dst[2] = map[o++];
227             src++;
228             dst += 3;
229         }
230 #endif /* USE_DUFFS_LOOP */
231         src += srcskip;
232         dst += dstskip;
233     }
234 }
235
236 static void
237 Blit1to4(SDL_BlitInfo * info)
238 {
239 #ifndef USE_DUFFS_LOOP
240     int c;
241 #endif
242     int width, height;
243     Uint8 *src;
244     Uint32 *map, *dst;
245     int srcskip, dstskip;
246
247     /* Set up some basic variables */
248     width = info->dst_w;
249     height = info->dst_h;
250     src = info->src;
251     srcskip = info->src_skip;
252     dst = (Uint32 *) info->dst;
253     dstskip = info->dst_skip / 4;
254     map = (Uint32 *) info->table;
255
256     while (height--) {
257 #ifdef USE_DUFFS_LOOP
258                 /* *INDENT-OFF* */
259                 DUFFS_LOOP(
260                         *dst++ = map[*src++];
261                 , width);
262                 /* *INDENT-ON* */
263 #else
264         for (c = width / 4; c; --c) {
265             *dst++ = map[*src++];
266             *dst++ = map[*src++];
267             *dst++ = map[*src++];
268             *dst++ = map[*src++];
269         }
270         switch (width & 3) {
271         case 3:
272             *dst++ = map[*src++];
273         case 2:
274             *dst++ = map[*src++];
275         case 1:
276             *dst++ = map[*src++];
277         }
278 #endif /* USE_DUFFS_LOOP */
279         src += srcskip;
280         dst += dstskip;
281     }
282 }
283
284 static void
285 Blit1to1Key(SDL_BlitInfo * info)
286 {
287     int width = info->dst_w;
288     int height = info->dst_h;
289     Uint8 *src = info->src;
290     int srcskip = info->src_skip;
291     Uint8 *dst = info->dst;
292     int dstskip = info->dst_skip;
293     Uint8 *palmap = info->table;
294     Uint32 ckey = info->colorkey;
295
296     if (palmap) {
297         while (height--) {
298                         /* *INDENT-OFF* */
299                         DUFFS_LOOP(
300                         {
301                                 if ( *src != ckey ) {
302                                   *dst = palmap[*src];
303                                 }
304                                 dst++;
305                                 src++;
306                         },
307                         width);
308                         /* *INDENT-ON* */
309             src += srcskip;
310             dst += dstskip;
311         }
312     } else {
313         while (height--) {
314                         /* *INDENT-OFF* */
315                         DUFFS_LOOP(
316                         {
317                                 if ( *src != ckey ) {
318                                   *dst = *src;
319                                 }
320                                 dst++;
321                                 src++;
322                         },
323                         width);
324                         /* *INDENT-ON* */
325             src += srcskip;
326             dst += dstskip;
327         }
328     }
329 }
330
331 static void
332 Blit1to2Key(SDL_BlitInfo * info)
333 {
334     int width = info->dst_w;
335     int height = info->dst_h;
336     Uint8 *src = info->src;
337     int srcskip = info->src_skip;
338     Uint16 *dstp = (Uint16 *) info->dst;
339     int dstskip = info->dst_skip;
340     Uint16 *palmap = (Uint16 *) info->table;
341     Uint32 ckey = info->colorkey;
342
343     /* Set up some basic variables */
344     dstskip /= 2;
345
346     while (height--) {
347                 /* *INDENT-OFF* */
348                 DUFFS_LOOP(
349                 {
350                         if ( *src != ckey ) {
351                                 *dstp=palmap[*src];
352                         }
353                         src++;
354                         dstp++;
355                 },
356                 width);
357                 /* *INDENT-ON* */
358         src += srcskip;
359         dstp += dstskip;
360     }
361 }
362
363 static void
364 Blit1to3Key(SDL_BlitInfo * info)
365 {
366     int width = info->dst_w;
367     int height = info->dst_h;
368     Uint8 *src = info->src;
369     int srcskip = info->src_skip;
370     Uint8 *dst = info->dst;
371     int dstskip = info->dst_skip;
372     Uint8 *palmap = info->table;
373     Uint32 ckey = info->colorkey;
374     int o;
375
376     while (height--) {
377                 /* *INDENT-OFF* */
378                 DUFFS_LOOP(
379                 {
380                         if ( *src != ckey ) {
381                                 o = *src * 4;
382                                 dst[0] = palmap[o++];
383                                 dst[1] = palmap[o++];
384                                 dst[2] = palmap[o++];
385                         }
386                         src++;
387                         dst += 3;
388                 },
389                 width);
390                 /* *INDENT-ON* */
391         src += srcskip;
392         dst += dstskip;
393     }
394 }
395
396 static void
397 Blit1to4Key(SDL_BlitInfo * info)
398 {
399     int width = info->dst_w;
400     int height = info->dst_h;
401     Uint8 *src = info->src;
402     int srcskip = info->src_skip;
403     Uint32 *dstp = (Uint32 *) info->dst;
404     int dstskip = info->dst_skip;
405     Uint32 *palmap = (Uint32 *) info->table;
406     Uint32 ckey = info->colorkey;
407
408     /* Set up some basic variables */
409     dstskip /= 4;
410
411     while (height--) {
412                 /* *INDENT-OFF* */
413                 DUFFS_LOOP(
414                 {
415                         if ( *src != ckey ) {
416                                 *dstp = palmap[*src];
417                         }
418                         src++;
419                         dstp++;
420                 },
421                 width);
422                 /* *INDENT-ON* */
423         src += srcskip;
424         dstp += dstskip;
425     }
426 }
427
428 static void
429 Blit1toNAlpha(SDL_BlitInfo * info)
430 {
431     int width = info->dst_w;
432     int height = info->dst_h;
433     Uint8 *src = info->src;
434     int srcskip = info->src_skip;
435     Uint8 *dst = info->dst;
436     int dstskip = info->dst_skip;
437     SDL_PixelFormat *dstfmt = info->dst_fmt;
438     const SDL_Color *srcpal = info->src_fmt->palette->colors;
439     int dstbpp;
440     Uint32 pixel;
441     unsigned sR, sG, sB;
442     unsigned dR, dG, dB, dA;
443     const unsigned A = info->a;
444
445     /* Set up some basic variables */
446     dstbpp = dstfmt->BytesPerPixel;
447
448     while (height--) {
449         /* *INDENT-OFF* */
450         DUFFS_LOOP4(
451         {
452             sR = srcpal[*src].r;
453             sG = srcpal[*src].g;
454             sB = srcpal[*src].b;
455             DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
456             ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
457             ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
458             src++;
459             dst += dstbpp;
460         },
461         width);
462         /* *INDENT-ON* */
463         src += srcskip;
464         dst += dstskip;
465     }
466 }
467
468 static void
469 Blit1toNAlphaKey(SDL_BlitInfo * info)
470 {
471     int width = info->dst_w;
472     int height = info->dst_h;
473     Uint8 *src = info->src;
474     int srcskip = info->src_skip;
475     Uint8 *dst = info->dst;
476     int dstskip = info->dst_skip;
477     SDL_PixelFormat *dstfmt = info->dst_fmt;
478     const SDL_Color *srcpal = info->src_fmt->palette->colors;
479     Uint32 ckey = info->colorkey;
480     int dstbpp;
481     Uint32 pixel;
482     unsigned sR, sG, sB;
483     unsigned dR, dG, dB, dA;
484     const unsigned A = info->a;
485
486     /* Set up some basic variables */
487     dstbpp = dstfmt->BytesPerPixel;
488
489     while (height--) {
490                 /* *INDENT-OFF* */
491                 DUFFS_LOOP(
492                 {
493                         if ( *src != ckey ) {
494                                 sR = srcpal[*src].r;
495                                 sG = srcpal[*src].g;
496                                 sB = srcpal[*src].b;
497                                 DISEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
498                                 ALPHA_BLEND_RGBA(sR, sG, sB, A, dR, dG, dB, dA);
499                                 ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
500                         }
501                         src++;
502                         dst += dstbpp;
503                 },
504                 width);
505                 /* *INDENT-ON* */
506         src += srcskip;
507         dst += dstskip;
508     }
509 }
510
511 static const SDL_BlitFunc one_blit[] = {
512     (SDL_BlitFunc) NULL, Blit1to1, Blit1to2, Blit1to3, Blit1to4
513 };
514
515 static const SDL_BlitFunc one_blitkey[] = {
516     (SDL_BlitFunc) NULL, Blit1to1Key, Blit1to2Key, Blit1to3Key, Blit1to4Key
517 };
518
519 SDL_BlitFunc
520 SDL_CalculateBlit1(SDL_Surface * surface)
521 {
522     int which;
523     SDL_PixelFormat *dstfmt;
524
525     dstfmt = surface->map->dst->format;
526     if (dstfmt->BitsPerPixel < 8) {
527         which = 0;
528     } else {
529         which = dstfmt->BytesPerPixel;
530     }
531     switch (surface->map->info.flags & ~SDL_COPY_RLE_MASK) {
532     case 0:
533         return one_blit[which];
534
535     case SDL_COPY_COLORKEY:
536         return one_blitkey[which];
537
538     case SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
539         /* Supporting 8bpp->8bpp alpha is doable but requires lots of
540            tables which consume space and takes time to precompute,
541            so is better left to the user */
542         return which >= 2 ? Blit1toNAlpha : (SDL_BlitFunc) NULL;
543
544     case SDL_COPY_COLORKEY | SDL_COPY_MODULATE_ALPHA | SDL_COPY_BLEND:
545         return which >= 2 ? Blit1toNAlphaKey : (SDL_BlitFunc) NULL;
546     }
547     return (SDL_BlitFunc) NULL;
548 }
549
550 /* vi: set ts=4 sw=4 expandtab: */