1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2018 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_blit_slow.h"
26 
27 /* The ONE TRUE BLITTER
28  * This puppy has to handle all the unoptimized cases - yes, it's slow.
29  */
30 void
SDL_Blit_Slow(SDL_BlitInfo * info)31 SDL_Blit_Slow(SDL_BlitInfo * info)
32 {
33     const int flags = info->flags;
34     const Uint32 modulateR = info->r;
35     const Uint32 modulateG = info->g;
36     const Uint32 modulateB = info->b;
37     const Uint32 modulateA = info->a;
38     Uint32 srcpixel;
39     Uint32 srcR, srcG, srcB, srcA;
40     Uint32 dstpixel;
41     Uint32 dstR, dstG, dstB, dstA;
42     int srcy, srcx;
43     int posy, posx;
44     int incy, incx;
45     SDL_PixelFormat *src_fmt = info->src_fmt;
46     SDL_PixelFormat *dst_fmt = info->dst_fmt;
47     int srcbpp = src_fmt->BytesPerPixel;
48     int dstbpp = dst_fmt->BytesPerPixel;
49     Uint32 rgbmask = ~src_fmt->Amask;
50     Uint32 ckey = info->colorkey & rgbmask;
51 
52     srcy = 0;
53     posy = 0;
54     incy = (info->src_h << 16) / info->dst_h;
55     incx = (info->src_w << 16) / info->dst_w;
56 
57     while (info->dst_h--) {
58         Uint8 *src = 0;
59         Uint8 *dst = (Uint8 *) info->dst;
60         int n = info->dst_w;
61         srcx = -1;
62         posx = 0x10000L;
63         while (posy >= 0x10000L) {
64             ++srcy;
65             posy -= 0x10000L;
66         }
67         while (n--) {
68             if (posx >= 0x10000L) {
69                 while (posx >= 0x10000L) {
70                     ++srcx;
71                     posx -= 0x10000L;
72                 }
73                 src =
74                     (info->src + (srcy * info->src_pitch) + (srcx * srcbpp));
75             }
76             if (src_fmt->Amask) {
77                 DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
78                               srcB, srcA);
79             } else {
80                 DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG,
81                              srcB);
82                 srcA = 0xFF;
83             }
84             if (flags & SDL_COPY_COLORKEY) {
85                 /* srcpixel isn't set for 24 bpp */
86                 if (srcbpp == 3) {
87                     srcpixel = (srcR << src_fmt->Rshift) |
88                         (srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift);
89                 }
90                 if ((srcpixel & rgbmask) == ckey) {
91                     posx += incx;
92                     dst += dstbpp;
93                     continue;
94                 }
95             }
96             if (dst_fmt->Amask) {
97                 DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
98                               dstB, dstA);
99             } else {
100                 DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG,
101                              dstB);
102                 dstA = 0xFF;
103             }
104 
105             if (flags & SDL_COPY_MODULATE_COLOR) {
106                 srcR = (srcR * modulateR) / 255;
107                 srcG = (srcG * modulateG) / 255;
108                 srcB = (srcB * modulateB) / 255;
109             }
110             if (flags & SDL_COPY_MODULATE_ALPHA) {
111                 srcA = (srcA * modulateA) / 255;
112             }
113             if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) {
114                 /* This goes away if we ever use premultiplied alpha */
115                 if (srcA < 255) {
116                     srcR = (srcR * srcA) / 255;
117                     srcG = (srcG * srcA) / 255;
118                     srcB = (srcB * srcA) / 255;
119                 }
120             }
121             switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD)) {
122             case 0:
123                 dstR = srcR;
124                 dstG = srcG;
125                 dstB = srcB;
126                 dstA = srcA;
127                 break;
128             case SDL_COPY_BLEND:
129                 dstR = srcR + ((255 - srcA) * dstR) / 255;
130                 dstG = srcG + ((255 - srcA) * dstG) / 255;
131                 dstB = srcB + ((255 - srcA) * dstB) / 255;
132                 dstA = srcA + ((255 - srcA) * dstA) / 255;
133                 break;
134             case SDL_COPY_ADD:
135                 dstR = srcR + dstR;
136                 if (dstR > 255)
137                     dstR = 255;
138                 dstG = srcG + dstG;
139                 if (dstG > 255)
140                     dstG = 255;
141                 dstB = srcB + dstB;
142                 if (dstB > 255)
143                     dstB = 255;
144                 break;
145             case SDL_COPY_MOD:
146                 dstR = (srcR * dstR) / 255;
147                 dstG = (srcG * dstG) / 255;
148                 dstB = (srcB * dstB) / 255;
149                 break;
150             }
151             if (dst_fmt->Amask) {
152                 ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA);
153             } else {
154                 ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB);
155             }
156             posx += incx;
157             dst += dstbpp;
158         }
159         posy += incy;
160         info->dst += info->dst_pitch;
161     }
162 }
163 
164 /* vi: set ts=4 sw=4 expandtab: */
165