Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: src/core/SkBitmapFilter.h

Issue 1588113002: add explicit bench for raw bitmapscaler (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: mark as nonrendering Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « bench/BitmapScaleBench.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkBitmapFilter_DEFINED 8 #ifndef SkBitmapFilter_DEFINED
9 #define SkBitmapFilter_DEFINED 9 #define SkBitmapFilter_DEFINED
10 10
11 #include "SkFixed.h" 11 #include "SkFixed.h"
12 #include "SkMath.h" 12 #include "SkMath.h"
13 #include "SkScalar.h" 13 #include "SkScalar.h"
14 14
15 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER 15 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER
16 #include "SkNx.h" 16 #include "SkNx.h"
17 #endif 17 #endif
18 18
19 // size of the precomputed bitmap filter tables for high quality filtering. 19 // size of the precomputed bitmap filter tables for high quality filtering.
20 // Used to precompute the shape of the filter kernel. 20 // Used to precompute the shape of the filter kernel.
21 // Table size chosen from experiments to see where I could start to see a differ ence. 21 // Table size chosen from experiments to see where I could start to see a differ ence.
22 22
23 #define SKBITMAP_FILTER_TABLE_SIZE 128 23 #define SKBITMAP_FILTER_TABLE_SIZE 128
24 24
25 class SkBitmapFilter { 25 class SkBitmapFilter {
26 public: 26 public:
27 SkBitmapFilter(float width) 27 SkBitmapFilter(float width) : fWidth(width), fInvWidth(1.f/width) {
28 : fWidth(width), fInvWidth(1.f/width) { 28 fPrecomputed = false;
29 fPrecomputed = false; 29 fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1);
30 fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1); 30 }
31 } 31 virtual ~SkBitmapFilter() {}
32 32
33 SkFixed lookup(float x) const { 33 SkFixed lookup(float x) const {
34 if (!fPrecomputed) { 34 if (!fPrecomputed) {
35 precomputeTable(); 35 precomputeTable();
36 } 36 }
37 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); 37 int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
38 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); 38 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
39 return fFilterTable[filter_idx]; 39 return fFilterTable[filter_idx];
40 } 40 }
41 41
42 SkScalar lookupScalar(float x) const { 42 SkScalar lookupScalar(float x) const {
43 if (!fPrecomputed) { 43 if (!fPrecomputed) {
44 precomputeTable(); 44 precomputeTable();
45 } 45 }
46 int filter_idx = int(sk_float_abs(x * fLookupMultiplier)); 46 int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
47 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE); 47 SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
48 return fFilterTableScalar[filter_idx]; 48 return fFilterTableScalar[filter_idx];
49 } 49 }
50 50
51 float width() const { return fWidth; } 51 float width() const { return fWidth; }
52 float invWidth() const { return fInvWidth; } 52 float invWidth() const { return fInvWidth; }
53 virtual float evaluate(float x) const = 0; 53 virtual float evaluate(float x) const = 0;
54 54
55 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER 55 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER
56 virtual float evaluate_n(float val, float diff, int count, float* output) const { 56 virtual float evaluate_n(float val, float diff, int count, float* output) co nst {
57 float sum = 0; 57 float sum = 0;
58 for (int index = 0; index < count; index++) { 58 for (int index = 0; index < count; index++) {
59 float filterValue = evaluate(val); 59 float filterValue = evaluate(val);
60 *output++ = filterValue; 60 *output++ = filterValue;
61 sum += filterValue; 61 sum += filterValue;
62 val += diff; 62 val += diff;
63 } 63 }
64 return sum; 64 return sum;
65 } 65 }
66 #endif 66 #endif
67 67
68 virtual ~SkBitmapFilter() {} 68 static SkBitmapFilter* Allocate();
69 69
70 static SkBitmapFilter* Allocate(); 70 protected:
71 protected: 71 float fWidth;
72 float fWidth; 72 float fInvWidth;
73 float fInvWidth; 73 float fLookupMultiplier;
74 74
75 float fLookupMultiplier; 75 mutable bool fPrecomputed;
76 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE];
77 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE];
76 78
77 mutable bool fPrecomputed; 79 private:
78 mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE]; 80 void precomputeTable() const {
79 mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE]; 81 fPrecomputed = true;
80 private: 82 SkFixed *ftp = fFilterTable;
81 void precomputeTable() const { 83 SkScalar *ftpScalar = fFilterTableScalar;
82 fPrecomputed = true; 84 for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) {
83 SkFixed *ftp = fFilterTable; 85 float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABLE_ SIZE;
84 SkScalar *ftpScalar = fFilterTableScalar; 86 float filter_value = evaluate(fx);
85 for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) { 87 *ftpScalar++ = filter_value;
86 float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABL E_SIZE; 88 *ftp++ = SkFloatToFixed(filter_value);
87 float filter_value = evaluate(fx); 89 }
88 *ftpScalar++ = filter_value; 90 }
89 *ftp++ = SkFloatToFixed(filter_value);
90 }
91 }
92 }; 91 };
93 92
94 class SkMitchellFilter : public SkBitmapFilter { 93 class SkMitchellFilter final : public SkBitmapFilter {
95 public: 94 public:
96 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER 95 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER
97 SkMitchellFilter() 96 SkMitchellFilter() : INHERITED(2), B(1.f / 3), C(1.f / 3) {}
98 : INHERITED(2), B(1.f / 3), C(1.f / 3) {
99 }
100 #else 97 #else
101 SkMitchellFilter() 98 SkMitchellFilter()
102 : INHERITED(2) 99 : INHERITED(2)
103 , fB(1.f / 3.f) 100 , fB(1.f / 3.f)
104 , fC(1.f / 3.f) 101 , fC(1.f / 3.f)
105 , fA1(-fB - 6*fC) 102 , fA1(-fB - 6*fC)
106 , fB1(6*fB + 30*fC) 103 , fB1(6*fB + 30*fC)
107 , fC1(-12*fB - 48*fC) 104 , fC1(-12*fB - 48*fC)
108 , fD1(8*fB + 24*fC) 105 , fD1(8*fB + 24*fC)
109 , fA2(12 - 9*fB - 6*fC) 106 , fA2(12 - 9*fB - 6*fC)
110 , fB2(-18 + 12*fB + 6*fC) 107 , fB2(-18 + 12*fB + 6*fC)
111 , fD2(6 - 2*fB) { 108 , fD2(6 - 2*fB)
112 } 109 {}
113 #endif 110 #endif
114 111
115 float evaluate(float x) const override { 112 float evaluate(float x) const override {
116 x = fabsf(x); 113 x = fabsf(x);
117 if (x > 2.f) { 114 if (x > 2.f) {
118 return 0; 115 return 0;
119 } else if (x > 1.f) { 116 } else if (x > 1.f) {
120 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER 117 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER
121 return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x + 118 return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x +
122 (-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f); 119 (-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f);
123 #else 120 #else
124 return (((fA1 * x + fB1) * x + fC1) * x + fD1) * (1.f/6.f); 121 return (((fA1 * x + fB1) * x + fC1) * x + fD1) * (1.f/6.f);
125 #endif 122 #endif
126 } else { 123 } else {
127 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER 124 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER
128 return ((12 - 9*B - 6*C) * x*x*x + 125 return ((12 - 9*B - 6*C) * x*x*x +
129 (-18 + 12*B + 6*C) * x*x + 126 (-18 + 12*B + 6*C) * x*x +
130 (6 - 2*B)) * (1.f/6.f); 127 (6 - 2*B)) * (1.f/6.f);
131 #else 128 #else
132 return ((fA2 * x + fB2) * x*x + fD2) * (1.f/6.f); 129 return ((fA2 * x + fB2) * x*x + fD2) * (1.f/6.f);
133 #endif 130 #endif
134 } 131 }
135 } 132 }
136 133
137 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER 134 #ifndef SK_SUPPORT_LEGACY_BITMAP_FILTER
138 // TODO : native Sk4f abs 135 // TODO : native Sk4f abs
139 static Sk4f abs(const Sk4f& x) { 136 static Sk4f abs(const Sk4f& x) {
140 Sk4f neg = x < Sk4f(0); 137 Sk4f neg = x < Sk4f(0);
141 return neg.thenElse(Sk4f(0) - x, x); 138 return neg.thenElse(Sk4f(0) - x, x);
142 } 139 }
143 140
144 Sk4f evalcore_n(const Sk4f& val) const { 141 Sk4f evalcore_n(const Sk4f& val) const {
145 Sk4f x = abs(val); 142 Sk4f x = abs(val);
146 Sk4f over2 = x > Sk4f(2); 143 Sk4f over2 = x > Sk4f(2);
147 Sk4f over1 = x > Sk4f(1); 144 Sk4f over1 = x > Sk4f(1);
148 Sk4f poly1 = (((Sk4f(fA1) * x + Sk4f(fB1)) * x + Sk4f(fC1)) * x + Sk4f (fD1)) 145 Sk4f poly1 = (((Sk4f(fA1) * x + Sk4f(fB1)) * x + Sk4f(fC1)) * x + Sk4f(f D1))
149 * Sk4f(1.f/6.f); 146 * Sk4f(1.f/6.f);
150 Sk4f poly0 = ((Sk4f(fA2) * x + Sk4f(fB2)) * x*x + Sk4f(fD2)) * Sk4f(1. f/6.f); 147 Sk4f poly0 = ((Sk4f(fA2) * x + Sk4f(fB2)) * x*x + Sk4f(fD2)) * Sk4f(1.f/ 6.f);
151 return over2.thenElse(Sk4f(0), over1.thenElse(poly1, poly0)); 148 return over2.thenElse(Sk4f(0), over1.thenElse(poly1, poly0));
152 } 149 }
153 150
154 float evaluate_n(float val, float diff, int count, float* output) const ov erride { 151 float evaluate_n(float val, float diff, int count, float* output) const over ride {
155 Sk4f sum(0); 152 Sk4f sum(0);
156 while (count >= 4) { 153 while (count >= 4) {
157 float v0 = val; 154 float v0 = val;
158 float v1 = val += diff; 155 float v1 = val += diff;
159 float v2 = val += diff; 156 float v2 = val += diff;
160 float v3 = val += diff; 157 float v3 = val += diff;
161 val += diff; 158 val += diff;
162 Sk4f filterValue = evalcore_n(Sk4f(v0, v1, v2, v3)); 159 Sk4f filterValue = evalcore_n(Sk4f(v0, v1, v2, v3));
163 filterValue.store(output); 160 filterValue.store(output);
164 output += 4; 161 output += 4;
165 sum = sum + filterValue; 162 sum = sum + filterValue;
166 count -= 4; 163 count -= 4;
167 } 164 }
168 float sums[4]; 165 float sums[4];
169 sum.store(sums); 166 sum.store(sums);
170 float result = sums[0] + sums[1] + sums[2] + sums[3]; 167 float result = sums[0] + sums[1] + sums[2] + sums[3];
171 result += INHERITED::evaluate_n(val, diff, count, output); 168 result += INHERITED::evaluate_n(val, diff, count, output);
172 return result; 169 return result;
173 } 170 }
174 #endif 171 #endif
175 172
176 protected: 173 protected:
177 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER 174 #ifdef SK_SUPPORT_LEGACY_BITMAP_FILTER
178 float B, C; 175 float B, C;
179 #else 176 #else
180 float fB, fC; 177 float fB, fC;
181 float fA1, fB1, fC1, fD1; 178 float fA1, fB1, fC1, fD1;
182 float fA2, fB2, fD2; 179 float fA2, fB2, fD2;
183 #endif 180 #endif
184 private: 181 private:
185 typedef SkBitmapFilter INHERITED; 182 typedef SkBitmapFilter INHERITED;
186 }; 183 };
187 184
188 class SkGaussianFilter: public SkBitmapFilter { 185 class SkGaussianFilter final : public SkBitmapFilter {
189 public: 186 float fAlpha, fExpWidth;
190 SkGaussianFilter(float a, float width=2.0f)
191 : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width)) {
192 }
193 187
194 float evaluate(float x) const override { 188 public:
195 return SkTMax(0.f, float(expf(-alpha*x*x) - expWidth)); 189 SkGaussianFilter(float a, float width = 2)
196 } 190 : SkBitmapFilter(width)
197 protected: 191 , fAlpha(a)
198 float alpha, expWidth; 192 , fExpWidth(expf(-a * width * width))
193 {}
194
195 float evaluate(float x) const override {
196 return SkTMax(0.f, float(expf(-fAlpha*x*x) - fExpWidth));
197 }
199 }; 198 };
200 199
201 class SkTriangleFilter: public SkBitmapFilter { 200 class SkTriangleFilter final : public SkBitmapFilter {
202 public: 201 public:
203 SkTriangleFilter(float width=1) 202 SkTriangleFilter(float width = 1) : SkBitmapFilter(width) {}
204 : SkBitmapFilter(width) {
205 }
206 203
207 float evaluate(float x) const override { 204 float evaluate(float x) const override {
208 return SkTMax(0.f, fWidth - fabsf(x)); 205 return SkTMax(0.f, fWidth - fabsf(x));
209 } 206 }
210 protected:
211 }; 207 };
212 208
213 class SkBoxFilter: public SkBitmapFilter { 209 class SkBoxFilter final : public SkBitmapFilter {
214 public: 210 public:
215 SkBoxFilter(float width=0.5f) 211 SkBoxFilter(float width = 0.5f) : SkBitmapFilter(width) {}
216 : SkBitmapFilter(width) {
217 }
218 212
219 float evaluate(float x) const override { 213 float evaluate(float x) const override {
220 return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f; 214 return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f;
221 } 215 }
222 protected:
223 }; 216 };
224 217
225 class SkHammingFilter: public SkBitmapFilter { 218 class SkHammingFilter final : public SkBitmapFilter {
226 public: 219 public:
227 SkHammingFilter(float width=1.f) 220 SkHammingFilter(float width = 1) : SkBitmapFilter(width) {}
228 : SkBitmapFilter(width) { 221
229 }
230 float evaluate(float x) const override { 222 float evaluate(float x) const override {
231 if (x <= -fWidth || x >= fWidth) { 223 if (x <= -fWidth || x >= fWidth) {
232 return 0.0f; // Outside of the window. 224 return 0.0f; // Outside of the window.
233 } 225 }
234 if (x > -FLT_EPSILON && x < FLT_EPSILON) { 226 if (x > -FLT_EPSILON && x < FLT_EPSILON) {
235 return 1.0f; // Special case the sinc discontinuity at the origin. 227 return 1.0f; // Special case the sinc discontinuity at the origin.
236 } 228 }
237 const float xpi = x * static_cast<float>(SK_ScalarPI); 229 const float xpi = x * static_cast<float>(SK_ScalarPI);
238 230
239 return ((sk_float_sin(xpi) / xpi) * // sinc(x) 231 return ((sk_float_sin(xpi) / xpi) * // sinc(x)
240 (0.54f + 0.46f * sk_float_cos(xpi / fWidth))); // hamming(x) 232 (0.54f + 0.46f * sk_float_cos(xpi / fWidth))); // hamming(x)
241 } 233 }
242 }; 234 };
243 235
244 class SkLanczosFilter: public SkBitmapFilter { 236 class SkLanczosFilter final : public SkBitmapFilter {
245 public: 237 public:
246 SkLanczosFilter(float width=3.f) 238 SkLanczosFilter(float width = 3.f) : SkBitmapFilter(width) {}
247 : SkBitmapFilter(width) {
248 }
249 239
250 float evaluate(float x) const override { 240 float evaluate(float x) const override {
251 if (x <= -fWidth || x >= fWidth) { 241 if (x <= -fWidth || x >= fWidth) {
252 return 0.0f; // Outside of the window. 242 return 0.0f; // Outside of the window.
253 } 243 }
254 if (x > -FLT_EPSILON && x < FLT_EPSILON) { 244 if (x > -FLT_EPSILON && x < FLT_EPSILON) {
255 return 1.0f; // Special case the discontinuity at the origin. 245 return 1.0f; // Special case the discontinuity at the origin.
256 } 246 }
257 float xpi = x * static_cast<float>(SK_ScalarPI); 247 float xpi = x * static_cast<float>(SK_ScalarPI);
258 return (sk_float_sin(xpi) / xpi) * // sinc(x) 248 return (sk_float_sin(xpi) / xpi) * // sinc(x)
259 sk_float_sin(xpi / fWidth) / (xpi / fWidth); // sinc(x/fWidth ) 249 sk_float_sin(xpi / fWidth) / (xpi / fWidth); // sinc(x/fWidth)
260 } 250 }
261 }; 251 };
262 252
263 253
264 #endif 254 #endif
OLDNEW
« no previous file with comments | « bench/BitmapScaleBench.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698