Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 1 | /* |
| 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 | |
| 15 | SrcoverBuilder_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 Klein | 9656dce | 2019-06-04 11:33:25 -0500 | [diff] [blame] | 38 | 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 Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 43 | } 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 Klein | 1665aaa | 2019-06-04 10:41:49 -0500 | [diff] [blame] | 79 | 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 Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 83 | |
Mike Klein | 1665aaa | 2019-06-04 10:41:49 -0500 | [diff] [blame] | 84 | R = pack(R, G, 8); |
| 85 | B = pack(B, A, 8); |
| 86 | R = pack(R, B, 16); |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 87 | |
| 88 | store32(dst, R); |
| 89 | } break; |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | SrcoverBuilder_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 Klein | 9656dce | 2019-06-04 11:33:25 -0500 | [diff] [blame] | 99 | 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 Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 104 | }; |
| 105 | |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 106 | 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 Klein | 6b43c30 | 2019-06-05 14:20:41 -0500 | [diff] [blame] | 113 | 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 Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 117 | |
Mike Klein | 1665aaa | 2019-06-04 10:41:49 -0500 | [diff] [blame] | 118 | r = pack(r, g, 8); |
| 119 | b = pack(b, a, 8); |
| 120 | r = pack(r, b, 16); |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 121 | store32(dst, r); |
| 122 | } |
| 123 | |
| 124 | SrcoverBuilder_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 Klein | 9656dce | 2019-06-04 11:33:25 -0500 | [diff] [blame] | 130 | skvm::I32 rgba = load32(ptr); |
| 131 | *rb = extract(rgba, 0x00ff00ff); |
| 132 | *ga = extract(rgba, 0xff00ff00); |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 133 | }; |
| 134 | |
Mike Klein | d7d04dc | 2019-06-04 10:10:19 -0500 | [diff] [blame] | 135 | auto mul_unorm8_SWAR = [&](skvm::I32 x, skvm::I32 y) { |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 136 | // 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 Klein | 9656dce | 2019-06-04 11:33:25 -0500 | [diff] [blame] | 138 | return extract(add(mul(x, y), _255), |
| 139 | 0xff00ff00); |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 140 | }; |
| 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 Klein | d7d04dc | 2019-06-04 10:10:19 -0500 | [diff] [blame] | 150 | rb = add(rb, mul_unorm8_SWAR(drb, invA)); |
| 151 | ga = add(ga, mul_unorm8_SWAR(dga, invA)); |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 152 | |
Mike Klein | 1665aaa | 2019-06-04 10:41:49 -0500 | [diff] [blame] | 153 | store32(dst, pack(rb, ga, 8)); |
Mike Klein | 7b7077c | 2019-06-03 17:10:59 -0500 | [diff] [blame] | 154 | } |