* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "tools/SkVMBuilders.h"
SrcoverBuilder_F32::SrcoverBuilder_F32(Fmt srcFmt, Fmt dstFmt) {
auto byte_to_f32 = [&](skvm::I32 byte) {
skvm::F32 _1_255 = splat(1/255.0f);
return mul(_1_255, to_f32(byte));
};
auto load = [&](Fmt fmt, skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) {
skvm::Arg ptr;
switch (fmt) {
case Fmt::A8: {
ptr = varying<uint8_t>();
*r = *g = *b = splat(0.0f);
*a = byte_to_f32(load8(ptr));
} break;
case Fmt::G8: {
ptr = varying<uint8_t>();
*r = *g = *b = byte_to_f32(load8(ptr));
*a = splat(1.0f);
} break;
case Fmt::RGBA_8888: {
ptr = varying<int>();
skvm::I32 rgba = load32(ptr);
*r = byte_to_f32(extract(rgba, 0, splat(0xff)));
*g = byte_to_f32(extract(rgba, 8, splat(0xff)));
*b = byte_to_f32(extract(rgba, 16, splat(0xff)));
*a = byte_to_f32(extract(rgba, 24, splat(0xff)));
} break;
}
return ptr;
};
skvm::F32 r,g,b,a;
(void)load(srcFmt, &r,&g,&b,&a);
skvm::F32 dr,dg,db,da;
skvm::Arg dst = load(dstFmt, &dr,&dg,&db,&da);
skvm::F32 invA = sub(splat(1.0f), a);
r = mad(dr, invA, r);
g = mad(dg, invA, g);
b = mad(db, invA, b);
a = mad(da, invA, a);
auto f32_to_byte = [&](skvm::F32 f32) {
skvm::F32 _255 = splat(255.0f),
_0_5 = splat(0.5f);
return to_i32(mad(f32, _255, _0_5));
};
switch (dstFmt) {
case Fmt::A8: {
store8(dst, f32_to_byte(a));
} break;
case Fmt::G8: {
skvm::F32 _2126 = splat(0.2126f),
_7152 = splat(0.7152f),
_0722 = splat(0.0722f);
store8(dst, f32_to_byte(mad(r, _2126,
mad(g, _7152,
mul(b, _0722)))));
} break;
case Fmt::RGBA_8888: {
skvm::I32 R = f32_to_byte(r),
G = f32_to_byte(g),
B = f32_to_byte(b),
A = f32_to_byte(a);
R = pack(R, G, 8);
B = pack(B, A, 8);
R = pack(R, B, 16);
store32(dst, R);
} break;
}
}
SrcoverBuilder_I32_Naive::SrcoverBuilder_I32_Naive() {
skvm::Arg src = varying<int>(),
dst = varying<int>();
auto load = [&](skvm::Arg ptr,
skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) {
skvm::I32 rgba = load32(ptr);
*r = extract(rgba, 0, splat(0xff));
*g = extract(rgba, 8, splat(0xff));
*b = extract(rgba, 16, splat(0xff));
*a = extract(rgba, 24, splat(0xff));
};
skvm::I32 r,g,b,a;
load(src, &r,&g,&b,&a);
skvm::I32 dr,dg,db,da;
load(dst, &dr,&dg,&db,&da);
skvm::I32 invA = sub(splat(256), a);
r = add(r, shr(mul(dr, invA), 8));
g = add(g, shr(mul(dg, invA), 8));
b = add(b, shr(mul(db, invA), 8));
a = add(a, shr(mul(da, invA), 8));
r = pack(r, g, 8);
b = pack(b, a, 8);
r = pack(r, b, 16);
store32(dst, r);
}
SrcoverBuilder_I32::SrcoverBuilder_I32() {
skvm::Arg src = varying<int>(),
dst = varying<int>();
auto load = [&](skvm::Arg ptr,
skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) {
skvm::I32 rgba = load32(ptr);
*r = bit_and(rgba, splat(0xff));
*g = bytes (rgba, 0x0002);
*b = bytes (rgba, 0x0003);
*a = shr (rgba, 24);
};
skvm::I32 r,g,b,a;
load(src, &r,&g,&b,&a);
skvm::I32 dr,dg,db,da;
load(dst, &dr,&dg,&db,&da);
skvm::I32 invA = sub(splat(256), a);
r = add(r, shr(mul_16x2(dr, invA), 8));
g = add(g, shr(mul_16x2(dg, invA), 8));
b = add(b, shr(mul_16x2(db, invA), 8));
a = add(a, shr(mul_16x2(da, invA), 8));
r = pack(r, g, 8);
b = pack(b, a, 8);
r = pack(r, b, 16);
store32(dst, r);
}
SrcoverBuilder_I32_SWAR::SrcoverBuilder_I32_SWAR() {
skvm::Arg src = varying<int>(),
dst = varying<int>();
skvm::I32 s = load32(src),
ax2 = bytes(s, 0x0404);
skvm::I32 invAx2 = sub_16x2(splat(0x01000100), ax2);
skvm::I32 d = load32(dst),
rb = bit_and (d, splat(0x00ff00ff)),
ga = shr_16x2(d, 8);
rb = shr_16x2(mul_16x2(rb, invAx2), 8);
ga = mul_16x2(ga, invAx2);
ga = bit_clear(ga, splat(0x00ff00ff));
store32(dst, add(s, bit_or(rb, ga)));
}