ScummVM API documentation
blit-alpha.h
1/* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#ifndef GRAPHICS_BLIT_BLIT_ALPHA_H
23#define GRAPHICS_BLIT_BLIT_ALPHA_H
24
25#include "graphics/blit.h"
26
27namespace Graphics {
28
30 friend class BlendBlit;
31protected:
32
33template<bool rgbmod, bool alphamod>
34struct BaseBlend {
35public:
36 constexpr BaseBlend(const uint32 color) :
37 ca(alphamod ? ((color >> BlendBlit::kAModShift) & 0xFF) : 255),
38 cr(rgbmod ? ((color >> BlendBlit::kRModShift) & 0xFF) : 255),
39 cg(rgbmod ? ((color >> BlendBlit::kGModShift) & 0xFF) : 255),
40 cb(rgbmod ? ((color >> BlendBlit::kBModShift) & 0xFF) : 255) {}
41
42protected:
43 const byte ca, cr, cg, cb;
44};
45
46template<bool rgbmod, bool alphamod>
47struct AlphaBlend : public BaseBlend<rgbmod, alphamod> {
48public:
49 constexpr AlphaBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
50
51 inline void normal(const byte *in, byte *out) const {
52 uint32 ina;
53
54 if (alphamod) {
55 ina = in[BlendBlit::kAIndex] * this->ca >> 8;
56 } else {
57 ina = in[BlendBlit::kAIndex];
58 }
59
60 if (ina == 255) {
61 if (rgbmod) {
62 out[BlendBlit::kAIndex] = 255;
63 out[BlendBlit::kBIndex] = (in[BlendBlit::kBIndex] * this->cb >> 8);
64 out[BlendBlit::kGIndex] = (in[BlendBlit::kGIndex] * this->cg >> 8);
65 out[BlendBlit::kRIndex] = (in[BlendBlit::kRIndex] * this->cr >> 8);
66 } else {
67 out[BlendBlit::kAIndex] = 255;
68 out[BlendBlit::kBIndex] = in[BlendBlit::kBIndex];
69 out[BlendBlit::kGIndex] = in[BlendBlit::kGIndex];
70 out[BlendBlit::kRIndex] = in[BlendBlit::kRIndex];
71 }
72 } else if (ina != 0) {
73 if (rgbmod) {
74 const uint outb = (out[BlendBlit::kBIndex] * (255 - ina) >> 8);
75 const uint outg = (out[BlendBlit::kGIndex] * (255 - ina) >> 8);
76 const uint outr = (out[BlendBlit::kRIndex] * (255 - ina) >> 8);
77
78 out[BlendBlit::kAIndex] = 255;
79 out[BlendBlit::kBIndex] = outb + (in[BlendBlit::kBIndex] * ina * this->cb >> 16);
80 out[BlendBlit::kGIndex] = outg + (in[BlendBlit::kGIndex] * ina * this->cg >> 16);
81 out[BlendBlit::kRIndex] = outr + (in[BlendBlit::kRIndex] * ina * this->cr >> 16);
82 } else {
83 out[BlendBlit::kAIndex] = 255;
84 out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * (255 - ina) + in[BlendBlit::kBIndex] * ina) >> 8;
85 out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * (255 - ina) + in[BlendBlit::kGIndex] * ina) >> 8;
86 out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * (255 - ina) + in[BlendBlit::kRIndex] * ina) >> 8;
87 }
88 }
89
90 }
91
92 inline void fill(byte *out) const {
93 uint32 ina = this->ca;
94
95 /* if (ina == 255) {
96 if (rgbmod) {
97 out[BlendBlit::kAIndex] = 255;
98 out[BlendBlit::kBIndex] = this->cb;
99 out[BlendBlit::kGIndex] = this->cg;
100 out[BlendBlit::kRIndex] = this->cr;
101 } else {
102 out[BlendBlit::kAIndex] = 255;
103 out[BlendBlit::kBIndex] = 255;
104 out[BlendBlit::kGIndex] = 255;
105 out[BlendBlit::kRIndex] = 255;
106 }
107 } else if (ina != 0) */ {
108 if (rgbmod) {
109 const uint outb = (out[BlendBlit::kBIndex] * (255 - ina) >> 8);
110 const uint outg = (out[BlendBlit::kGIndex] * (255 - ina) >> 8);
111 const uint outr = (out[BlendBlit::kRIndex] * (255 - ina) >> 8);
112
113 out[BlendBlit::kAIndex] = 255;
114 out[BlendBlit::kBIndex] = outb + (255 * ina * this->cb >> 16);
115 out[BlendBlit::kGIndex] = outg + (255 * ina * this->cg >> 16);
116 out[BlendBlit::kRIndex] = outr + (255 * ina * this->cr >> 16);
117 } else {
118 out[BlendBlit::kAIndex] = 255;
119 out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * (255 - ina) + 255 * ina) >> 8;
120 out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * (255 - ina) + 255 * ina) >> 8;
121 out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * (255 - ina) + 255 * ina) >> 8;
122 }
123 }
124
125 }
126};
127
128template<bool rgbmod, bool alphamod>
129struct MultiplyBlend : public BaseBlend<rgbmod, alphamod> {
130public:
131 constexpr MultiplyBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
132
133 inline void normal(const byte *in, byte *out) const {
134 uint32 ina;
135
136 if (alphamod) {
137 ina = in[BlendBlit::kAIndex] * this->ca >> 8;
138 } else {
139 ina = in[BlendBlit::kAIndex];
140 }
141
142 if (ina == 255) {
143 if (rgbmod) {
144 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((in[BlendBlit::kBIndex] * this->cb) >> 8) >> 8;
145 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((in[BlendBlit::kGIndex] * this->cg) >> 8) >> 8;
146 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((in[BlendBlit::kRIndex] * this->cr) >> 8) >> 8;
147 } else {
148 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * in[BlendBlit::kBIndex] >> 8;
149 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * in[BlendBlit::kGIndex] >> 8;
150 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * in[BlendBlit::kRIndex] >> 8;
151 }
152 } else if (ina != 0) {
153 if (rgbmod) {
154 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((in[BlendBlit::kBIndex] * this->cb * ina) >> 16) >> 8;
155 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((in[BlendBlit::kGIndex] * this->cg * ina) >> 16) >> 8;
156 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((in[BlendBlit::kRIndex] * this->cr * ina) >> 16) >> 8;
157 } else {
158 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((in[BlendBlit::kBIndex] * ina) >> 8) >> 8;
159 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((in[BlendBlit::kGIndex] * ina) >> 8) >> 8;
160 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((in[BlendBlit::kRIndex] * ina) >> 8) >> 8;
161 }
162 }
163 }
164
165 inline void fill(byte *out) const {
166 uint32 ina = this->ca;
167
168 if (ina == 255) {
169 if (rgbmod) {
170 out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * this->cb) >> 8;
171 out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * this->cg) >> 8;
172 out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * this->cr) >> 8;
173 }
174 } else if (ina != 0) {
175 if (rgbmod) {
176 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] * ((this->cb * ina) >> 8) >> 8;
177 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] * ((this->cg * ina) >> 8) >> 8;
178 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] * ((this->cr * ina) >> 8) >> 8;
179 } else {
180 out[BlendBlit::kBIndex] = (out[BlendBlit::kBIndex] * ina) >> 8;
181 out[BlendBlit::kGIndex] = (out[BlendBlit::kGIndex] * ina) >> 8;
182 out[BlendBlit::kRIndex] = (out[BlendBlit::kRIndex] * ina) >> 8;
183 }
184 }
185 }
186};
187
188template<bool rgbmod, bool alphamod>
189struct OpaqueBlend : public BaseBlend<rgbmod, alphamod> {
190public:
191 constexpr OpaqueBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
192
193 inline void normal(const byte *in, byte *out) const {
194 *(uint32 *)out = *(const uint32 *)in | BlendBlit::kAModMask;
195 }
196};
197
198template<bool rgbmod, bool alphamod>
199struct BinaryBlend : public BaseBlend<rgbmod, alphamod> {
200public:
201 constexpr BinaryBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
202
203 inline void normal(const byte *in, byte *out) const {
204 uint32 pix = *(const uint32 *)in;
205 uint32 a = pix & BlendBlit::kAModMask;
206
207 if (a != 0) { // Full opacity (Any value not exactly 0 is Opaque here)
208 *(uint32 *)out = pix | BlendBlit::kAModMask;
209 }
210 }
211};
212
213template<bool rgbmod, bool alphamod>
214struct AdditiveBlend : public BaseBlend<rgbmod, alphamod> {
215public:
216 constexpr AdditiveBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
217
218 inline void normal(const byte *in, byte *out) const {
219 uint32 ina;
220
221 if (alphamod) {
222 ina = in[BlendBlit::kAIndex] * this->ca >> 8;
223 } else {
224 ina = in[BlendBlit::kAIndex];
225 }
226
227 if (ina == 255) {
228 if (rgbmod) {
229 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((in[BlendBlit::kBIndex] * this->cb) >> 8);
230 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((in[BlendBlit::kGIndex] * this->cg) >> 8);
231 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((in[BlendBlit::kRIndex] * this->cr) >> 8);
232 } else {
233 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + in[BlendBlit::kBIndex];
234 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + in[BlendBlit::kGIndex];
235 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + in[BlendBlit::kRIndex];
236 }
237 } else if (ina != 0) {
238 if (rgbmod) {
239 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((in[BlendBlit::kBIndex] * this->cb * ina) >> 16);
240 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((in[BlendBlit::kGIndex] * this->cg * ina) >> 16);
241 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((in[BlendBlit::kRIndex] * this->cr * ina) >> 16);
242 } else {
243 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((in[BlendBlit::kBIndex] * ina) >> 8);
244 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((in[BlendBlit::kGIndex] * ina) >> 8);
245 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((in[BlendBlit::kRIndex] * ina) >> 8);
246 }
247 }
248 }
249
250 inline void fill(byte *out) const {
251 uint32 ina = this->ca;
252
253 if (ina == 255) {
254 if (rgbmod) {
255 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + this->cb;
256 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + this->cg;
257 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + this->cr;
258 } else {
259 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + 255;
260 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + 255;
261 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + 255;
262 }
263 } else if (ina != 0) {
264 if (rgbmod) {
265 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ((this->cb * ina) >> 8);
266 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ((this->cg * ina) >> 8);
267 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ((this->cr * ina) >> 8);
268 } else {
269 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ina;
270 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ina;
271 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ina;
272 }
273 }
274 }
275};
276
277template<bool rgbmod, bool alphamod>
278struct SubtractiveBlend : public BaseBlend<rgbmod, alphamod> {
279public:
280 constexpr SubtractiveBlend(const uint32 color) : BaseBlend<rgbmod, alphamod>(color) {}
281
282 inline void normal(const byte *in, byte *out) const {
283 uint32 ina = in[BlendBlit::kAIndex];
284 out[BlendBlit::kAIndex] = 255;
285
286 if (ina == 255) {
287 if (rgbmod) {
288 out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * this->cb * (out[BlendBlit::kBIndex])) >> 16), 0);
289 out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * this->cg * (out[BlendBlit::kGIndex])) >> 16), 0);
290 out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * this->cr * (out[BlendBlit::kRIndex])) >> 16), 0);
291 } else {
292 out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * (out[BlendBlit::kBIndex])) >> 8), 0);
293 out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * (out[BlendBlit::kGIndex])) >> 8), 0);
294 out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * (out[BlendBlit::kRIndex])) >> 8), 0);
295 }
296 } else if (ina != 0) {
297 if (rgbmod) {
298 out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * this->cb * (out[BlendBlit::kBIndex]) * ina) >> 24), 0);
299 out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * this->cg * (out[BlendBlit::kGIndex]) * ina) >> 24), 0);
300 out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * this->cr * (out[BlendBlit::kRIndex]) * ina) >> 24), 0);
301 } else {
302 out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((in[BlendBlit::kBIndex] * (out[BlendBlit::kBIndex]) * ina) >> 16), 0);
303 out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((in[BlendBlit::kGIndex] * (out[BlendBlit::kGIndex]) * ina) >> 16), 0);
304 out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((in[BlendBlit::kRIndex] * (out[BlendBlit::kRIndex]) * ina) >> 16), 0);
305 }
306 }
307 }
308
309 inline void fill(byte *out) const {
310 out[BlendBlit::kAIndex] = 255;
311
312 if (rgbmod) {
313 out[BlendBlit::kBIndex] = MAX<int32>(out[BlendBlit::kBIndex] - ((this->cb * out[BlendBlit::kBIndex]) >> 8), 0);
314 out[BlendBlit::kGIndex] = MAX<int32>(out[BlendBlit::kGIndex] - ((this->cg * out[BlendBlit::kGIndex]) >> 8), 0);
315 out[BlendBlit::kRIndex] = MAX<int32>(out[BlendBlit::kRIndex] - ((this->cr * out[BlendBlit::kRIndex]) >> 8), 0);
316 } else {
317 out[BlendBlit::kBIndex] = 0;
318 out[BlendBlit::kGIndex] = 0;
319 out[BlendBlit::kRIndex] = 0;
320 }
321 }
322};
323
324}; // End of class BlendBlitImpl_Base
325
326template<class T>
327void BlendBlit::blitT(Args &args, const TSpriteBlendMode &blendMode, const AlphaType &alphaType) {
328 bool rgbmod = ((args.color & kRGBModMask) != kRGBModMask);
329 bool alphamod = ((args.color & kAModMask) != kAModMask);
330 if (args.scaleX == SCALE_THRESHOLD && args.scaleY == SCALE_THRESHOLD) {
331 if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_OPAQUE) {
332 T::template blitInnerLoop<T::template OpaqueBlend, false, false, false>(args);
333 } else if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_BINARY) {
334 T::template blitInnerLoop<T::template BinaryBlend, false, false, false>(args);
335 } else {
336 if (blendMode == BLEND_ADDITIVE) {
337 if (rgbmod) {
338 if (alphamod) {
339 T::template blitInnerLoop<T::template AdditiveBlend, false, true, true>(args);
340 } else {
341 T::template blitInnerLoop<T::template AdditiveBlend, false, true, false>(args);
342 }
343 } else {
344 if (alphamod) {
345 T::template blitInnerLoop<T::template AdditiveBlend, false, false, true>(args);
346 } else {
347 T::template blitInnerLoop<T::template AdditiveBlend, false, false, false>(args);
348 }
349 }
350 } else if (blendMode == BLEND_SUBTRACTIVE) {
351 if (rgbmod) {
352 T::template blitInnerLoop<T::template SubtractiveBlend, false, true, false>(args);
353 } else {
354 T::template blitInnerLoop<T::template SubtractiveBlend, false, false, false>(args);
355 }
356 } else if (blendMode == BLEND_MULTIPLY) {
357 if (rgbmod) {
358 if (alphamod) {
359 T::template blitInnerLoop<T::template MultiplyBlend, false, true, true>(args);
360 } else {
361 T::template blitInnerLoop<T::template MultiplyBlend, false, true, false>(args);
362 }
363 } else {
364 if (alphamod) {
365 T::template blitInnerLoop<T::template MultiplyBlend, false, false, true>(args);
366 } else {
367 T::template blitInnerLoop<T::template MultiplyBlend, false, false, false>(args);
368 }
369 }
370 } else {
371 assert(blendMode == BLEND_NORMAL);
372 if (rgbmod) {
373 if (alphamod) {
374 T::template blitInnerLoop<T::template AlphaBlend, false, true, true>(args);
375 } else {
376 T::template blitInnerLoop<T::template AlphaBlend, false, true, false>(args);
377 }
378 } else {
379 if (alphamod) {
380 T::template blitInnerLoop<T::template AlphaBlend, false, false, true>(args);
381 } else {
382 T::template blitInnerLoop<T::template AlphaBlend, false, false, false>(args);
383 }
384 }
385 }
386 }
387 } else {
388 if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_OPAQUE) {
389 T::template blitInnerLoop<T::template OpaqueBlend, true, false, false>(args);
390 } else if (args.color == 0xffffffff && blendMode == BLEND_NORMAL && alphaType == ALPHA_BINARY) {
391 T::template blitInnerLoop<T::template BinaryBlend, true, false, false>(args);
392 } else {
393 if (blendMode == BLEND_ADDITIVE) {
394 if (rgbmod) {
395 if (alphamod) {
396 T::template blitInnerLoop<T::template AdditiveBlend, true, true, true>(args);
397 } else {
398 T::template blitInnerLoop<T::template AdditiveBlend, true, true, false>(args);
399 }
400 } else {
401 if (alphamod) {
402 T::template blitInnerLoop<T::template AdditiveBlend, true, false, true>(args);
403 } else {
404 T::template blitInnerLoop<T::template AdditiveBlend, true, false, false>(args);
405 }
406 }
407 } else if (blendMode == BLEND_SUBTRACTIVE) {
408 if (rgbmod) {
409 T::template blitInnerLoop<T::template SubtractiveBlend, true, true, false>(args);
410 } else {
411 T::template blitInnerLoop<T::template SubtractiveBlend, true, false, false>(args);
412 }
413 } else if (blendMode == BLEND_MULTIPLY) {
414 if (rgbmod) {
415 if (alphamod) {
416 T::template blitInnerLoop<T::template MultiplyBlend, true, true, true>(args);
417 } else {
418 T::template blitInnerLoop<T::template MultiplyBlend, true, true, false>(args);
419 }
420 } else {
421 if (alphamod) {
422 T::template blitInnerLoop<T::template MultiplyBlend, true, false, true>(args);
423 } else {
424 T::template blitInnerLoop<T::template MultiplyBlend, true, false, false>(args);
425 }
426 }
427 } else {
428 assert(blendMode == BLEND_NORMAL);
429 if (rgbmod) {
430 if (alphamod) {
431 T::template blitInnerLoop<T::template AlphaBlend, true, true, true>(args);
432 } else {
433 T::template blitInnerLoop<T::template AlphaBlend, true, true, false>(args);
434 }
435 } else {
436 if (alphamod) {
437 T::template blitInnerLoop<T::template AlphaBlend, true, false, true>(args);
438 } else {
439 T::template blitInnerLoop<T::template AlphaBlend, true, false, false>(args);
440 }
441 }
442 }
443 }
444 }
445}
446
447template<class T>
448void BlendBlit::fillT(Args &args, const TSpriteBlendMode &blendMode) {
449 bool rgbmod = ((args.color & kRGBModMask) != kRGBModMask);
450 bool alphamod = ((args.color & kAModMask) != kAModMask);
451
452 if (blendMode == BLEND_ADDITIVE) {
453 if (rgbmod) {
454 if (alphamod) {
455 T::template fillInnerLoop<T::template AdditiveBlend, true, true>(args);
456 } else {
457 T::template fillInnerLoop<T::template AdditiveBlend, true, false>(args);
458 }
459 } else {
460 if (alphamod) {
461 T::template fillInnerLoop<T::template AdditiveBlend, false, true>(args);
462 } else {
463 T::template fillInnerLoop<T::template AdditiveBlend, false, false>(args);
464 }
465 }
466 } else if (blendMode == BLEND_SUBTRACTIVE) {
467 if (rgbmod) {
468 T::template fillInnerLoop<T::template SubtractiveBlend, true, false>(args);
469 } else {
470 T::template fillInnerLoop<T::template SubtractiveBlend, false, false>(args);
471 }
472 } else if (blendMode == BLEND_MULTIPLY) {
473 if (rgbmod) {
474 if (alphamod) {
475 T::template fillInnerLoop<T::template MultiplyBlend, true, true>(args);
476 } else {
477 T::template fillInnerLoop<T::template MultiplyBlend, true, false>(args);
478 }
479 } else {
480 if (alphamod) {
481 T::template fillInnerLoop<T::template MultiplyBlend, false, true>(args);
482 } else {
483 T::template fillInnerLoop<T::template MultiplyBlend, false, false>(args);
484 }
485 }
486 } else {
487 assert(blendMode == BLEND_NORMAL);
488 if (rgbmod) {
489 if (alphamod) {
490 T::template fillInnerLoop<T::template AlphaBlend, true, true>(args);
491 } else {
492 T::template fillInnerLoop<T::template AlphaBlend, true, false>(args);
493 }
494 } else {
495 if (alphamod) {
496 T::template fillInnerLoop<T::template AlphaBlend, false, true>(args);
497 } else {
498 T::template fillInnerLoop<T::template AlphaBlend, false, false>(args);
499 }
500 }
501 }
502}
503
504} // End of namespace Graphics
505
506#endif // GRAPHICS_BLIT_BLIT_ALPHA_H
Definition: blit.h:321
Definition: blit-alpha.h:29
Definition: formatinfo.h:28
Definition: blit-alpha.h:47
Definition: blit-alpha.h:34
Definition: blit-alpha.h:199
Definition: blit-alpha.h:189