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

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

Issue 1719333002: tile spans (Closed) Base URL: https://skia.googlesource.com/skia.git@code-organization-speed
Patch Set: Handle -dx. Created 4 years, 9 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 | « gm/SkLinearBitmapPipelineGM.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 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. 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 18 #if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
19 #define VECTORCALL __vectorcall 19 #define VECTORCALL __vectorcall
20 #elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON) 20 #elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON)
21 #define VECTORCALL __attribute__((pcs("aapcs-vfp"))) 21 #define VECTORCALL __attribute__((pcs("aapcs-vfp")))
22 #else 22 #else
23 #define VECTORCALL 23 #define VECTORCALL
24 #endif 24 #endif
25 25
26 class SkLinearBitmapPipeline::PointProcessorInterface { 26 class SkLinearBitmapPipeline::PointProcessorInterface {
27 public: 27 public:
28 virtual ~PointProcessorInterface() { } 28 virtual ~PointProcessorInterface() { }
29 virtual void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) = 0; 29 virtual void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) = 0;
30 virtual void VECTORCALL pointList4(Sk4f xs, Sk4f ys) = 0; 30 virtual void VECTORCALL pointList4(Sk4s xs, Sk4s ys) = 0;
31 31
32 // The pointSpan method efficiently process horizontal spans of pixels. 32 // The pointSpan method efficiently process horizontal spans of pixels.
33 // * start - the point where to start the span. 33 // * start - the point where to start the span.
34 // * length - the number of pixels to traverse in source space. 34 // * length - the number of pixels to traverse in source space.
35 // * count - the number of pixels to produce in destination 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 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. 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. 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 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. 40 // to the edge of the destination scan.
(...skipping 10 matching lines...) Expand all
51 // | | | 51 // | | |
52 // | px00 | px10 | 52 // | px00 | px10 |
53 // | 0 | 1 | 53 // | 0 | 1 |
54 // +--------+--------+ 54 // +--------+--------+
55 // | | | 55 // | | |
56 // | px01 | px11 | 56 // | px01 | px11 |
57 // | 2 | 3 | 57 // | 2 | 3 |
58 // +--------+--------+ 58 // +--------+--------+
59 // These pixels coordinates are arranged in the following order in xs and ys : 59 // These pixels coordinates are arranged in the following order in xs and ys :
60 // px00 px10 px01 px11 60 // px00 px10 px01 px11
61 virtual void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) = 0; 61 virtual void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) = 0;
62 }; 62 };
63 63
64 class SkLinearBitmapPipeline::PixelPlacerInterface { 64 class SkLinearBitmapPipeline::PixelPlacerInterface {
65 public: 65 public:
66 virtual ~PixelPlacerInterface() { } 66 virtual ~PixelPlacerInterface() { }
67 virtual void setDestination(SkPM4f* dst) = 0; 67 virtual void setDestination(SkPM4f* dst) = 0;
68 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; 68 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0;
69 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ; 69 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0 ;
70 }; 70 };
71 71
72 namespace { 72 namespace {
73 73
74 struct X { 74 struct X {
75 explicit X(SkScalar val) : fVal{val} { } 75 explicit X(SkScalar val) : fVal{val} { }
76 explicit X(SkPoint pt) : fVal{pt.fX} { } 76 explicit X(SkPoint pt) : fVal{pt.fX} { }
77 explicit X(SkSize s) : fVal{s.fWidth} { } 77 explicit X(SkSize s) : fVal{s.fWidth} { }
78 explicit X(SkISize s) : fVal(s.fWidth) { } 78 explicit X(SkISize s) : fVal(s.fWidth) { }
79 operator float () const {return fVal;} 79 operator SkScalar () const {return fVal;}
80 private: 80 private:
81 float fVal; 81 SkScalar fVal;
82 }; 82 };
83 83
84 struct Y { 84 struct Y {
85 explicit Y(SkScalar val) : fVal{val} { } 85 explicit Y(SkScalar val) : fVal{val} { }
86 explicit Y(SkPoint pt) : fVal{pt.fY} { } 86 explicit Y(SkPoint pt) : fVal{pt.fY} { }
87 explicit Y(SkSize s) : fVal{s.fHeight} { } 87 explicit Y(SkSize s) : fVal{s.fHeight} { }
88 explicit Y(SkISize s) : fVal(s.fHeight) { } 88 explicit Y(SkISize s) : fVal(s.fHeight) { }
89 operator float () const {return fVal;} 89 operator SkScalar () const {return fVal;}
90 private: 90 private:
91 float fVal; 91 SkScalar fVal;
92 }; 92 };
93 93
94 template <typename Stage> 94 template <typename Stage>
95 void span_fallback(SkPoint start, SkScalar length, int count, Stage* stage) { 95 void span_fallback(SkPoint start, SkScalar length, int count, Stage* stage) {
96 // If count == 1 use PointListFew instead. 96 Sk4f xs{X(start)};
97 SkASSERT(count > 1); 97 Sk4f ys{Y(start)};
98 98 Sk4s fourDx;
99 float dx = length / (count - 1); 99 if (count > 1) {
100 Sk4f Xs = Sk4f(X(start)) + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * Sk4f{dx}; 100 SkScalar dx = length / (count - 1);
101 Sk4f Ys{Y(start)}; 101 xs = xs + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * dx;
102 Sk4f fourDx = {4.0f * dx}; 102 // Only used if count is >= 4.
103 fourDx = Sk4f{4.0f * dx};
104 }
103 105
104 while (count >= 4) { 106 while (count >= 4) {
105 stage->pointList4(Xs, Ys); 107 stage->pointList4(xs, ys);
106 Xs = Xs + fourDx; 108 xs = xs + fourDx;
107 count -= 4; 109 count -= 4;
108 } 110 }
109 if (count > 0) { 111 if (count > 0) {
110 stage->pointListFew(count, Xs, Ys); 112 stage->pointListFew(count, xs, ys);
111 } 113 }
112 } 114 }
113 115
114 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy 116 // PointProcessor uses a strategy to help complete the work of the different sta ges. The strategy
115 // must implement the following methods: 117 // must implement the following methods:
116 // * processPoints(xs, ys) - must mutate the xs and ys for the stage. 118 // * processPoints(xs, ys) - must mutate the xs and ys for the stage.
117 // * maybeProcessSpan(start, length, count) - This represents a horizontal serie s of pixels 119 // * maybeProcessSpan(start, length, count) - This represents a horizontal serie s of pixels
118 // to work over. 120 // to work over.
119 // start - is the starting pixel. This is in destination space before the matr ix stage, and in 121 // start - is the starting pixel. This is in destination space before the matr ix stage, and in
120 // source space after the matrix stage. 122 // source space after the matrix stage.
121 // length - is this distance between the first pixel center and the last pixel center. Like start, 123 // length - is this distance between the first pixel center and the last pixel center. Like start,
122 // this is in destination space before the matrix stage, and in source space after. 124 // this is in destination space before the matrix stage, and in source space after.
123 // count - the number of pixels in source space to produce. 125 // count - the number of pixels in source space to produce.
124 // next - a pointer to the next stage. 126 // next - a pointer to the next stage.
125 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to 127 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to
126 // point lists for processing. 128 // point lists for processing.
127 template<typename Strategy, typename Next> 129 template<typename Strategy, typename Next>
128 class PointProcessor final : public SkLinearBitmapPipeline::PointProcessorInterf ace { 130 class PointProcessor final : public SkLinearBitmapPipeline::PointProcessorInterf ace {
129 public: 131 public:
130 template <typename... Args> 132 template <typename... Args>
131 PointProcessor(Next* next, Args&&... args) 133 PointProcessor(Next* next, Args&&... args)
132 : fNext{next} 134 : fNext{next}
133 , fStrategy{std::forward<Args>(args)...}{ } 135 , fStrategy{std::forward<Args>(args)...}{ }
134 136
135 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 137 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
136 fStrategy.processPoints(&xs, &ys); 138 fStrategy.processPoints(&xs, &ys);
137 fNext->pointListFew(n, xs, ys); 139 fNext->pointListFew(n, xs, ys);
138 } 140 }
139 141
140 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 142 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
141 fStrategy.processPoints(&xs, &ys); 143 fStrategy.processPoints(&xs, &ys);
142 fNext->pointList4(xs, ys); 144 fNext->pointList4(xs, ys);
143 } 145 }
144 146
145 void pointSpan(SkPoint start, SkScalar length, int count) override { 147 void pointSpan(SkPoint start, SkScalar length, int count) override {
146 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { 148 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) {
147 span_fallback(start, length, count, this); 149 span_fallback(start, length, count, this);
148 } 150 }
149 } 151 }
150 152
151 private: 153 private:
152 Next* const fNext; 154 Next* const fNext;
153 Strategy fStrategy; 155 Strategy fStrategy;
154 }; 156 };
155 157
156 // See PointProcessor for responsibilities of Strategy. 158 // See PointProcessor for responsibilities of Strategy.
157 template<typename Strategy, typename Next> 159 template<typename Strategy, typename Next>
158 class BilerpProcessor final : public SkLinearBitmapPipeline::BilerpProcessorInte rface { 160 class BilerpProcessor final : public SkLinearBitmapPipeline::BilerpProcessorInte rface {
159 public: 161 public:
160 template <typename... Args> 162 template <typename... Args>
161 BilerpProcessor(Next* next, Args&&... args) 163 BilerpProcessor(Next* next, Args&&... args)
162 : fNext{next} 164 : fNext{next}
163 , fStrategy{std::forward<Args>(args)...}{ } 165 , fStrategy{std::forward<Args>(args)...}{ }
164 166
165 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 167 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
166 fStrategy.processPoints(&xs, &ys); 168 fStrategy.processPoints(&xs, &ys);
167 fNext->pointListFew(n, xs, ys); 169 fNext->pointListFew(n, xs, ys);
168 } 170 }
169 171
170 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 172 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
171 fStrategy.processPoints(&xs, &ys); 173 fStrategy.processPoints(&xs, &ys);
172 fNext->pointList4(xs, ys); 174 fNext->pointList4(xs, ys);
173 } 175 }
174 176
175 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { 177 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override {
176 fStrategy.processPoints(&xs, &ys); 178 fStrategy.processPoints(&xs, &ys);
177 fNext->bilerpList(xs, ys); 179 fNext->bilerpList(xs, ys);
178 } 180 }
179 181
180 void pointSpan(SkPoint start, SkScalar length, int count) override { 182 void pointSpan(SkPoint start, SkScalar length, int count) override {
181 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { 183 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) {
182 span_fallback(start, length, count, this); 184 span_fallback(start, length, count, this);
183 } 185 }
184 } 186 }
185 187
186 private: 188 private:
187 Next* const fNext; 189 Next* const fNext;
188 Strategy fStrategy; 190 Strategy fStrategy;
189 }; 191 };
190 192
191 class SkippedStage final : public SkLinearBitmapPipeline::BilerpProcessorInterfa ce { 193 class SkippedStage final : public SkLinearBitmapPipeline::BilerpProcessorInterfa ce {
192 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 194 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
193 SkFAIL("Skipped stage."); 195 SkFAIL("Skipped stage.");
194 } 196 }
195 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 197 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
196 SkFAIL("Skipped stage."); 198 SkFAIL("Skipped stage.");
197 } 199 }
198 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { 200 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override {
199 SkFAIL("Skipped stage."); 201 SkFAIL("Skipped stage.");
200 } 202 }
201 void pointSpan(SkPoint start, SkScalar length, int count) override { 203 void pointSpan(SkPoint start, SkScalar length, int count) override {
202 SkFAIL("Skipped stage."); 204 SkFAIL("Skipped stage.");
203 } 205 }
204 }; 206 };
205 207
206 class TranslateMatrixStrategy { 208 class TranslateMatrixStrategy {
207 public: 209 public:
208 TranslateMatrixStrategy(SkVector offset) 210 TranslateMatrixStrategy(SkVector offset)
209 : fXOffset{X(offset)} 211 : fXOffset{X(offset)}
210 , fYOffset{Y(offset)} { } 212 , fYOffset{Y(offset)} { }
211 213
212 void processPoints(Sk4f* xs, Sk4f* ys) { 214 void processPoints(Sk4s* xs, Sk4s* ys) {
213 *xs = *xs + fXOffset; 215 *xs = *xs + fXOffset;
214 *ys = *ys + fYOffset; 216 *ys = *ys + fYOffset;
215 } 217 }
216 218
217 template <typename Next> 219 template <typename Next>
218 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 220 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
219 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count ); 221 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count );
220 return true; 222 return true;
221 } 223 }
222 224
223 private: 225 private:
224 const Sk4f fXOffset, fYOffset; 226 const Sk4s fXOffset, fYOffset;
225 }; 227 };
226 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> 228 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
227 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; 229 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>;
228 230
229 class ScaleMatrixStrategy { 231 class ScaleMatrixStrategy {
230 public: 232 public:
231 ScaleMatrixStrategy(SkVector offset, SkVector scale) 233 ScaleMatrixStrategy(SkVector offset, SkVector scale)
232 : fXOffset{X(offset)}, fYOffset{Y(offset)} 234 : fXOffset{X(offset)}, fYOffset{Y(offset)}
233 , fXScale{X(scale)}, fYScale{Y(scale)} { } 235 , fXScale{X(scale)}, fYScale{Y(scale)} { }
234 void processPoints(Sk4f* xs, Sk4f* ys) { 236 void processPoints(Sk4s* xs, Sk4s* ys) {
235 *xs = *xs * fXScale + fXOffset; 237 *xs = *xs * fXScale + fXOffset;
236 *ys = *ys * fYScale + fYOffset; 238 *ys = *ys * fYScale + fYOffset;
237 } 239 }
238 240
239 template <typename Next> 241 template <typename Next>
240 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 242 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
241 SkPoint newStart = 243 SkPoint newStart =
242 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]}; 244 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]};
243 SkScalar newLength = length * fXScale[0]; 245 SkScalar newLength = length * fXScale[0];
244 next->pointSpan(newStart, newLength, count); 246 next->pointSpan(newStart, newLength, count);
245 return true; 247 return true;
246 } 248 }
247 249
248 private: 250 private:
249 const Sk4f fXOffset, fYOffset; 251 const Sk4s fXOffset, fYOffset;
250 const Sk4f fXScale, fYScale; 252 const Sk4s fXScale, fYScale;
251 }; 253 };
252 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> 254 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
253 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; 255 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>;
254 256
255 class AffineMatrixStrategy { 257 class AffineMatrixStrategy {
256 public: 258 public:
257 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew) 259 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew)
258 : fXOffset{X(offset)}, fYOffset{Y(offset)} 260 : fXOffset{X(offset)}, fYOffset{Y(offset)}
259 , fXScale{X(scale)}, fYScale{Y(scale)} 261 , fXScale{X(scale)}, fYScale{Y(scale)}
260 , fXSkew{X(skew)}, fYSkew{Y(skew)} { } 262 , fXSkew{X(skew)}, fYSkew{Y(skew)} { }
261 void processPoints(Sk4f* xs, Sk4f* ys) { 263 void processPoints(Sk4s* xs, Sk4s* ys) {
262 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset; 264 Sk4s newXs = fXScale * *xs + fXSkew * *ys + fXOffset;
263 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset; 265 Sk4s newYs = fYSkew * *xs + fYScale * *ys + fYOffset;
264 266
265 *xs = newXs; 267 *xs = newXs;
266 *ys = newYs; 268 *ys = newYs;
267 } 269 }
268 270
269 template <typename Next> 271 template <typename Next>
270 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 272 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
271 return false; 273 return false;
272 } 274 }
273 275
274 private: 276 private:
275 const Sk4f fXOffset, fYOffset; 277 const Sk4s fXOffset, fYOffset;
276 const Sk4f fXScale, fYScale; 278 const Sk4s fXScale, fYScale;
277 const Sk4f fXSkew, fYSkew; 279 const Sk4s fXSkew, fYSkew;
278 }; 280 };
279 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> 281 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
280 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; 282 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>;
281 283
282 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( 284 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix(
283 SkLinearBitmapPipeline::PointProcessorInterface* next, 285 SkLinearBitmapPipeline::PointProcessorInterface* next,
284 const SkMatrix& inverse, 286 const SkMatrix& inverse,
285 SkLinearBitmapPipeline::MatrixStage* matrixProc) { 287 SkLinearBitmapPipeline::MatrixStage* matrixProc) {
286 if (inverse.hasPerspective()) { 288 if (inverse.hasPerspective()) {
287 SkFAIL("Not implemented."); 289 SkFAIL("Not implemented.");
(...skipping 17 matching lines...) Expand all
305 return next; 307 return next;
306 } 308 }
307 return matrixProc->get(); 309 return matrixProc->get();
308 } 310 }
309 311
310 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 312 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
311 class ExpandBilerp final : public SkLinearBitmapPipeline::PointProcessorInterfac e { 313 class ExpandBilerp final : public SkLinearBitmapPipeline::PointProcessorInterfac e {
312 public: 314 public:
313 ExpandBilerp(Next* next) : fNext{next} { } 315 ExpandBilerp(Next* next) : fNext{next} { }
314 316
315 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 317 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
316 SkASSERT(0 < n && n < 4); 318 SkASSERT(0 < n && n < 4);
317 // px00 px10 px01 px11 319 // px00 px10 px01 px11
318 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, 320 const Sk4s kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f},
319 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; 321 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f};
320 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets); 322 if (n >= 1) fNext->bilerpList(Sk4s{xs[0]} + kXOffsets, Sk4s{ys[0]} + kYO ffsets);
321 if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYO ffsets); 323 if (n >= 2) fNext->bilerpList(Sk4s{xs[1]} + kXOffsets, Sk4s{ys[1]} + kYO ffsets);
322 if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYO ffsets); 324 if (n >= 3) fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYO ffsets);
323 } 325 }
324 326
325 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 327 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override {
326 // px00 px10 px01 px11 328 // px00 px10 px01 px11
327 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, 329 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f},
328 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; 330 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f};
329 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); 331 fNext->bilerpList(Sk4s{xs[0]} + kXOffsets, Sk4s{ys[0]} + kYOffsets);
330 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); 332 fNext->bilerpList(Sk4s{xs[1]} + kXOffsets, Sk4s{ys[1]} + kYOffsets);
331 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); 333 fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYOffsets);
332 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); 334 fNext->bilerpList(Sk4s{xs[3]} + kXOffsets, Sk4s{ys[3]} + kYOffsets);
333 } 335 }
334 336
335 void pointSpan(SkPoint start, SkScalar length, int count) override { 337 void pointSpan(SkPoint start, SkScalar length, int count) override {
336 span_fallback(start, length, count, this); 338 span_fallback(start, length, count, this);
337 } 339 }
338 340
339 private: 341 private:
340 Next* const fNext; 342 Next* const fNext;
341 }; 343 };
342 344
343 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter( 345 static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter(
344 SkLinearBitmapPipeline::BilerpProcessorInterface* next, 346 SkLinearBitmapPipeline::BilerpProcessorInterface* next,
345 SkFilterQuality filterQuailty, 347 SkFilterQuality filterQuailty,
346 SkLinearBitmapPipeline::FilterStage* filterProc) { 348 SkLinearBitmapPipeline::FilterStage* filterProc) {
347 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { 349 if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) {
348 filterProc->Initialize<SkippedStage>(); 350 filterProc->Initialize<SkippedStage>();
349 return next; 351 return next;
350 } else { 352 } else {
351 filterProc->Initialize<ExpandBilerp<>>(next); 353 filterProc->Initialize<ExpandBilerp<>>(next);
352 return filterProc->get(); 354 return filterProc->get();
353 } 355 }
354 } 356 }
355 357
358 class Span {
359 public:
360 Span(SkPoint start, SkScalar length, int count)
361 : fStart{start}
362 , fLength(length)
363 , fCount{count} {
364 SkASSERT(std::isfinite(length));
365 }
366
367 bool isEmpty() const { return 0 == count(); }
368 int count() const { return fCount; }
369 SkScalar length() const { return fLength; }
370 SkScalar startX() const { return X(fStart); }
371 SkScalar endX() const { return startX() + length(); }
372
373 bool inRange(SkScalar xMin, SkScalar xMax) const {
mtklein 2016/02/25 21:47:41 -> completelyWithin? inRange seems ambiguous abou
herb_g 2016/02/26 04:05:53 Done.
374 SkScalar sMin, sMax;
375 std::tie(sMin, sMax) = std::minmax(startX(), endX());
376 return xMin <= sMin && sMax <= xMax;
377 }
378
379 void offset(SkScalar offsetX) {
380 fStart.offset(offsetX, 0.0f);
381 }
382
383 Span breakAt(SkScalar breakX, SkScalar dx) {
mtklein 2016/02/25 21:47:41 I find the countToBreak() and lengthToBreakAndAdju
herb_g 2016/02/26 04:05:54 Done.
384 SkPoint newStart = fStart;
385
386 int newCount = countToBreak(breakX, dx);
mtklein 2016/02/25 21:47:41 all self calls need this->
herb_g 2016/02/26 04:05:54 Done.
387
388 // The length is one dx less than the count * dx like the example above. There are
mtklein 2016/02/25 21:47:40 this comment doesn't belong here given the code th
herb_g 2016/02/26 04:05:54 Done.
389 // middleCount samples, but dx is advanced one less time to get to the l ast sample.
390 SkScalar newLength = lengthToBreakAndAdjust(newCount, dx);
391
392 return Span{newStart, newLength, newCount};
393 }
394
395 Span breakAtSingleColor(SkScalar breakX, SkScalar dx) {
mtklein 2016/02/25 21:47:41 I don't understand where colors are getting involv
herb_g 2016/02/26 04:05:54 Changed the way this is done.
396
397 int newCount = countToBreak(breakX, dx);
398
399 lengthToBreakAndAdjust(newCount, dx);
400 return Span{{breakX, Y(fStart)}, 0.0f, newCount};
401 }
402
403 template <typename Next>
404 void nextStage(Next* next) {
405 SkASSERT(next != nullptr);
406 SkASSERT(fCount > 0);
407 next->pointSpan(fStart, fLength, fCount);
mtklein 2016/02/25 21:47:41 why does this function exist? doesn't this sugges
herb_g 2016/02/26 04:05:53 This is still a work in progress. Doing it now.
408 }
409
410 private:
411 int countToBreak(SkScalar breakX, SkScalar dx) {
412 SkASSERT(std::isfinite(breakX));
413 SkASSERT(std::isfinite(dx));
414 SkScalar x = X(fStart);
415 // newCount will be at least 1.
416 int newCount = SkScalarFloorToInt((breakX - x) / dx) + 1;
417 SkASSERT(newCount > 0);
418 return newCount;
419 }
420
421 SkScalar lengthToBreakAndAdjust(int count, SkScalar dx) {
422 SkScalar lengthToStart = count * dx;
423 fLength -= lengthToStart;
424 fCount -= count;
425 fStart = {X(fStart) + lengthToStart, Y(fStart)};
426 // The length is one dx less than the count * dx like the example above. There are
mtklein 2016/02/25 21:47:41 there is no example above
herb_g 2016/02/26 04:05:54 Done.
427 // middleCount samples, but dx is advanced one less time to get to the l ast sample.
428 return lengthToStart - dx;
429 }
430
431 SkPoint fStart;
432 SkScalar fLength;
433 int fCount;
434 };
435
356 class ClampStrategy { 436 class ClampStrategy {
357 public: 437 public:
358 ClampStrategy(X max) 438 ClampStrategy(X max)
359 : fXMin{0.0f} 439 : fXMin{0.0f}
360 , fXMax{max - 1.0f} { } 440 , fXMax{max - 1.0f} { }
361 ClampStrategy(Y max) 441 ClampStrategy(Y max)
362 : fYMin{0.0f} 442 : fYMin{0.0f}
363 , fYMax{max - 1.0f} { } 443 , fYMax{max - 1.0f} { }
364 ClampStrategy(SkSize max) 444 ClampStrategy(SkSize max)
365 : fXMin{0.0f} 445 : fXMin{0.0f}
366 , fYMin{0.0f} 446 , fYMin{0.0f}
367 , fXMax{X(max) - 1.0f} 447 , fXMax{X(max) - 1.0f}
368 , fYMax{Y(max) - 1.0f} { } 448 , fYMax{Y(max) - 1.0f} { }
369 449
370 void processPoints(Sk4f* xs, Sk4f* ys) { 450 void processPoints(Sk4s* xs, Sk4s* ys) {
371 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); 451 *xs = Sk4s::Min(Sk4s::Max(*xs, fXMin), fXMax);
372 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); 452 *ys = Sk4s::Min(Sk4s::Max(*ys, fYMin), fYMax);
373 } 453 }
374 454
375 template <typename Next> 455 template <typename Next>
376 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 456 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
377 return false; 457 SkASSERT(count > 0);
458 SkASSERT(std::isfinite(length));
mtklein 2016/02/25 21:47:41 We seem to assert this multiple times, but count >
herb_g 2016/02/26 04:05:54 Acknowledged.
459 SkScalar xMin = fXMin[0];
460 SkScalar xMax = fXMax[0] + 1.0f;
461 SkScalar yMin = fYMin[0];
462 SkScalar yMax = fYMax[0];
463 SkScalar x = X(start);
464 SkScalar y = std::min(std::max<SkScalar>(yMin, Y(start)), yMax);
465
466 Span span{{x, y}, length, count};
467
468 // Handle the Span is on the tile if xMin and xMax not infinities or han dle the case where
mtklein 2016/02/25 21:47:40 please make this a sentence or delete it?
herb_g 2016/02/26 04:05:53 Done.
469 // the x component is a pass through when xMin and xMax are infinities.
470 if (span.inRange(xMin, xMax)) {
471 span.nextStage(next);
472 return true;
473 }
474
475 SkScalar dx = length / (count - 1);
476
477 // This is only the case where the count is one and it is in x < xMin || xMax < x,
mtklein 2016/02/25 21:47:41 ...and it it outside [xMin, xMax]? Is it really i
herb_g 2016/02/26 04:05:54 Acknowledged.
478 // otherwise it was handled above.
479 if (1 == count || dx < 0) {
mtklein 2016/02/25 21:47:41 if (count == 1 || length < 0) { return false;
herb_g 2016/02/26 04:05:53 Changed logic
480 return false;
481 }
482
483 // A B C
484 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
485 // | *---*|---*---|*---*--||-*---*-|---*---|*---...| |--*---*|---*- --||*---*....
486 // | | | || | | | ... | | ||
487 // | | | || | | | | | ||
488 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
489 // ^ ^
490 // | xMin xMax- 1 | xMax
491 //
492 // *---*---*---... - track of samples. * = sample
493 //
494 // +-+ ||
495 // | | - pixels in source space. || - tile border.
496 // +-+ ||
497 //
498 // The length from A to B is the length in source space or 4 * dx or (co unt - 1) * dx
499 // where dx is the distance between samples. There are 5 destination pix els
500 // corresponding to 5 samples specified in the A, B span. The distance f rom A to the next
501 // span starting at C is 5 * dx, so count * dx.
502 // Remember, count is the number of pixels needed for the destination an d the number of
503 // samples.
504 // Overall Strategy:
505 // * Under - for portions of the span < xMin, take the color at pixel {x Min, y} and use it
506 // to fill in the 5 pixel sampled from A to B.
507 // * Middle - for the portion of the span between xMin and xMax sample n ormally.
508 // * Over - for the portion of the span > xMax, take the color at pixel {xMax-1, y} and
509 // use it to fill in the rest of the destination pixels.
510
511 if (dx > 0) {
512 if (span.startX() < xMin) {
513 if (span.endX() > xMin) {
514 Span toDraw = span.breakAtSingleColor(xMin, dx);
mtklein 2016/02/25 21:47:40 This breakAtSingleColor seems like something Span
mtklein 2016/02/25 21:47:41 We're not drawing anything here...
herb_g 2016/02/26 04:05:54 Totally redid logic.
515 toDraw.nextStage(next);
516 } else {
517 span.nextStage(next);
mtklein 2016/02/25 21:47:41 I don't think I follow this case. It's entirely o
herb_g 2016/02/26 04:05:54 Redid logic
518 return true;
519 }
520 }
521 if (!span.isEmpty() && span.startX() < xMax) {
mtklein 2016/02/25 21:47:40 All these if cases are really complicated. Seems
herb_g 2016/02/26 04:05:53 Done.
522 if (span.endX() > xMax) {
523 Span toDraw = span.breakAt(xMax, dx);
524 toDraw.nextStage(next);
525 } else {
526 span.nextStage(next);
527 return true;
528 };
529 }
530 if (!span.isEmpty()) {
531 next->pointSpan({xMax - 1.0f, y}, 0.0f, span.count());
532 }
533 } else {
mtklein 2016/02/25 21:47:41 How did we get dx == 0 here? Some sort of degener
herb_g 2016/02/26 04:05:54 Done.
534 if (span.startX() > xMax) {
535 if (span.endX() < xMax) {
536 Span toDraw = span.breakAtSingleColor(xMax - 1.0f, dx);
537 toDraw.nextStage(next);
538 } else {
539 span.nextStage(next);
540 return true;
541 }
542 }
543 if (!span.isEmpty() && span.startX() > xMin) {
544 if (span.endX() < xMin) {
545 Span toDraw = span.breakAt(xMin, dx);
546 toDraw.nextStage(next);
547 } else {
548 span.nextStage(next);
549 return true;
550 }
551 }
552 if (!span.isEmpty()) {
553 next->pointSpan({xMin, y}, 0.0f, span.count());
554 }
555 }
556 return true;
378 } 557 }
379 558
380 private: 559 private:
381 const Sk4f fXMin{SK_FloatNegativeInfinity}; 560 const Sk4s fXMin{SK_FloatNegativeInfinity};
382 const Sk4f fYMin{SK_FloatNegativeInfinity}; 561 const Sk4s fYMin{SK_FloatNegativeInfinity};
383 const Sk4f fXMax{SK_FloatInfinity}; 562 const Sk4s fXMax{SK_FloatInfinity};
384 const Sk4f fYMax{SK_FloatInfinity}; 563 const Sk4s fYMax{SK_FloatInfinity};
385 }; 564 };
386 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 565 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
387 using Clamp = BilerpProcessor<ClampStrategy, Next>; 566 using Clamp = BilerpProcessor<ClampStrategy, Next>;
388 567
568 static SkScalar tile_mod(SkScalar x, SkScalar base) {
569 return x - std::floor(x / base) * base;
570 }
571
389 class RepeatStrategy { 572 class RepeatStrategy {
390 public: 573 public:
391 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } 574 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { }
392 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } 575 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { }
393 RepeatStrategy(SkSize max) 576 RepeatStrategy(SkSize max)
394 : fXMax{X(max)} 577 : fXMax{X(max)}
395 , fXInvMax{1.0f / X(max)} 578 , fXInvMax{1.0f / X(max)}
396 , fYMax{Y(max)} 579 , fYMax{Y(max)}
397 , fYInvMax{1.0f / Y(max)} { } 580 , fYInvMax{1.0f / Y(max)} { }
398 581
399 void processPoints(Sk4f* xs, Sk4f* ys) { 582 void processPoints(Sk4s* xs, Sk4s* ys) {
400 Sk4f divX = (*xs * fXInvMax).floor(); 583 Sk4s divX = (*xs * fXInvMax).floor();
401 Sk4f divY = (*ys * fYInvMax).floor(); 584 Sk4s divY = (*ys * fYInvMax).floor();
402 Sk4f baseX = (divX * fXMax); 585 Sk4s baseX = (divX * fXMax);
403 Sk4f baseY = (divY * fYMax); 586 Sk4s baseY = (divY * fYMax);
404 *xs = *xs - baseX; 587 *xs = *xs - baseX;
405 *ys = *ys - baseY; 588 *ys = *ys - baseY;
406 } 589 }
407 590
408 template <typename Next> 591 template <typename Next>
409 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 592 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
410 return false; 593 SkASSERT(count > 0);
594 SkASSERT(std::isfinite(length));
595 // Make x and y in range on the tile.
596 SkScalar x = tile_mod(X(start), fXMax[0]);
597 SkScalar y = tile_mod(Y(start), fYMax[0]);
598 SkScalar xMax = fXMax[0];
599 SkScalar xMin = 0.0f;
600 SkScalar dx = length / (count - 1);
601
602 if (SkScalarAbs(dx) >= xMax) {
603 return false;
604 }
605
606 // A B C D Z
607 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
608 // | | *---|*---*--||-*---*-|---*---|*---*--|| |--*---*| ||
609 // | | | || | | || ... | | ||
610 // | | | || | | || | | ||
611 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
612 // ^^ ^^ ^^
613 // xMax || xMin xMax || xMin xM ax || xMin
614 //
615 // *---*---*---... - track of samples. * = sample
616 //
617 // +-+ ||
618 // | | - pixels in source space. || - tile border.
619 // +-+ ||
620 //
621 //
622 // The given span starts at A and continues on through several tiles to sample point Z.
623 // The idea is to break this into several spans one on each tile the ent ire span
624 // intersects. The A to B span only covers a partial tile and has a coun t of 3 and the
625 // distance from A to B is (count - 1) * dx or 2 * dx. The distance from A to the start of
626 // the next span is count * dx or 3 * dx. Span C to D covers an entire t ile has a count
627 // of 5 and a length of 4 * dx. Remember, count is the number of pixels needed for the
628 // destination and the number of samples.
629 //
630 // Overall Strategy:
631 // While the span hangs over the edge of the tile, draw the span coverin g the tile then
632 // slide the span over to the next tile.
633
634 // The guard could have been count > 0, but then a bunch of math would b e done in the
635 // common case.
636
637 Span span{{x, y}, length, count};
638 if (dx > 0) {
639 while (!span.isEmpty() && span.endX() > xMax) {
640 Span toDraw = span.breakAt(xMax, dx);
641 toDraw.nextStage(next);
642 span.offset(-xMax);
643 }
644 } else {
645 while (!span.isEmpty() && span.endX() < xMin) {
646 Span toDraw = span.breakAt(xMin, dx);
647 toDraw.nextStage(next);
648 span.offset(xMax);
649 }
650 }
651
652 // All on a single tile.
653 if (!span.isEmpty()) {
654 span.nextStage(next);
655 }
656
657 return true;
411 } 658 }
412 659
413 private: 660 private:
414 const Sk4f fXMax{0.0f}; 661 const Sk4s fXMax{0.0f};
415 const Sk4f fXInvMax{0.0f}; 662 const Sk4s fXInvMax{0.0f};
416 const Sk4f fYMax{0.0f}; 663 const Sk4s fYMax{0.0f};
417 const Sk4f fYInvMax{0.0f}; 664 const Sk4s fYInvMax{0.0f};
418 }; 665 };
419 666
420 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 667 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
421 using Repeat = BilerpProcessor<RepeatStrategy, Next>; 668 using Repeat = BilerpProcessor<RepeatStrategy, Next>;
422 669
423 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler( 670 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler(
424 SkLinearBitmapPipeline::BilerpProcessorInterface* next, 671 SkLinearBitmapPipeline::BilerpProcessorInterface* next,
425 SkSize dimensions, 672 SkSize dimensions,
426 SkShader::TileMode xMode, 673 SkShader::TileMode xMode,
427 SkShader::TileMode yMode, 674 SkShader::TileMode yMode,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 case SkShader::kMirror_TileMode: 709 case SkShader::kMirror_TileMode:
463 SkFAIL("Not implemented."); 710 SkFAIL("Not implemented.");
464 break; 711 break;
465 } 712 }
466 } 713 }
467 return tileProcXOrBoth->get(); 714 return tileProcXOrBoth->get();
468 } 715 }
469 716
470 class sRGBFast { 717 class sRGBFast {
471 public: 718 public:
472 static Sk4f VECTORCALL sRGBToLinear(Sk4f pixel) { 719 static Sk4s VECTORCALL sRGBToLinear(Sk4s pixel) {
473 Sk4f l = pixel * pixel; 720 Sk4s l = pixel * pixel;
474 return Sk4f{l[0], l[1], l[2], pixel[3]}; 721 return Sk4s{l[0], l[1], l[2], pixel[3]};
475 } 722 }
476 }; 723 };
477 724
478 template <SkColorProfileType colorProfile> 725 template <SkColorProfileType colorProfile>
479 class Passthrough8888 { 726 class Passthrough8888 {
480 public: 727 public:
481 Passthrough8888(int width, const uint32_t* src) 728 Passthrough8888(int width, const uint32_t* src)
482 : fSrc{src}, fWidth{width}{ } 729 : fSrc{src}, fWidth{width}{ }
483 730
484 void VECTORCALL getFewPixels(int n, Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { 731 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) {
485 Sk4i XIs = SkNx_cast<int, float>(xs); 732 Sk4i XIs = SkNx_cast<int, SkScalar>(xs);
486 Sk4i YIs = SkNx_cast<int, float>(ys); 733 Sk4i YIs = SkNx_cast<int, SkScalar>(ys);
487 Sk4i bufferLoc = YIs * fWidth + XIs; 734 Sk4i bufferLoc = YIs * fWidth + XIs;
488 switch (n) { 735 switch (n) {
489 case 3: 736 case 3:
490 *px2 = getPixel(fSrc, bufferLoc[2]); 737 *px2 = getPixel(fSrc, bufferLoc[2]);
491 case 2: 738 case 2:
492 *px1 = getPixel(fSrc, bufferLoc[1]); 739 *px1 = getPixel(fSrc, bufferLoc[1]);
493 case 1: 740 case 1:
494 *px0 = getPixel(fSrc, bufferLoc[0]); 741 *px0 = getPixel(fSrc, bufferLoc[0]);
495 default: 742 default:
496 break; 743 break;
497 } 744 }
498 } 745 }
499 746
500 void VECTORCALL get4Pixels(Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) { 747 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) {
501 Sk4i XIs = SkNx_cast<int, float>(xs); 748 Sk4i XIs = SkNx_cast<int, SkScalar>(xs);
502 Sk4i YIs = SkNx_cast<int, float>(ys); 749 Sk4i YIs = SkNx_cast<int, SkScalar>(ys);
503 Sk4i bufferLoc = YIs * fWidth + XIs; 750 Sk4i bufferLoc = YIs * fWidth + XIs;
504 *px0 = getPixel(fSrc, bufferLoc[0]); 751 *px0 = getPixel(fSrc, bufferLoc[0]);
505 *px1 = getPixel(fSrc, bufferLoc[1]); 752 *px1 = getPixel(fSrc, bufferLoc[1]);
506 *px2 = getPixel(fSrc, bufferLoc[2]); 753 *px2 = getPixel(fSrc, bufferLoc[2]);
507 *px3 = getPixel(fSrc, bufferLoc[3]); 754 *px3 = getPixel(fSrc, bufferLoc[3]);
508 } 755 }
509 756
510 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; } 757 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; }
511 758
512 private: 759 private:
(...skipping 23 matching lines...) Expand all
536 // +--------+--------+ 783 // +--------+--------+
537 // 784 //
538 // 785 //
539 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x 786 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x
540 // and y: 787 // and y:
541 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy 788 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy
542 // * px10 -> x(1 - y) = x - xy 789 // * px10 -> x(1 - y) = x - xy
543 // * px01 -> (1 - x)y = y - xy 790 // * px01 -> (1 - x)y = y - xy
544 // * px11 -> xy 791 // * px11 -> xy
545 // So x * y is calculated first and then used to calculate all the other factors . 792 // So x * y is calculated first and then used to calculate all the other factors .
546 static Sk4f VECTORCALL bilerp4(Sk4f xs, Sk4f ys, Sk4f px00, Sk4f px10, 793 static Sk4s VECTORCALL bilerp4(Sk4s xs, Sk4s ys, Sk4f px00, Sk4f px10,
547 Sk4f px01, Sk4f px11) { 794 Sk4f px01, Sk4f px11) {
548 // Calculate fractional xs and ys. 795 // Calculate fractional xs and ys.
549 Sk4f fxs = xs - xs.floor(); 796 Sk4s fxs = xs - xs.floor();
550 Sk4f fys = ys - ys.floor(); 797 Sk4s fys = ys - ys.floor();
551 Sk4f fxys{fxs * fys}; 798 Sk4s fxys{fxs * fys};
552 Sk4f sum = px11 * fxys; 799 Sk4f sum = px11 * fxys;
553 sum = sum + px01 * (fys - fxys); 800 sum = sum + px01 * (fys - fxys);
554 sum = sum + px10 * (fxs - fxys); 801 sum = sum + px10 * (fxs - fxys);
555 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); 802 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys);
556 return sum; 803 return sum;
557 } 804 }
558 805
559 template <typename SourceStrategy> 806 template <typename SourceStrategy>
560 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface { 807 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface {
561 public: 808 public:
562 template <typename... Args> 809 template <typename... Args>
563 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args) 810 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args)
564 : fNext{next} 811 : fNext{next}
565 , fStrategy{std::forward<Args>(args)...} { } 812 , fStrategy{std::forward<Args>(args)...} { }
566 813
567 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 814 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
568 SkASSERT(0 < n && n < 4); 815 SkASSERT(0 < n && n < 4);
569 Sk4f px0, px1, px2; 816 Sk4f px0, px1, px2;
570 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); 817 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2);
571 if (n >= 1) fNext->placePixel(px0); 818 if (n >= 1) fNext->placePixel(px0);
572 if (n >= 2) fNext->placePixel(px1); 819 if (n >= 2) fNext->placePixel(px1);
573 if (n >= 3) fNext->placePixel(px2); 820 if (n >= 3) fNext->placePixel(px2);
574 } 821 }
575 822
576 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 823 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
577 Sk4f px0, px1, px2, px3; 824 Sk4f px0, px1, px2, px3;
578 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); 825 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3);
579 fNext->place4Pixels(px0, px1, px2, px3); 826 fNext->place4Pixels(px0, px1, px2, px3);
580 } 827 }
581 828
582 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { 829 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override {
583 Sk4f px00, px10, px01, px11; 830 Sk4f px00, px10, px01, px11;
584 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); 831 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11);
585 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); 832 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11);
586 fNext->placePixel(pixel); 833 fNext->placePixel(pixel);
587 } 834 }
588 835
589 void pointSpan(SkPoint start, SkScalar length, int count) override { 836 void pointSpan(SkPoint start, SkScalar length, int count) override {
590 span_fallback(start, length, count, this); 837 span_fallback(start, length, count, this);
591 } 838 }
592 839
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp leStage); 937 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp leStage);
691 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage, 938 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage,
692 &fTileYStage); 939 &fTileYStage);
693 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage ); 940 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage );
694 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); 941 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage);
695 } 942 }
696 943
697 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { 944 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
698 SkASSERT(count > 0); 945 SkASSERT(count > 0);
699 fPixelStage->setDestination(dst); 946 fPixelStage->setDestination(dst);
700 // Adjust points by 0.5, 0.5 to sample from the center of the pixels. 947 // The count and length arguments start out in a precise relation in order t o keep the
701 if (count == 1) { 948 // math correct through the different stages. Count is the number of pixel t o produce.
702 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); 949 // Since the code samples at pixel centers, length is the distance from the center of the
703 } else { 950 // first pixel to the center of the last pixel. This implies that length is count-1.
704 // The count and length arguments start out in a precise relation in ord er to keep the 951 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count);
705 // math correct through the different stages. Count is the number of pix el to produce.
706 // Since the code samples at pixel centers, length is the distance from the center of the
707 // first pixel to the center of the last pixel. This implies that length is count-1.
708 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count);
709 }
710 } 952 }
OLDNEW
« no previous file with comments | « gm/SkLinearBitmapPipelineGM.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698