22#ifndef GRAPHICS_BLIT_BLIT_ALPHA_H
23#define GRAPHICS_BLIT_BLIT_ALPHA_H
25#include "graphics/blit.h"
33template<
bool rgbmod,
bool alphamod>
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) {}
43 const byte ca, cr, cg, cb;
46template<
bool rgbmod,
bool alphamod>
51 inline void normal(
const byte *in,
byte *out)
const {
55 ina = in[BlendBlit::kAIndex] * this->ca >> 8;
57 ina = in[BlendBlit::kAIndex];
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);
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];
72 }
else if (ina != 0) {
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);
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);
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;
92 inline void fill(
byte *out)
const {
93 uint32 ina = this->ca;
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);
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);
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;
128template<
bool rgbmod,
bool alphamod>
133 inline void normal(
const byte *in,
byte *out)
const {
137 ina = in[BlendBlit::kAIndex] * this->ca >> 8;
139 ina = in[BlendBlit::kAIndex];
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;
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;
152 }
else if (ina != 0) {
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;
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;
165 inline void fill(
byte *out)
const {
166 uint32 ina = this->ca;
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;
174 }
else if (ina != 0) {
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;
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;
188template<
bool rgbmod,
bool alphamod>
193 inline void normal(
const byte *in,
byte *out)
const {
194 *(uint32 *)out = *(
const uint32 *)in | BlendBlit::kAModMask;
198template<
bool rgbmod,
bool alphamod>
203 inline void normal(
const byte *in,
byte *out)
const {
204 uint32 pix = *(
const uint32 *)in;
205 uint32 a = pix & BlendBlit::kAModMask;
208 *(uint32 *)out = pix | BlendBlit::kAModMask;
213template<
bool rgbmod,
bool alphamod>
218 inline void normal(
const byte *in,
byte *out)
const {
222 ina = in[BlendBlit::kAIndex] * this->ca >> 8;
224 ina = in[BlendBlit::kAIndex];
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);
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];
237 }
else if (ina != 0) {
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);
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);
250 inline void fill(
byte *out)
const {
251 uint32 ina = this->ca;
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;
259 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + 255;
260 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + 255;
261 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + 255;
263 }
else if (ina != 0) {
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);
269 out[BlendBlit::kBIndex] = out[BlendBlit::kBIndex] + ina;
270 out[BlendBlit::kGIndex] = out[BlendBlit::kGIndex] + ina;
271 out[BlendBlit::kRIndex] = out[BlendBlit::kRIndex] + ina;
277template<
bool rgbmod,
bool alphamod>
282 inline void normal(
const byte *in,
byte *out)
const {
283 uint32 ina = in[BlendBlit::kAIndex];
284 out[BlendBlit::kAIndex] = 255;
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);
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);
296 }
else if (ina != 0) {
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);
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);
309 inline void fill(
byte *out)
const {
310 out[BlendBlit::kAIndex] = 255;
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);
317 out[BlendBlit::kBIndex] = 0;
318 out[BlendBlit::kGIndex] = 0;
319 out[BlendBlit::kRIndex] = 0;
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);
336 if (blendMode == BLEND_ADDITIVE) {
339 T::template blitInnerLoop<T::template AdditiveBlend, false, true, true>(args);
341 T::template blitInnerLoop<T::template AdditiveBlend, false, true, false>(args);
345 T::template blitInnerLoop<T::template AdditiveBlend, false, false, true>(args);
347 T::template blitInnerLoop<T::template AdditiveBlend, false, false, false>(args);
350 }
else if (blendMode == BLEND_SUBTRACTIVE) {
352 T::template blitInnerLoop<T::template SubtractiveBlend, false, true, false>(args);
354 T::template blitInnerLoop<T::template SubtractiveBlend, false, false, false>(args);
356 }
else if (blendMode == BLEND_MULTIPLY) {
359 T::template blitInnerLoop<T::template MultiplyBlend, false, true, true>(args);
361 T::template blitInnerLoop<T::template MultiplyBlend, false, true, false>(args);
365 T::template blitInnerLoop<T::template MultiplyBlend, false, false, true>(args);
367 T::template blitInnerLoop<T::template MultiplyBlend, false, false, false>(args);
371 assert(blendMode == BLEND_NORMAL);
374 T::template blitInnerLoop<T::template AlphaBlend, false, true, true>(args);
376 T::template blitInnerLoop<T::template AlphaBlend, false, true, false>(args);
380 T::template blitInnerLoop<T::template AlphaBlend, false, false, true>(args);
382 T::template blitInnerLoop<T::template AlphaBlend, false, false, false>(args);
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);
393 if (blendMode == BLEND_ADDITIVE) {
396 T::template blitInnerLoop<T::template AdditiveBlend, true, true, true>(args);
398 T::template blitInnerLoop<T::template AdditiveBlend, true, true, false>(args);
402 T::template blitInnerLoop<T::template AdditiveBlend, true, false, true>(args);
404 T::template blitInnerLoop<T::template AdditiveBlend, true, false, false>(args);
407 }
else if (blendMode == BLEND_SUBTRACTIVE) {
409 T::template blitInnerLoop<T::template SubtractiveBlend, true, true, false>(args);
411 T::template blitInnerLoop<T::template SubtractiveBlend, true, false, false>(args);
413 }
else if (blendMode == BLEND_MULTIPLY) {
416 T::template blitInnerLoop<T::template MultiplyBlend, true, true, true>(args);
418 T::template blitInnerLoop<T::template MultiplyBlend, true, true, false>(args);
422 T::template blitInnerLoop<T::template MultiplyBlend, true, false, true>(args);
424 T::template blitInnerLoop<T::template MultiplyBlend, true, false, false>(args);
428 assert(blendMode == BLEND_NORMAL);
431 T::template blitInnerLoop<T::template AlphaBlend, true, true, true>(args);
433 T::template blitInnerLoop<T::template AlphaBlend, true, true, false>(args);
437 T::template blitInnerLoop<T::template AlphaBlend, true, false, true>(args);
439 T::template blitInnerLoop<T::template AlphaBlend, true, false, false>(args);
448void BlendBlit::fillT(Args &args,
const TSpriteBlendMode &blendMode) {
449 bool rgbmod = ((args.color & kRGBModMask) != kRGBModMask);
450 bool alphamod = ((args.color & kAModMask) != kAModMask);
452 if (blendMode == BLEND_ADDITIVE) {
455 T::template fillInnerLoop<T::template AdditiveBlend, true, true>(args);
457 T::template fillInnerLoop<T::template AdditiveBlend, true, false>(args);
461 T::template fillInnerLoop<T::template AdditiveBlend, false, true>(args);
463 T::template fillInnerLoop<T::template AdditiveBlend, false, false>(args);
466 }
else if (blendMode == BLEND_SUBTRACTIVE) {
468 T::template fillInnerLoop<T::template SubtractiveBlend, true, false>(args);
470 T::template fillInnerLoop<T::template SubtractiveBlend, false, false>(args);
472 }
else if (blendMode == BLEND_MULTIPLY) {
475 T::template fillInnerLoop<T::template MultiplyBlend, true, true>(args);
477 T::template fillInnerLoop<T::template MultiplyBlend, true, false>(args);
481 T::template fillInnerLoop<T::template MultiplyBlend, false, true>(args);
483 T::template fillInnerLoop<T::template MultiplyBlend, false, false>(args);
487 assert(blendMode == BLEND_NORMAL);
490 T::template fillInnerLoop<T::template AlphaBlend, true, true>(args);
492 T::template fillInnerLoop<T::template AlphaBlend, true, false>(args);
496 T::template fillInnerLoop<T::template AlphaBlend, false, true>(args);
498 T::template fillInnerLoop<T::template AlphaBlend, false, false>(args);
Definition: blit-alpha.h:29
Definition: formatinfo.h:28
Definition: blit-alpha.h:214
Definition: blit-alpha.h:47
Definition: blit-alpha.h:34
Definition: blit-alpha.h:199
Definition: blit-alpha.h:129
Definition: blit-alpha.h:189
Definition: blit-alpha.h:278