blob: a5263d770f7b06dc3dca23ef7328245a8b17ea37 [file] [log] [blame]
mtklein281b33f2016-07-12 15:01:26 -07001/*
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
12static const int N = 1023;
13
14static uint32_t dst[N],
15 src[N];
16static 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
mtkleinfe2042e2016-07-29 14:27:41 -070026SK_RASTER_STAGE(load_s_srgb) {
27 auto ptr = (const uint32_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -070028
29 r = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 0) & 0xff],
30 sk_linear_from_srgb[(ptr[1] >> 0) & 0xff],
31 sk_linear_from_srgb[(ptr[2] >> 0) & 0xff],
32 sk_linear_from_srgb[(ptr[3] >> 0) & 0xff] };
33
34 g = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 8) & 0xff],
35 sk_linear_from_srgb[(ptr[1] >> 8) & 0xff],
36 sk_linear_from_srgb[(ptr[2] >> 8) & 0xff],
37 sk_linear_from_srgb[(ptr[3] >> 8) & 0xff] };
38
39 b = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 16) & 0xff],
40 sk_linear_from_srgb[(ptr[1] >> 16) & 0xff],
41 sk_linear_from_srgb[(ptr[2] >> 16) & 0xff],
42 sk_linear_from_srgb[(ptr[3] >> 16) & 0xff] };
43
44 a = SkNx_cast<float>((Sk4i::Load(ptr) >> 24) & 0xff) * (1/255.0f);
mtklein281b33f2016-07-12 15:01:26 -070045}
46
mtkleinfe2042e2016-07-29 14:27:41 -070047SK_RASTER_STAGE(load_s_srgb_tail) {
48 auto ptr = (const uint32_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -070049
50 r = Sk4f{ sk_linear_from_srgb[(*ptr >> 0) & 0xff], 0,0,0 };
51 g = Sk4f{ sk_linear_from_srgb[(*ptr >> 8) & 0xff], 0,0,0 };
52 b = Sk4f{ sk_linear_from_srgb[(*ptr >> 16) & 0xff], 0,0,0 };
53 a = Sk4f{ (*ptr >> 24) * (1/255.0f), 0,0,0 };
mtklein281b33f2016-07-12 15:01:26 -070054}
55
mtkleinfe2042e2016-07-29 14:27:41 -070056SK_RASTER_STAGE(load_d_srgb) {
57 auto ptr = (const uint32_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -070058
59 dr = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 0) & 0xff],
60 sk_linear_from_srgb[(ptr[1] >> 0) & 0xff],
61 sk_linear_from_srgb[(ptr[2] >> 0) & 0xff],
62 sk_linear_from_srgb[(ptr[3] >> 0) & 0xff] };
63
64 dg = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 8) & 0xff],
65 sk_linear_from_srgb[(ptr[1] >> 8) & 0xff],
66 sk_linear_from_srgb[(ptr[2] >> 8) & 0xff],
67 sk_linear_from_srgb[(ptr[3] >> 8) & 0xff] };
68
69 db = Sk4f{ sk_linear_from_srgb[(ptr[0] >> 16) & 0xff],
70 sk_linear_from_srgb[(ptr[1] >> 16) & 0xff],
71 sk_linear_from_srgb[(ptr[2] >> 16) & 0xff],
72 sk_linear_from_srgb[(ptr[3] >> 16) & 0xff] };
73
74 da = SkNx_cast<float>((Sk4i::Load(ptr) >> 24) & 0xff) * (1/255.0f);
mtklein281b33f2016-07-12 15:01:26 -070075}
76
mtkleinfe2042e2016-07-29 14:27:41 -070077SK_RASTER_STAGE(load_d_srgb_tail) {
78 auto ptr = (const uint32_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -070079
80 dr = Sk4f{ sk_linear_from_srgb[(*ptr >> 0) & 0xff], 0,0,0 };
81 dg = Sk4f{ sk_linear_from_srgb[(*ptr >> 8) & 0xff], 0,0,0 };
82 db = Sk4f{ sk_linear_from_srgb[(*ptr >> 16) & 0xff], 0,0,0 };
83 da = Sk4f{ (*ptr >> 24) * (1/255.0f), 0,0,0 };
mtklein281b33f2016-07-12 15:01:26 -070084}
85
mtkleinfe2042e2016-07-29 14:27:41 -070086SK_RASTER_STAGE(scale_u8) {
87 auto ptr = (const uint8_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -070088
89 auto c = SkNx_cast<float>(Sk4b::Load(ptr)) * (1/255.0f);
90 r *= c;
91 g *= c;
92 b *= c;
93 a *= c;
mtklein281b33f2016-07-12 15:01:26 -070094}
95
mtkleinfe2042e2016-07-29 14:27:41 -070096SK_RASTER_STAGE(scale_u8_tail) {
97 auto ptr = (const uint8_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -070098
99 auto c = *ptr * (1/255.0f);
100 r *= c;
101 g *= c;
102 b *= c;
103 a *= c;
mtklein281b33f2016-07-12 15:01:26 -0700104}
105
mtkleinfe2042e2016-07-29 14:27:41 -0700106SK_RASTER_STAGE(srcover) {
mtklein281b33f2016-07-12 15:01:26 -0700107 auto A = 1.0f - a;
108 r += dr * A;
109 g += dg * A;
110 b += db * A;
111 a += da * A;
mtklein281b33f2016-07-12 15:01:26 -0700112}
113
mtkleinfe2042e2016-07-29 14:27:41 -0700114SK_RASTER_STAGE(store_srgb) {
115 auto ptr = (uint32_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -0700116
mtklein566ea9b2016-07-20 12:10:11 -0700117 ( sk_linear_to_srgb(r)
118 | sk_linear_to_srgb(g) << 8
119 | sk_linear_to_srgb(b) << 16
120 | Sk4f_round(255.0f*a) << 24).store(ptr);
mtklein281b33f2016-07-12 15:01:26 -0700121}
122
mtkleinfe2042e2016-07-29 14:27:41 -0700123SK_RASTER_STAGE(store_srgb_tail) {
124 auto ptr = (uint32_t*)ctx + x;
mtklein281b33f2016-07-12 15:01:26 -0700125
mtklein566ea9b2016-07-20 12:10:11 -0700126 Sk4i rgba = sk_linear_to_srgb({r[0], g[0], b[0], 0});
127 rgba = {rgba[0], rgba[1], rgba[2], (int)(255.0f * a[0] + 0.5f)};
mtklein281b33f2016-07-12 15:01:26 -0700128
129 SkNx_cast<uint8_t>(rgba).store(ptr);
130}
131
132class SkRasterPipelineBench : public Benchmark {
133public:
mtkleinfe2042e2016-07-29 14:27:41 -0700134 SkRasterPipelineBench(bool fused) : fFused(fused) {}
mtklein281b33f2016-07-12 15:01:26 -0700135
136 bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
mtkleinfe2042e2016-07-29 14:27:41 -0700137 const char* onGetName() override { return fFused ? "SkRasterPipelineBench_fused"
138 : "SkRasterPipelineBench_pipeline"; }
mtklein281b33f2016-07-12 15:01:26 -0700139
140 void onDraw(int loops, SkCanvas*) override {
mtklein281b33f2016-07-12 15:01:26 -0700141 while (loops --> 0) {
mtkleinfe2042e2016-07-29 14:27:41 -0700142 fFused ? this->runFused() : this->runPipeline();
mtklein281b33f2016-07-12 15:01:26 -0700143 }
144 }
mtkleinfe2042e2016-07-29 14:27:41 -0700145
146 void runFused() {
147 Sk4f r,g,b,a, dr,dg,db,da;
148 size_t x = 0, n = N;
149 while (n >= 4) {
150 load_s_srgb(src , x, r,g,b,a, dr,dg,db,da);
151 scale_u8 (mask , x, r,g,b,a, dr,dg,da,da);
152 load_d_srgb(dst , x, r,g,b,a, dr,dg,da,da);
153 srcover (nullptr, x, r,g,b,a, dr,dg,da,da);
154 store_srgb (dst , x, r,g,b,a, dr,dg,da,da);
155
156 x += 4;
157 n -= 4;
158 }
159 while (n > 0) {
160 load_s_srgb_tail(src , x, r,g,b,a, dr,dg,db,da);
161 scale_u8_tail (mask , x, r,g,b,a, dr,dg,da,da);
162 load_d_srgb_tail(dst , x, r,g,b,a, dr,dg,da,da);
163 srcover (nullptr, x, r,g,b,a, dr,dg,da,da);
164 store_srgb_tail (dst , x, r,g,b,a, dr,dg,da,da);
165
166 x += 1;
167 n -= 1;
168 }
169 }
170
171 void runPipeline() {
172 SkRasterPipeline p;
173 p.append<load_s_srgb, load_s_srgb_tail>( src);
174 p.append< scale_u8, scale_u8_tail>(mask);
175 p.append<load_d_srgb, load_d_srgb_tail>( dst);
176 p.append<srcover>();
177 p.append< store_srgb, store_srgb_tail>( dst);
178
179 p.run(N);
180 }
181
182 bool fFused;
mtklein281b33f2016-07-12 15:01:26 -0700183};
184
mtkleinfe2042e2016-07-29 14:27:41 -0700185DEF_BENCH( return new SkRasterPipelineBench(true); )
186DEF_BENCH( return new SkRasterPipelineBench(false); )