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