blob: 11e61c9943f564534e82ad05d0b558bbe84c3873 [file] [log] [blame]
Mike Klein7b7077c2019-06-03 17:10:59 -05001/*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "tools/SkVMBuilders.h"
9
10// Some parts of this builder code are written less fluently than possible,
11// to avoid any ambiguity of function argument evaluation order. This lets
12// our golden tests work portably. In general there's no reason to fear
13// nesting calls to Builder routines.
14
15SrcoverBuilder_F32::SrcoverBuilder_F32(Fmt srcFmt, Fmt dstFmt) {
16 skvm::Arg src = arg(0),
17 dst = arg(1);
18
19 auto byte_to_f32 = [&](skvm::I32 byte) {
20 skvm::F32 _1_255 = splat(1/255.0f);
21 return mul(_1_255, to_f32(byte));
22 };
23
24 auto load = [&](skvm::Arg ptr, Fmt fmt,
25 skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) {
26 switch (fmt) {
27 case Fmt::A8: {
28 *r = *g = *b = splat(0.0f);
29 *a = byte_to_f32(load8(ptr));
30 } break;
31
32 case Fmt::G8: {
33 *r = *g = *b = byte_to_f32(load8(ptr));
34 *a = splat(1.0f);
35 } break;
36
37 case Fmt::RGBA_8888: {
Mike Klein9656dce2019-06-04 11:33:25 -050038 skvm::I32 rgba = load32(ptr);
39 *r = byte_to_f32(extract(rgba, 0xff));
40 *g = byte_to_f32(extract(rgba, 0xff00));
41 *b = byte_to_f32(extract(rgba, 0xff0000));
42 *a = byte_to_f32(extract(rgba, 0xff000000));
Mike Klein7b7077c2019-06-03 17:10:59 -050043 } break;
44 }
45 };
46
47 skvm::F32 r,g,b,a;
48 load(src, srcFmt, &r,&g,&b,&a);
49
50 skvm::F32 dr,dg,db,da;
51 load(dst, dstFmt, &dr,&dg,&db,&da);
52
53 skvm::F32 invA = sub(splat(1.0f), a);
54 r = mad(dr, invA, r);
55 g = mad(dg, invA, g);
56 b = mad(db, invA, b);
57 a = mad(da, invA, a);
58
59 auto f32_to_byte = [&](skvm::F32 f32) {
60 skvm::F32 _255 = splat(255.0f),
61 _0_5 = splat(0.5f);
62 return to_i32(mad(f32, _255, _0_5));
63 };
64 switch (dstFmt) {
65 case Fmt::A8: {
66 store8(dst, f32_to_byte(a));
67 } break;
68
69 case Fmt::G8: {
70 skvm::F32 _2126 = splat(0.2126f),
71 _7152 = splat(0.7152f),
72 _0722 = splat(0.0722f);
73 store8(dst, f32_to_byte(mad(r, _2126,
74 mad(g, _7152,
75 mul(b, _0722)))));
76 } break;
77
78 case Fmt::RGBA_8888: {
Mike Klein1665aaa2019-06-04 10:41:49 -050079 skvm::I32 R = f32_to_byte(r),
80 G = f32_to_byte(g),
81 B = f32_to_byte(b),
82 A = f32_to_byte(a);
Mike Klein7b7077c2019-06-03 17:10:59 -050083
Mike Klein1665aaa2019-06-04 10:41:49 -050084 R = pack(R, G, 8);
85 B = pack(B, A, 8);
86 R = pack(R, B, 16);
Mike Klein7b7077c2019-06-03 17:10:59 -050087
88 store32(dst, R);
89 } break;
90 }
91}
92
93SrcoverBuilder_I32::SrcoverBuilder_I32() {
94 skvm::Arg src = arg(0),
95 dst = arg(1);
96
97 auto load = [&](skvm::Arg ptr,
98 skvm::I32* r, skvm::I32* g, skvm::I32* b, skvm::I32* a) {
Mike Klein9656dce2019-06-04 11:33:25 -050099 skvm::I32 rgba = load32(ptr);
100 *r = extract(rgba, 0xff);
101 *g = extract(rgba, 0xff00);
102 *b = extract(rgba, 0xff0000);
103 *a = extract(rgba, 0xff000000);
Mike Klein7b7077c2019-06-03 17:10:59 -0500104 };
105
Mike Klein7b7077c2019-06-03 17:10:59 -0500106 skvm::I32 r,g,b,a;
107 load(src, &r,&g,&b,&a);
108
109 skvm::I32 dr,dg,db,da;
110 load(dst, &dr,&dg,&db,&da);
111
112 skvm::I32 invA = sub(splat(0xff), a);
Mike Klein6b43c302019-06-05 14:20:41 -0500113 r = mad_unorm8(dr, invA, r);
114 g = mad_unorm8(dg, invA, g);
115 b = mad_unorm8(db, invA, b);
116 a = mad_unorm8(da, invA, a);
Mike Klein7b7077c2019-06-03 17:10:59 -0500117
Mike Klein1665aaa2019-06-04 10:41:49 -0500118 r = pack(r, g, 8);
119 b = pack(b, a, 8);
120 r = pack(r, b, 16);
Mike Klein7b7077c2019-06-03 17:10:59 -0500121 store32(dst, r);
122}
123
124SrcoverBuilder_I32_SWAR::SrcoverBuilder_I32_SWAR() {
125 skvm::Arg src = arg(0),
126 dst = arg(1);
127
128 auto load = [&](skvm::Arg ptr,
129 skvm::I32* rb, skvm::I32* ga) {
Mike Klein9656dce2019-06-04 11:33:25 -0500130 skvm::I32 rgba = load32(ptr);
131 *rb = extract(rgba, 0x00ff00ff);
132 *ga = extract(rgba, 0xff00ff00);
Mike Klein7b7077c2019-06-03 17:10:59 -0500133 };
134
Mike Kleind7d04dc2019-06-04 10:10:19 -0500135 auto mul_unorm8_SWAR = [&](skvm::I32 x, skvm::I32 y) {
Mike Klein7b7077c2019-06-03 17:10:59 -0500136 // As above, assuming x is two SWAR bytes in lanes 0 and 2, and y is a byte.
137 skvm::I32 _255 = splat(0x00ff00ff);
Mike Klein9656dce2019-06-04 11:33:25 -0500138 return extract(add(mul(x, y), _255),
139 0xff00ff00);
Mike Klein7b7077c2019-06-03 17:10:59 -0500140 };
141
142 skvm::I32 rb, ga;
143 load(src, &rb, &ga);
144
145 skvm::I32 drb, dga;
146 load(dst, &drb, &dga);
147
148 skvm::I32 _255 = splat(0xff),
149 invA = sub(_255, shr(ga, 16));
Mike Kleind7d04dc2019-06-04 10:10:19 -0500150 rb = add(rb, mul_unorm8_SWAR(drb, invA));
151 ga = add(ga, mul_unorm8_SWAR(dga, invA));
Mike Klein7b7077c2019-06-03 17:10:59 -0500152
Mike Klein1665aaa2019-06-04 10:41:49 -0500153 store32(dst, pack(rb, ga, 8));
Mike Klein7b7077c2019-06-03 17:10:59 -0500154}