OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 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 "Benchmark.h" |
| 9 #include "SkRasterPipeline.h" |
| 10 #include "SkSRGB.h" |
| 11 |
| 12 static const int N = 1023; |
| 13 |
| 14 static uint32_t dst[N], |
| 15 src[N]; |
| 16 static uint8_t mask[N]; |
| 17 |
| 18 // We'll build up a somewhat realistic useful pipeline: |
| 19 // - load srgb src |
| 20 // - scale src by 8-bit mask |
| 21 // - load srgb dst |
| 22 // - src = srcover(dst, src) |
| 23 // - store src back as srgb |
| 24 // Every stage except for srcover interacts with memory, and so will need _tail
variants. |
| 25 |
| 26 static void SK_VECTORCALL load_s_srgb(SkRasterPipeline::Stage* st, size_t x, |
| 27 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 28 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 29 auto ptr = st->ctx<const uint32_t*>() + x; |
| 30 |
| 31 r = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 0) & 0xff], |
| 32 sk_linear_from_srgb[(ptr[1] >> 0) & 0xff], |
| 33 sk_linear_from_srgb[(ptr[2] >> 0) & 0xff], |
| 34 sk_linear_from_srgb[(ptr[3] >> 0) & 0xff] }; |
| 35 |
| 36 g = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 8) & 0xff], |
| 37 sk_linear_from_srgb[(ptr[1] >> 8) & 0xff], |
| 38 sk_linear_from_srgb[(ptr[2] >> 8) & 0xff], |
| 39 sk_linear_from_srgb[(ptr[3] >> 8) & 0xff] }; |
| 40 |
| 41 b = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 16) & 0xff], |
| 42 sk_linear_from_srgb[(ptr[1] >> 16) & 0xff], |
| 43 sk_linear_from_srgb[(ptr[2] >> 16) & 0xff], |
| 44 sk_linear_from_srgb[(ptr[3] >> 16) & 0xff] }; |
| 45 |
| 46 a = SkNx_cast<float>((Sk4i::Load(ptr) >> 24) & 0xff) * (1/255.0f); |
| 47 |
| 48 st->next(x, r,g,b,a, dr,dg,db,da); |
| 49 } |
| 50 |
| 51 static void SK_VECTORCALL load_s_srgb_tail(SkRasterPipeline::Stage* st, size_t x
, |
| 52 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 53 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 54 auto ptr = st->ctx<const uint32_t*>() + x; |
| 55 |
| 56 r = Sk4f{ sk_linear_from_srgb[(*ptr >> 0) & 0xff], 0,0,0 }; |
| 57 g = Sk4f{ sk_linear_from_srgb[(*ptr >> 8) & 0xff], 0,0,0 }; |
| 58 b = Sk4f{ sk_linear_from_srgb[(*ptr >> 16) & 0xff], 0,0,0 }; |
| 59 a = Sk4f{ (*ptr >> 24) * (1/255.0f), 0,0,0 }; |
| 60 |
| 61 st->next(x, r,g,b,a, dr,dg,db,da); |
| 62 } |
| 63 |
| 64 static void SK_VECTORCALL load_d_srgb(SkRasterPipeline::Stage* st, size_t x, |
| 65 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 66 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 67 auto ptr = st->ctx<const uint32_t*>() + x; |
| 68 |
| 69 dr = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 0) & 0xff], |
| 70 sk_linear_from_srgb[(ptr[1] >> 0) & 0xff], |
| 71 sk_linear_from_srgb[(ptr[2] >> 0) & 0xff], |
| 72 sk_linear_from_srgb[(ptr[3] >> 0) & 0xff] }; |
| 73 |
| 74 dg = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 8) & 0xff], |
| 75 sk_linear_from_srgb[(ptr[1] >> 8) & 0xff], |
| 76 sk_linear_from_srgb[(ptr[2] >> 8) & 0xff], |
| 77 sk_linear_from_srgb[(ptr[3] >> 8) & 0xff] }; |
| 78 |
| 79 db = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 16) & 0xff], |
| 80 sk_linear_from_srgb[(ptr[1] >> 16) & 0xff], |
| 81 sk_linear_from_srgb[(ptr[2] >> 16) & 0xff], |
| 82 sk_linear_from_srgb[(ptr[3] >> 16) & 0xff] }; |
| 83 |
| 84 da = SkNx_cast<float>((Sk4i::Load(ptr) >> 24) & 0xff) * (1/255.0f); |
| 85 |
| 86 st->next(x, r,g,b,a, dr,dg,db,da); |
| 87 } |
| 88 |
| 89 static void SK_VECTORCALL load_d_srgb_tail(SkRasterPipeline::Stage* st, size_t x
, |
| 90 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 91 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 92 auto ptr = st->ctx<const uint32_t*>() + x; |
| 93 |
| 94 dr = Sk4f{ sk_linear_from_srgb[(*ptr >> 0) & 0xff], 0,0,0 }; |
| 95 dg = Sk4f{ sk_linear_from_srgb[(*ptr >> 8) & 0xff], 0,0,0 }; |
| 96 db = Sk4f{ sk_linear_from_srgb[(*ptr >> 16) & 0xff], 0,0,0 }; |
| 97 da = Sk4f{ (*ptr >> 24) * (1/255.0f), 0,0,0 }; |
| 98 |
| 99 st->next(x, r,g,b,a, dr,dg,db,da); |
| 100 } |
| 101 |
| 102 static void SK_VECTORCALL scale_u8(SkRasterPipeline::Stage* st, size_t x, |
| 103 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 104 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 105 auto ptr = st->ctx<const uint8_t*>() + x; |
| 106 |
| 107 auto c = SkNx_cast<float>(Sk4b::Load(ptr)) * (1/255.0f); |
| 108 r *= c; |
| 109 g *= c; |
| 110 b *= c; |
| 111 a *= c; |
| 112 |
| 113 st->next(x, r,g,b,a, dr,dg,db,da); |
| 114 } |
| 115 |
| 116 static void SK_VECTORCALL scale_u8_tail(SkRasterPipeline::Stage* st, size_t x, |
| 117 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 118 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 119 auto ptr = st->ctx<const uint8_t*>() + x; |
| 120 |
| 121 auto c = *ptr * (1/255.0f); |
| 122 r *= c; |
| 123 g *= c; |
| 124 b *= c; |
| 125 a *= c; |
| 126 |
| 127 st->next(x, r,g,b,a, dr,dg,db,da); |
| 128 } |
| 129 |
| 130 static void SK_VECTORCALL srcover(SkRasterPipeline::Stage* st, size_t x, |
| 131 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 132 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 133 auto A = 1.0f - a; |
| 134 r += dr * A; |
| 135 g += dg * A; |
| 136 b += db * A; |
| 137 a += da * A; |
| 138 |
| 139 st->next(x, r,g,b,a, dr,dg,db,da); |
| 140 } |
| 141 |
| 142 static Sk4f clamp(const Sk4f& x) { |
| 143 return Sk4f::Min(Sk4f::Max(x, 0.0f), 255.0f); |
| 144 } |
| 145 |
| 146 static void SK_VECTORCALL store_srgb(SkRasterPipeline::Stage* st, size_t x, |
| 147 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 148 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 149 auto ptr = st->ctx<uint32_t*>() + x; |
| 150 |
| 151 r = clamp(sk_linear_to_srgb(r)); |
| 152 g = clamp(sk_linear_to_srgb(g)); |
| 153 b = clamp(sk_linear_to_srgb(b)); |
| 154 a = clamp( 255.0f * a ); |
| 155 |
| 156 ( SkNx_cast<int>(r) |
| 157 | SkNx_cast<int>(g) << 8 |
| 158 | SkNx_cast<int>(b) << 16 |
| 159 | SkNx_cast<int>(a) << 24 ).store(ptr); |
| 160 } |
| 161 |
| 162 static void SK_VECTORCALL store_srgb_tail(SkRasterPipeline::Stage* st, size_t x, |
| 163 Sk4f r, Sk4f g, Sk4f b, Sk4f a, |
| 164 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { |
| 165 auto ptr = st->ctx<uint32_t*>() + x; |
| 166 |
| 167 auto rgba = sk_linear_to_srgb({r[0], g[0], b[0], 0}); |
| 168 rgba = {rgba[0], rgba[1], rgba[2], 255.0f*a[0]}; |
| 169 rgba = clamp(rgba); |
| 170 |
| 171 SkNx_cast<uint8_t>(rgba).store(ptr); |
| 172 } |
| 173 |
| 174 class SkRasterPipelineBench : public Benchmark { |
| 175 public: |
| 176 SkRasterPipelineBench() {} |
| 177 |
| 178 bool isSuitableFor(Backend backend) override { return backend == kNonRenderi
ng_Backend; } |
| 179 const char* onGetName() override { return "SkRasterPipelineBench"; } |
| 180 |
| 181 void onDraw(int loops, SkCanvas*) override { |
| 182 SkRasterPipeline p; |
| 183 p.append(load_s_srgb, load_s_srgb_tail, src); |
| 184 p.append( scale_u8, scale_u8_tail, mask); |
| 185 p.append(load_d_srgb, load_d_srgb_tail, dst); |
| 186 p.append(srcover); |
| 187 p.append( store_srgb, store_srgb_tail, dst); |
| 188 |
| 189 while (loops --> 0) { |
| 190 p.run(N); |
| 191 } |
| 192 } |
| 193 }; |
| 194 |
| 195 DEF_BENCH( return new SkRasterPipelineBench; ) |
OLD | NEW |