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 */
30void
31SDL_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