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

Side by Side Diff: src/core/SkLinearBitmapPipeline.cpp

Issue 1723683002: Better encapsulation and vector calling convention. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Make inlines VECTORCALL. Created 4 years, 10 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 | « src/core/SkLinearBitmapPipeline.h ('k') | tests/SkLinearBitmapPipelineTest.cpp » ('j') | 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 2016 Google Inc. 2 * Copyright 2016 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 #include "SkLinearBitmapPipeline.h" 8 #include "SkLinearBitmapPipeline.h"
9 #include "SkPM4f.h" 9 #include "SkPM4f.h"
10 10
11 #include <algorithm> 11 #include <algorithm>
12 #include <cmath> 12 #include <cmath>
13 #include <limits> 13 #include <limits>
14 #include "SkColor.h" 14 #include "SkColor.h"
15 #include "SkSize.h" 15 #include "SkSize.h"
16 16
17 // Tweak ABI of functions that pass Sk4f by value to pass them via registers.
18 #if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
19 #define VECTORCALL __vectorcall
20 #elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON)
21 #define VECTORCALL __attribute__((pcs("aapcs-vfp")))
22 #else
23 #define VECTORCALL
24 #endif
25
26 class SkLinearBitmapPipeline::PointProcessorInterface {
27 public:
28 virtual ~PointProcessorInterface() { }
29 virtual void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) = 0;
30 virtual void VECTORCALL pointList4(Sk4f xs, Sk4f ys) = 0;
31
32 // The pointSpan method efficiently process horizontal spans of pixels.
33 // * start - the point where to start the span.
34 // * length - the number of pixels to traverse in source space.
35 // * count - the number of pixels to produce in destination space.
36 // Both start and length are mapped through the inversion matrix to produce values in source
37 // space. After the matrix operation, the tilers may break the spans up into smaller spans.
38 // The tilers can produce spans that seem nonsensical.
39 // * The clamp tiler can create spans with length of 0. This indicates to co py an edge pixel out
40 // to the edge of the destination scan.
41 // * The mirror tiler can produce spans with negative length. This indicates that the source
42 // should be traversed in the opposite direction to the destination pixels .
43 virtual void pointSpan(SkPoint start, SkScalar length, int count) = 0;
44 };
45
46 class SkLinearBitmapPipeline::BilerpProcessorInterface
47 : public SkLinearBitmapPipeline::PointProcessorInterface {
48 public:
49 // The x's and y's are setup in the following order:
50 // +--------+--------+
51 // | | |
52 // | px00 | px10 |
53 // | 0 | 1 |
54 // +--------+--------+
55 // | | |
56 // | px01 | px11 |
57 // | 2 | 3 |
58 // +--------+--------+
59 // These pixels coordinates are arranged in the following order in xs and ys :
60 // px00 px10 px01 px11
61 virtual void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) = 0;
62 };
63
64 class SkLinearBitmapPipeline::PixelPlacerInterface {
65 public:
66 virtual ~PixelPlacerInterface() { }
67 virtual void setDestination(SkPM4f* dst) = 0;
68 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0;
69 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ;
70 };
71
72 namespace {
73
17 struct X { 74 struct X {
18 explicit X(SkScalar val) : fVal{val} { } 75 explicit X(SkScalar val) : fVal{val} { }
19 explicit X(SkPoint pt) : fVal{pt.fX} { } 76 explicit X(SkPoint pt) : fVal{pt.fX} { }
20 explicit X(SkSize s) : fVal{s.fWidth} { } 77 explicit X(SkSize s) : fVal{s.fWidth} { }
21 explicit X(SkISize s) : fVal(s.fWidth) { } 78 explicit X(SkISize s) : fVal(s.fWidth) { }
22 operator float () const {return fVal;} 79 operator float () const {return fVal;}
23 private: 80 private:
24 float fVal; 81 float fVal;
25 }; 82 };
26 83
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 // to work over. 118 // to work over.
62 // start - is the starting pixel. This is in destination space before the matr ix stage, and in 119 // start - is the starting pixel. This is in destination space before the matr ix stage, and in
63 // source space after the matrix stage. 120 // source space after the matrix stage.
64 // length - is this distance between the first pixel center and the last pixel center. Like start, 121 // length - is this distance between the first pixel center and the last pixel center. Like start,
65 // this is in destination space before the matrix stage, and in source space after. 122 // this is in destination space before the matrix stage, and in source space after.
66 // count - the number of pixels in source space to produce. 123 // count - the number of pixels in source space to produce.
67 // next - a pointer to the next stage. 124 // next - a pointer to the next stage.
68 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to 125 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to
69 // point lists for processing. 126 // point lists for processing.
70 template<typename Strategy, typename Next> 127 template<typename Strategy, typename Next>
71 class PointProcessor final : public PointProcessorInterface { 128 class PointProcessor final : public SkLinearBitmapPipeline::PointProcessorInterf ace {
72 public: 129 public:
73 template <typename... Args> 130 template <typename... Args>
74 PointProcessor(Next* next, Args&&... args) 131 PointProcessor(Next* next, Args&&... args)
75 : fNext{next} 132 : fNext{next}
76 , fStrategy{std::forward<Args>(args)...}{ } 133 , fStrategy{std::forward<Args>(args)...}{ }
77 134
78 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { 135 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override {
79 Sk4f newXs = xs; 136 Sk4f newXs = xs;
80 Sk4f newYs = ys; 137 Sk4f newYs = ys;
f(malita) 2016/02/22 22:48:08 Are the locals still needed?
mtklein 2016/02/22 23:00:55 Nope.
81 fStrategy.processPoints(&newXs, &newYs); 138 fStrategy.processPoints(&newXs, &newYs);
82 fNext->pointListFew(n, newXs, newYs); 139 fNext->pointListFew(n, newXs, newYs);
83 } 140 }
84 141
85 void pointList4(Sk4fArg xs, Sk4fArg ys) override { 142 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override {
86 Sk4f newXs = xs; 143 Sk4f newXs = xs;
87 Sk4f newYs = ys; 144 Sk4f newYs = ys;
88 fStrategy.processPoints(&newXs, &newYs); 145 fStrategy.processPoints(&newXs, &newYs);
89 fNext->pointList4(newXs, newYs); 146 fNext->pointList4(newXs, newYs);
90 } 147 }
91 148
92 void pointSpan(SkPoint start, SkScalar length, int count) override { 149 void pointSpan(SkPoint start, SkScalar length, int count) override {
93 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { 150 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) {
94 span_fallback(start, length, count, this); 151 span_fallback(start, length, count, this);
95 } 152 }
96 } 153 }
97 154
98 private: 155 private:
99 Next* const fNext; 156 Next* const fNext;
100 Strategy fStrategy; 157 Strategy fStrategy;
101 }; 158 };
102 159
103 // See PointProcessor for responsibilities of Strategy. 160 // See PointProcessor for responsibilities of Strategy.
104 template<typename Strategy, typename Next> 161 template<typename Strategy, typename Next>
105 class BilerpProcessor final : public BilerpProcessorInterface { 162 class BilerpProcessor final : public SkLinearBitmapPipeline::BilerpProcessorInte rface {
106 public: 163 public:
107 template <typename... Args> 164 template <typename... Args>
108 BilerpProcessor(Next* next, Args&&... args) 165 BilerpProcessor(Next* next, Args&&... args)
109 : fNext{next} 166 : fNext{next}
110 , fStrategy{std::forward<Args>(args)...}{ } 167 , fStrategy{std::forward<Args>(args)...}{ }
111 168
112 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { 169 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override {
113 Sk4f newXs = xs; 170 Sk4f newXs = xs;
114 Sk4f newYs = ys; 171 Sk4f newYs = ys;
115 fStrategy.processPoints(&newXs, &newYs); 172 fStrategy.processPoints(&newXs, &newYs);
116 fNext->pointListFew(n, newXs, newYs); 173 fNext->pointListFew(n, newXs, newYs);
117 } 174 }
118 175
119 void pointList4(Sk4fArg xs, Sk4fArg ys) override { 176 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override {
120 Sk4f newXs = xs; 177 Sk4f newXs = xs;
121 Sk4f newYs = ys; 178 Sk4f newYs = ys;
122 fStrategy.processPoints(&newXs, &newYs); 179 fStrategy.processPoints(&newXs, &newYs);
123 fNext->pointList4(newXs, newYs); 180 fNext->pointList4(newXs, newYs);
124 } 181 }
125 182
126 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { 183 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override {
127 Sk4f newXs = xs; 184 Sk4f newXs = xs;
128 Sk4f newYs = ys; 185 Sk4f newYs = ys;
129 fStrategy.processPoints(&newXs, &newYs); 186 fStrategy.processPoints(&newXs, &newYs);
130 fNext->bilerpList(newXs, newYs); 187 fNext->bilerpList(newXs, newYs);
131 } 188 }
132 189
133 void pointSpan(SkPoint start, SkScalar length, int count) override { 190 void pointSpan(SkPoint start, SkScalar length, int count) override {
134 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { 191 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) {
135 span_fallback(start, length, count, this); 192 span_fallback(start, length, count, this);
136 } 193 }
137 } 194 }
138 195
139 private: 196 private:
140 Next* const fNext; 197 Next* const fNext;
141 Strategy fStrategy; 198 Strategy fStrategy;
142 }; 199 };
143 200
144 class SkippedStage final : public BilerpProcessorInterface { 201 class SkippedStage final : public SkLinearBitmapPipeline::BilerpProcessorInterfa ce {
145 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { 202 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override {
146 SkFAIL("Skipped stage."); 203 SkFAIL("Skipped stage.");
147 } 204 }
148 void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { 205 void VECTORCALL pointList4(Sk4f Xs, Sk4f Ys) override {
149 SkFAIL("Skipped stage."); 206 SkFAIL("Skipped stage.");
150 } 207 }
151 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { 208 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override {
152 SkFAIL("Skipped stage."); 209 SkFAIL("Skipped stage.");
153 } 210 }
154 void pointSpan(SkPoint start, SkScalar length, int count) override { 211 void pointSpan(SkPoint start, SkScalar length, int count) override {
155 SkFAIL("Skipped stage."); 212 SkFAIL("Skipped stage.");
156 } 213 }
157 }; 214 };
158 215
159 class TranslateMatrixStrategy { 216 class TranslateMatrixStrategy {
160 public: 217 public:
161 TranslateMatrixStrategy(SkVector offset) 218 TranslateMatrixStrategy(SkVector offset)
162 : fXOffset{X(offset)} 219 : fXOffset{X(offset)}
163 , fYOffset{Y(offset)} { } 220 , fYOffset{Y(offset)} { }
164 221
165 void processPoints(Sk4f* xs, Sk4f* ys) { 222 void processPoints(Sk4f* xs, Sk4f* ys) {
166 *xs = *xs + fXOffset; 223 *xs = *xs + fXOffset;
167 *ys = *ys + fYOffset; 224 *ys = *ys + fYOffset;
168 } 225 }
169 226
170 template <typename Next> 227 template <typename Next>
171 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 228 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
172 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count ); 229 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count );
173 return true; 230 return true;
174 } 231 }
175 232
176 private: 233 private:
177 const Sk4f fXOffset, fYOffset; 234 const Sk4f fXOffset, fYOffset;
178 }; 235 };
179 template <typename Next = PointProcessorInterface> 236 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
180 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; 237 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>;
181 238
182 class ScaleMatrixStrategy { 239 class ScaleMatrixStrategy {
183 public: 240 public:
184 ScaleMatrixStrategy(SkVector offset, SkVector scale) 241 ScaleMatrixStrategy(SkVector offset, SkVector scale)
185 : fXOffset{X(offset)}, fYOffset{Y(offset)} 242 : fXOffset{X(offset)}, fYOffset{Y(offset)}
186 , fXScale{X(scale)}, fYScale{Y(scale)} { } 243 , fXScale{X(scale)}, fYScale{Y(scale)} { }
187 void processPoints(Sk4f* xs, Sk4f* ys) { 244 void processPoints(Sk4f* xs, Sk4f* ys) {
188 *xs = *xs * fXScale + fXOffset; 245 *xs = *xs * fXScale + fXOffset;
189 *ys = *ys * fYScale + fYOffset; 246 *ys = *ys * fYScale + fYOffset;
190 } 247 }
191 248
192 template <typename Next> 249 template <typename Next>
193 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 250 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
194 SkPoint newStart = 251 SkPoint newStart =
195 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]}; 252 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]};
196 SkScalar newLength = length * fXScale[0]; 253 SkScalar newLength = length * fXScale[0];
197 next->pointSpan(newStart, newLength, count); 254 next->pointSpan(newStart, newLength, count);
198 return true; 255 return true;
199 } 256 }
200 257
201 private: 258 private:
202 const Sk4f fXOffset, fYOffset; 259 const Sk4f fXOffset, fYOffset;
203 const Sk4f fXScale, fYScale; 260 const Sk4f fXScale, fYScale;
204 }; 261 };
205 template <typename Next = PointProcessorInterface> 262 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
206 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; 263 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>;
207 264
208 class AffineMatrixStrategy { 265 class AffineMatrixStrategy {
209 public: 266 public:
210 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew) 267 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew)
211 : fXOffset{X(offset)}, fYOffset{Y(offset)} 268 : fXOffset{X(offset)}, fYOffset{Y(offset)}
212 , fXScale{X(scale)}, fYScale{Y(scale)} 269 , fXScale{X(scale)}, fYScale{Y(scale)}
213 , fXSkew{X(skew)}, fYSkew{Y(skew)} { } 270 , fXSkew{X(skew)}, fYSkew{Y(skew)} { }
214 void processPoints(Sk4f* xs, Sk4f* ys) { 271 void processPoints(Sk4f* xs, Sk4f* ys) {
215 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset; 272 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset;
216 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset; 273 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset;
217 274
218 *xs = newXs; 275 *xs = newXs;
219 *ys = newYs; 276 *ys = newYs;
220 } 277 }
221 278
222 template <typename Next> 279 template <typename Next>
223 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 280 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
224 return false; 281 return false;
225 } 282 }
226 283
227 private: 284 private:
228 const Sk4f fXOffset, fYOffset; 285 const Sk4f fXOffset, fYOffset;
229 const Sk4f fXScale, fYScale; 286 const Sk4f fXScale, fYScale;
230 const Sk4f fXSkew, fYSkew; 287 const Sk4f fXSkew, fYSkew;
231 }; 288 };
232 template <typename Next = PointProcessorInterface> 289 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
233 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; 290 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>;
234 291
235 static PointProcessorInterface* choose_matrix( 292 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix(
236 PointProcessorInterface* next, 293 SkLinearBitmapPipeline::PointProcessorInterface* next,
237 const SkMatrix& inverse, 294 const SkMatrix& inverse,
238 SkLinearBitmapPipeline::MatrixStage* matrixProc) { 295 SkLinearBitmapPipeline::MatrixStage* matrixProc) {
239 if (inverse.hasPerspective()) { 296 if (inverse.hasPerspective()) {
240 SkFAIL("Not implemented."); 297 SkFAIL("Not implemented.");
241 } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) { 298 } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) {
242 matrixProc->Initialize<AffineMatrix<>>( 299 matrixProc->Initialize<AffineMatrix<>>(
243 next, 300 next,
244 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, 301 SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
245 SkVector{inverse.getScaleX(), inverse.getScaleY()}, 302 SkVector{inverse.getScaleX(), inverse.getScaleY()},
246 SkVector{inverse.getSkewX(), inverse.getSkewY()}); 303 SkVector{inverse.getSkewX(), inverse.getSkewY()});
247 } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) { 304 } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) {
248 matrixProc->Initialize<ScaleMatrix<>>( 305 matrixProc->Initialize<ScaleMatrix<>>(
249 next, 306 next,
250 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, 307 SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
251 SkVector{inverse.getScaleX(), inverse.getScaleY()}); 308 SkVector{inverse.getScaleX(), inverse.getScaleY()});
252 } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0 f) { 309 } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0 f) {
253 matrixProc->Initialize<TranslateMatrix<>>( 310 matrixProc->Initialize<TranslateMatrix<>>(
254 next, 311 next,
255 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); 312 SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
256 } else { 313 } else {
257 matrixProc->Initialize<SkippedStage>(); 314 matrixProc->Initialize<SkippedStage>();
258 return next; 315 return next;
259 } 316 }
260 return matrixProc->get(); 317 return matrixProc->get();
261 } 318 }
262 319
263 template <typename Next = BilerpProcessorInterface> 320 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
264 class ExpandBilerp final : public PointProcessorInterface { 321 class ExpandBilerp final : public SkLinearBitmapPipeline::PointProcessorInterfac e {
265 public: 322 public:
266 ExpandBilerp(Next* next) : fNext{next} { } 323 ExpandBilerp(Next* next) : fNext{next} { }
267 324
268 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { 325 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override {
269 SkASSERT(0 < n && n < 4); 326 SkASSERT(0 < n && n < 4);
270 // px00 px10 px01 px11 327 // px00 px10 px01 px11
271 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, 328 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f},
272 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; 329 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f};
273 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets); 330 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets);
274 if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYO ffsets); 331 if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYO ffsets);
275 if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYO ffsets); 332 if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYO ffsets);
276 } 333 }
277 334
278 void pointList4(Sk4fArg xs, Sk4fArg ys) override { 335 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override {
279 // px00 px10 px01 px11 336 // px00 px10 px01 px11
280 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, 337 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f},
281 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; 338 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f};
282 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); 339 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets);
283 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); 340 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets);
284 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); 341 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets);
285 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); 342 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets);
286 } 343 }
287 344
288 void pointSpan(SkPoint start, SkScalar length, int count) override { 345 void pointSpan(SkPoint start, SkScalar length, int count) override {
289 span_fallback(start, length, count, this); 346 span_fallback(start, length, count, this);
290 } 347 }
291 348
292 private: 349 private:
293 Next* const fNext; 350 Next* const fNext;
294 }; 351 };
295 352
296 static PointProcessorInterface* choose_filter( 353 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter(
297 BilerpProcessorInterface* next, 354 SkLinearBitmapPipeline::BilerpProcessorInterface* next,
298 SkFilterQuality filterQuailty, 355 SkFilterQuality filterQuailty,
299 SkLinearBitmapPipeline::FilterStage* filterProc) { 356 SkLinearBitmapPipeline::FilterStage* filterProc) {
300 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { 357 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) {
301 filterProc->Initialize<SkippedStage>(); 358 filterProc->Initialize<SkippedStage>();
302 return next; 359 return next;
303 } else { 360 } else {
304 filterProc->Initialize<ExpandBilerp<>>(next); 361 filterProc->Initialize<ExpandBilerp<>>(next);
305 return filterProc->get(); 362 return filterProc->get();
306 } 363 }
307 } 364 }
(...skipping 21 matching lines...) Expand all
329 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 386 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
330 return false; 387 return false;
331 } 388 }
332 389
333 private: 390 private:
334 const Sk4f fXMin{SK_FloatNegativeInfinity}; 391 const Sk4f fXMin{SK_FloatNegativeInfinity};
335 const Sk4f fYMin{SK_FloatNegativeInfinity}; 392 const Sk4f fYMin{SK_FloatNegativeInfinity};
336 const Sk4f fXMax{SK_FloatInfinity}; 393 const Sk4f fXMax{SK_FloatInfinity};
337 const Sk4f fYMax{SK_FloatInfinity}; 394 const Sk4f fYMax{SK_FloatInfinity};
338 }; 395 };
339 template <typename Next = BilerpProcessorInterface> 396 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
340 using Clamp = BilerpProcessor<ClampStrategy, Next>; 397 using Clamp = BilerpProcessor<ClampStrategy, Next>;
341 398
342 class RepeatStrategy { 399 class RepeatStrategy {
343 public: 400 public:
344 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } 401 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { }
345 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } 402 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { }
346 RepeatStrategy(SkSize max) 403 RepeatStrategy(SkSize max)
347 : fXMax{X(max)} 404 : fXMax{X(max)}
348 , fXInvMax{1.0f / X(max)} 405 , fXInvMax{1.0f / X(max)}
349 , fYMax{Y(max)} 406 , fYMax{Y(max)}
(...skipping 13 matching lines...) Expand all
363 return false; 420 return false;
364 } 421 }
365 422
366 private: 423 private:
367 const Sk4f fXMax{0.0f}; 424 const Sk4f fXMax{0.0f};
368 const Sk4f fXInvMax{0.0f}; 425 const Sk4f fXInvMax{0.0f};
369 const Sk4f fYMax{0.0f}; 426 const Sk4f fYMax{0.0f};
370 const Sk4f fYInvMax{0.0f}; 427 const Sk4f fYInvMax{0.0f};
371 }; 428 };
372 429
373 template <typename Next = BilerpProcessorInterface> 430 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
374 using Repeat = BilerpProcessor<RepeatStrategy, Next>; 431 using Repeat = BilerpProcessor<RepeatStrategy, Next>;
375 432
376 static BilerpProcessorInterface* choose_tiler( 433 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler(
377 BilerpProcessorInterface* next, 434 SkLinearBitmapPipeline::BilerpProcessorInterface* next,
378 SkSize dimensions, 435 SkSize dimensions,
379 SkShader::TileMode xMode, 436 SkShader::TileMode xMode,
380 SkShader::TileMode yMode, 437 SkShader::TileMode yMode,
381 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth, 438 SkLinearBitmapPipeline::TileStage* tileProcXOrBoth,
382 SkLinearBitmapPipeline::TileStage* tileProcY) { 439 SkLinearBitmapPipeline::TileStage* tileProcY) {
383 if (xMode == yMode) { 440 if (xMode == yMode) {
384 switch (xMode) { 441 switch (xMode) {
385 case SkShader::kClamp_TileMode: 442 case SkShader::kClamp_TileMode:
386 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions); 443 tileProcXOrBoth->Initialize<Clamp<>>(next, dimensions);
387 break; 444 break;
(...skipping 27 matching lines...) Expand all
415 case SkShader::kMirror_TileMode: 472 case SkShader::kMirror_TileMode:
416 SkFAIL("Not implemented."); 473 SkFAIL("Not implemented.");
417 break; 474 break;
418 } 475 }
419 } 476 }
420 return tileProcXOrBoth->get(); 477 return tileProcXOrBoth->get();
421 } 478 }
422 479
423 class sRGBFast { 480 class sRGBFast {
424 public: 481 public:
425 static Sk4f sRGBToLinear(Sk4fArg pixel) { 482 static Sk4f VECTORCALL sRGBToLinear(Sk4f pixel) {
426 Sk4f l = pixel * pixel; 483 Sk4f l = pixel * pixel;
427 return Sk4f{l[0], l[1], l[2], pixel[3]}; 484 return Sk4f{l[0], l[1], l[2], pixel[3]};
428 } 485 }
429 }; 486 };
430 487
431 template <SkColorProfileType colorProfile> 488 template <SkColorProfileType colorProfile>
432 class Passthrough8888 { 489 class Passthrough8888 {
433 public: 490 public:
434 Passthrough8888(int width, const uint32_t* src) 491 Passthrough8888(int width, const uint32_t* src)
435 : fSrc{src}, fWidth{width}{ } 492 : fSrc{src}, fWidth{width}{ }
436 493
437 void getFewPixels(int n, Sk4fArg xs, Sk4fArg ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { 494 void VECTORCALL getFewPixels(int n, Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) {
438 Sk4i XIs = SkNx_cast<int, float>(xs); 495 Sk4i XIs = SkNx_cast<int, float>(xs);
439 Sk4i YIs = SkNx_cast<int, float>(ys); 496 Sk4i YIs = SkNx_cast<int, float>(ys);
440 Sk4i bufferLoc = YIs * fWidth + XIs; 497 Sk4i bufferLoc = YIs * fWidth + XIs;
441 switch (n) { 498 switch (n) {
442 case 3: 499 case 3:
443 *px2 = getPixel(fSrc, bufferLoc[2]); 500 *px2 = getPixel(fSrc, bufferLoc[2]);
444 case 2: 501 case 2:
445 *px1 = getPixel(fSrc, bufferLoc[1]); 502 *px1 = getPixel(fSrc, bufferLoc[1]);
446 case 1: 503 case 1:
447 *px0 = getPixel(fSrc, bufferLoc[0]); 504 *px0 = getPixel(fSrc, bufferLoc[0]);
448 default: 505 default:
449 break; 506 break;
450 } 507 }
451 } 508 }
452 509
453 void get4Pixels(Sk4fArg xs, Sk4fArg ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4 f* px3) { 510 void VECTORCALL get4Pixels(Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) {
454 Sk4i XIs = SkNx_cast<int, float>(xs); 511 Sk4i XIs = SkNx_cast<int, float>(xs);
455 Sk4i YIs = SkNx_cast<int, float>(ys); 512 Sk4i YIs = SkNx_cast<int, float>(ys);
456 Sk4i bufferLoc = YIs * fWidth + XIs; 513 Sk4i bufferLoc = YIs * fWidth + XIs;
457 *px0 = getPixel(fSrc, bufferLoc[0]); 514 *px0 = getPixel(fSrc, bufferLoc[0]);
458 *px1 = getPixel(fSrc, bufferLoc[1]); 515 *px1 = getPixel(fSrc, bufferLoc[1]);
459 *px2 = getPixel(fSrc, bufferLoc[2]); 516 *px2 = getPixel(fSrc, bufferLoc[2]);
460 *px3 = getPixel(fSrc, bufferLoc[3]); 517 *px3 = getPixel(fSrc, bufferLoc[3]);
461 } 518 }
462 519
463 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; } 520 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; }
(...skipping 25 matching lines...) Expand all
489 // +--------+--------+ 546 // +--------+--------+
490 // 547 //
491 // 548 //
492 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x 549 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x
493 // and y: 550 // and y:
494 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy 551 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy
495 // * px10 -> x(1 - y) = x - xy 552 // * px10 -> x(1 - y) = x - xy
496 // * px01 -> (1 - x)y = y - xy 553 // * px01 -> (1 - x)y = y - xy
497 // * px11 -> xy 554 // * px11 -> xy
498 // So x * y is calculated first and then used to calculate all the other factors . 555 // So x * y is calculated first and then used to calculate all the other factors .
499 static Sk4f bilerp4(Sk4fArg xs, Sk4fArg ys, Sk4fArg px00, Sk4fArg px10, 556 static Sk4f VECTORCALL bilerp4(Sk4f xs, Sk4f ys, Sk4f px00, Sk4f px10,
500 Sk4fArg px01, Sk4fArg px11) { 557 Sk4f px01, Sk4f px11) {
501 // Calculate fractional xs and ys. 558 // Calculate fractional xs and ys.
502 Sk4f fxs = xs - xs.floor(); 559 Sk4f fxs = xs - xs.floor();
503 Sk4f fys = ys - ys.floor(); 560 Sk4f fys = ys - ys.floor();
504 Sk4f fxys{fxs * fys}; 561 Sk4f fxys{fxs * fys};
505 Sk4f sum = px11 * fxys; 562 Sk4f sum = px11 * fxys;
506 sum = sum + px01 * (fys - fxys); 563 sum = sum + px01 * (fys - fxys);
507 sum = sum + px10 * (fxs - fxys); 564 sum = sum + px10 * (fxs - fxys);
508 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); 565 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys);
509 return sum; 566 return sum;
510 } 567 }
511 568
512 template <typename SourceStrategy> 569 template <typename SourceStrategy>
513 class Sampler final : public BilerpProcessorInterface { 570 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface {
514 public: 571 public:
515 template <typename... Args> 572 template <typename... Args>
516 Sampler(PixelPlacerInterface* next, Args&&... args) 573 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args)
517 : fNext{next} 574 : fNext{next}
518 , fStrategy{std::forward<Args>(args)...} { } 575 , fStrategy{std::forward<Args>(args)...} { }
519 576
520 void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { 577 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override {
521 SkASSERT(0 < n && n < 4); 578 SkASSERT(0 < n && n < 4);
522 Sk4f px0, px1, px2; 579 Sk4f px0, px1, px2;
523 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); 580 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2);
524 if (n >= 1) fNext->placePixel(px0); 581 if (n >= 1) fNext->placePixel(px0);
525 if (n >= 2) fNext->placePixel(px1); 582 if (n >= 2) fNext->placePixel(px1);
526 if (n >= 3) fNext->placePixel(px2); 583 if (n >= 3) fNext->placePixel(px2);
527 } 584 }
528 585
529 void pointList4(Sk4fArg xs, Sk4fArg ys) override { 586 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override {
530 Sk4f px0, px1, px2, px3; 587 Sk4f px0, px1, px2, px3;
531 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); 588 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3);
532 fNext->place4Pixels(px0, px1, px2, px3); 589 fNext->place4Pixels(px0, px1, px2, px3);
533 } 590 }
534 591
535 void bilerpList(Sk4fArg xs, Sk4fArg ys) override { 592 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override {
536 Sk4f px00, px10, px01, px11; 593 Sk4f px00, px10, px01, px11;
537 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); 594 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11);
538 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); 595 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11);
539 fNext->placePixel(pixel); 596 fNext->placePixel(pixel);
540 } 597 }
541 598
542 void pointSpan(SkPoint start, SkScalar length, int count) override { 599 void pointSpan(SkPoint start, SkScalar length, int count) override {
543 span_fallback(start, length, count, this); 600 span_fallback(start, length, count, this);
544 } 601 }
545 602
546 private: 603 private:
547 PixelPlacerInterface* const fNext; 604 SkLinearBitmapPipeline::PixelPlacerInterface* const fNext;
548 SourceStrategy fStrategy; 605 SourceStrategy fStrategy;
549 }; 606 };
550 607
551 static BilerpProcessorInterface* choose_pixel_sampler( 608 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_pixel_sampler(
552 PixelPlacerInterface* next, 609 SkLinearBitmapPipeline::PixelPlacerInterface* next,
553 const SkPixmap& srcPixmap, 610 const SkPixmap& srcPixmap,
554 SkLinearBitmapPipeline::SampleStage* sampleStage) { 611 SkLinearBitmapPipeline::SampleStage* sampleStage) {
555 const SkImageInfo& imageInfo = srcPixmap.info(); 612 const SkImageInfo& imageInfo = srcPixmap.info();
556 switch (imageInfo.colorType()) { 613 switch (imageInfo.colorType()) {
557 case kRGBA_8888_SkColorType: 614 case kRGBA_8888_SkColorType:
558 case kBGRA_8888_SkColorType: 615 case kBGRA_8888_SkColorType:
559 if (kN32_SkColorType == imageInfo.colorType()) { 616 if (kN32_SkColorType == imageInfo.colorType()) {
560 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { 617 if (imageInfo.profileType() == kSRGB_SkColorProfileType) {
561 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>( 618 sampleStage->Initialize<Sampler<Passthrough8888<kSRGB_SkColo rProfileType>>>(
562 next, static_cast<int>(srcPixmap.rowBytes() / 4), 619 next, static_cast<int>(srcPixmap.rowBytes() / 4),
563 srcPixmap.addr32()); 620 srcPixmap.addr32());
564 } else { 621 } else {
565 sampleStage->Initialize<Sampler<Passthrough8888<kLinear_SkCo lorProfileType>>>( 622 sampleStage->Initialize<Sampler<Passthrough8888<kLinear_SkCo lorProfileType>>>(
566 next, static_cast<int>(srcPixmap.rowBytes() / 4), 623 next, static_cast<int>(srcPixmap.rowBytes() / 4),
567 srcPixmap.addr32()); 624 srcPixmap.addr32());
568 } 625 }
569 } else { 626 } else {
570 SkFAIL("Not implemented. No 8888 Swizzle"); 627 SkFAIL("Not implemented. No 8888 Swizzle");
571 } 628 }
572 break; 629 break;
573 default: 630 default:
574 SkFAIL("Not implemented. Unsupported src"); 631 SkFAIL("Not implemented. Unsupported src");
575 break; 632 break;
576 } 633 }
577 return sampleStage->get(); 634 return sampleStage->get();
578 } 635 }
579 636
580 template <SkAlphaType alphaType> 637 template <SkAlphaType alphaType>
581 class PlaceFPPixel final : public PixelPlacerInterface { 638 class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface {
582 public: 639 public:
583 void placePixel(Sk4fArg pixel) override { 640 void VECTORCALL placePixel(Sk4f pixel) override {
584 PlacePixel(fDst, pixel, 0); 641 PlacePixel(fDst, pixel, 0);
585 fDst += 1; 642 fDst += 1;
586 } 643 }
587 644
588 void place4Pixels(Sk4fArg p0, Sk4fArg p1, Sk4fArg p2, Sk4fArg p3) override { 645 void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
589 SkPM4f* dst = fDst; 646 SkPM4f* dst = fDst;
590 PlacePixel(dst, p0, 0); 647 PlacePixel(dst, p0, 0);
591 PlacePixel(dst, p1, 1); 648 PlacePixel(dst, p1, 1);
592 PlacePixel(dst, p2, 2); 649 PlacePixel(dst, p2, 2);
593 PlacePixel(dst, p3, 3); 650 PlacePixel(dst, p3, 3);
594 fDst += 4; 651 fDst += 4;
595 } 652 }
596 653
597 void setDestination(SkPM4f* dst) override { 654 void setDestination(SkPM4f* dst) override {
598 fDst = dst; 655 fDst = dst;
599 } 656 }
600 657
601 private: 658 private:
602 static void PlacePixel(SkPM4f* dst, Sk4fArg pixel, int index) { 659 static void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) {
603 Sk4f newPixel = pixel; 660 Sk4f newPixel = pixel;
604 if (alphaType == kUnpremul_SkAlphaType) { 661 if (alphaType == kUnpremul_SkAlphaType) {
605 newPixel = Premultiply(pixel); 662 newPixel = Premultiply(pixel);
606 } 663 }
607 newPixel.store(dst + index); 664 newPixel.store(dst + index);
608 } 665 }
609 static Sk4f Premultiply(Sk4fArg pixel) { 666 static Sk4f VECTORCALL Premultiply(Sk4f pixel) {
610 float alpha = pixel[3]; 667 float alpha = pixel[3];
611 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; 668 return pixel * Sk4f{alpha, alpha, alpha, 1.0f};
612 } 669 }
613 670
614 SkPM4f* fDst; 671 SkPM4f* fDst;
615 }; 672 };
616 673
617 static PixelPlacerInterface* choose_pixel_placer( 674 static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer(
618 SkAlphaType alphaType, 675 SkAlphaType alphaType,
619 SkLinearBitmapPipeline::PixelStage* placerStage) { 676 SkLinearBitmapPipeline::PixelStage* placerStage) {
620 if (alphaType == kUnpremul_SkAlphaType) { 677 if (alphaType == kUnpremul_SkAlphaType) {
621 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(); 678 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>();
622 } else { 679 } else {
623 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType 680 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
624 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(); 681 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>();
625 } 682 }
626 return placerStage->get(); 683 return placerStage->get();
627 } 684 }
685 } // namespace
686
687 SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {}
628 688
629 SkLinearBitmapPipeline::SkLinearBitmapPipeline( 689 SkLinearBitmapPipeline::SkLinearBitmapPipeline(
630 const SkMatrix& inverse, 690 const SkMatrix& inverse,
631 SkFilterQuality filterQuality, 691 SkFilterQuality filterQuality,
632 SkShader::TileMode xTile, SkShader::TileMode yTile, 692 SkShader::TileMode xTile, SkShader::TileMode yTile,
633 const SkPixmap& srcPixmap) { 693 const SkPixmap& srcPixmap) {
634 SkSize size = SkSize::Make(srcPixmap.width(), srcPixmap.height()); 694 SkSize size = SkSize::Make(srcPixmap.width(), srcPixmap.height());
635 const SkImageInfo& srcImageInfo = srcPixmap.info(); 695 const SkImageInfo& srcImageInfo = srcPixmap.info();
636 696
637 // As the stages are built, the chooser function may skip a stage. For examp le, with the 697 // As the stages are built, the chooser function may skip a stage. For examp le, with the
(...skipping 13 matching lines...) Expand all
651 if (count == 1) { 711 if (count == 1) {
652 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); 712 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f});
653 } else { 713 } else {
654 // The count and length arguments start out in a precise relation in ord er to keep the 714 // The count and length arguments start out in a precise relation in ord er to keep the
655 // math correct through the different stages. Count is the number of pix el to produce. 715 // math correct through the different stages. Count is the number of pix el to produce.
656 // Since the code samples at pixel centers, length is the distance from the center of the 716 // Since the code samples at pixel centers, length is the distance from the center of the
657 // first pixel to the center of the last pixel. This implies that length is count-1. 717 // first pixel to the center of the last pixel. This implies that length is count-1.
658 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); 718 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count);
659 } 719 }
660 } 720 }
OLDNEW
« no previous file with comments | « src/core/SkLinearBitmapPipeline.h ('k') | tests/SkLinearBitmapPipelineTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698