1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2021 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 |
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 | Uint32 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 | incy = (info->src_h << 16) / info->dst_h; |
53 | incx = (info->src_w << 16) / info->dst_w; |
54 | posy = incy / 2; /* start at the middle of pixel */ |
55 | |
56 | while (info->dst_h--) { |
57 | Uint8 *src = 0; |
58 | Uint8 *dst = info->dst; |
59 | int n = info->dst_w; |
60 | posx = incx / 2; /* start at the middle of pixel */ |
61 | srcy = posy >> 16; |
62 | while (n--) { |
63 | srcx = posx >> 16; |
64 | src = (info->src + (srcy * info->src_pitch) + (srcx * srcbpp)); |
65 | if (src_fmt->Amask) { |
66 | DISEMBLE_RGBA(src, srcbpp, src_fmt, srcpixel, srcR, srcG, |
67 | srcB, srcA); |
68 | } else { |
69 | DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, |
70 | srcB); |
71 | srcA = 0xFF; |
72 | } |
73 | if (flags & SDL_COPY_COLORKEY) { |
74 | /* srcpixel isn't set for 24 bpp */ |
75 | if (srcbpp == 3) { |
76 | srcpixel = (srcR << src_fmt->Rshift) | |
77 | (srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift); |
78 | } |
79 | if ((srcpixel & rgbmask) == ckey) { |
80 | posx += incx; |
81 | dst += dstbpp; |
82 | continue; |
83 | } |
84 | } |
85 | if (dst_fmt->Amask) { |
86 | DISEMBLE_RGBA(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, |
87 | dstB, dstA); |
88 | } else { |
89 | DISEMBLE_RGB(dst, dstbpp, dst_fmt, dstpixel, dstR, dstG, |
90 | dstB); |
91 | dstA = 0xFF; |
92 | } |
93 | |
94 | if (flags & SDL_COPY_MODULATE_COLOR) { |
95 | srcR = (srcR * modulateR) / 255; |
96 | srcG = (srcG * modulateG) / 255; |
97 | srcB = (srcB * modulateB) / 255; |
98 | } |
99 | if (flags & SDL_COPY_MODULATE_ALPHA) { |
100 | srcA = (srcA * modulateA) / 255; |
101 | } |
102 | if (flags & (SDL_COPY_BLEND | SDL_COPY_ADD)) { |
103 | /* This goes away if we ever use premultiplied alpha */ |
104 | if (srcA < 255) { |
105 | srcR = (srcR * srcA) / 255; |
106 | srcG = (srcG * srcA) / 255; |
107 | srcB = (srcB * srcA) / 255; |
108 | } |
109 | } |
110 | switch (flags & (SDL_COPY_BLEND | SDL_COPY_ADD | SDL_COPY_MOD | SDL_COPY_MUL)) { |
111 | case 0: |
112 | dstR = srcR; |
113 | dstG = srcG; |
114 | dstB = srcB; |
115 | dstA = srcA; |
116 | break; |
117 | case SDL_COPY_BLEND: |
118 | dstR = srcR + ((255 - srcA) * dstR) / 255; |
119 | dstG = srcG + ((255 - srcA) * dstG) / 255; |
120 | dstB = srcB + ((255 - srcA) * dstB) / 255; |
121 | dstA = srcA + ((255 - srcA) * dstA) / 255; |
122 | break; |
123 | case SDL_COPY_ADD: |
124 | dstR = srcR + dstR; |
125 | if (dstR > 255) |
126 | dstR = 255; |
127 | dstG = srcG + dstG; |
128 | if (dstG > 255) |
129 | dstG = 255; |
130 | dstB = srcB + dstB; |
131 | if (dstB > 255) |
132 | dstB = 255; |
133 | break; |
134 | case SDL_COPY_MOD: |
135 | dstR = (srcR * dstR) / 255; |
136 | dstG = (srcG * dstG) / 255; |
137 | dstB = (srcB * dstB) / 255; |
138 | break; |
139 | case SDL_COPY_MUL: |
140 | dstR = ((srcR * dstR) + (dstR * (255 - srcA))) / 255; |
141 | if (dstR > 255) |
142 | dstR = 255; |
143 | dstG = ((srcG * dstG) + (dstG * (255 - srcA))) / 255; |
144 | if (dstG > 255) |
145 | dstG = 255; |
146 | dstB = ((srcB * dstB) + (dstB * (255 - srcA))) / 255; |
147 | if (dstB > 255) |
148 | dstB = 255; |
149 | dstA = ((srcA * dstA) + (dstA * (255 - srcA))) / 255; |
150 | if (dstA > 255) |
151 | dstA = 255; |
152 | break; |
153 | } |
154 | if (dst_fmt->Amask) { |
155 | ASSEMBLE_RGBA(dst, dstbpp, dst_fmt, dstR, dstG, dstB, dstA); |
156 | } else { |
157 | ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB); |
158 | } |
159 | posx += incx; |
160 | dst += dstbpp; |
161 | } |
162 | posy += incy; |
163 | info->dst += info->dst_pitch; |
164 | } |
165 | } |
166 | |
167 | /* vi: set ts=4 sw=4 expandtab: */ |
168 | |