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

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: Address comments. 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 | « no previous file | 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
(...skipping 14 matching lines...) Expand all
357 public: 359 public:
358 ClampStrategy(X max) 360 ClampStrategy(X max)
359 : fXMin{0.0f} 361 : fXMin{0.0f}
360 , fXMax{max - 1.0f} { } 362 , fXMax{max - 1.0f} { }
361 ClampStrategy(Y max) 363 ClampStrategy(Y max)
362 : fYMin{0.0f} 364 : fYMin{0.0f}
363 , fYMax{max - 1.0f} { } 365 , fYMax{max - 1.0f} { }
364 ClampStrategy(SkSize max) 366 ClampStrategy(SkSize max)
365 : fXMin{0.0f} 367 : fXMin{0.0f}
366 , fYMin{0.0f} 368 , fYMin{0.0f}
367 , fXMax{X(max) - 1.0f} 369 , fXMax{X(max) - 1.0f}
mtklein 2016/02/24 19:42:52 Some of this stuff would be clearer if we stuck to
368 , fYMax{Y(max) - 1.0f} { } 370 , fYMax{Y(max) - 1.0f} { }
369 371
370 void processPoints(Sk4f* xs, Sk4f* ys) { 372 void processPoints(Sk4s* xs, Sk4s* ys) {
371 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); 373 *xs = Sk4s::Min(Sk4s::Max(*xs, fXMin), fXMax);
372 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); 374 *ys = Sk4s::Min(Sk4s::Max(*ys, fYMin), fYMax);
373 } 375 }
374 376
375 template <typename Next> 377 template <typename Next>
376 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 378 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
377 return false; 379 SkScalar xMin = fXMin[0];
380 SkScalar xMax = fXMax[0] + 1.0f;
381 SkScalar yMin = fYMin[0];
382 SkScalar yMax = fYMax[0];
383 SkScalar x = X(start);
384 SkScalar y = std::min(std::max<SkScalar>(yMin, Y(start)), yMax);
385
386 bool under = x < xMin;
387
388 if (!under && x + length < xMax) {
389 next->pointSpan(start, length, count);
390 return true;
391 }
392
393 SkScalar dx = length / (count - 1);
mtklein 2016/02/24 19:42:52 Watch out for NaN?
394
395 if (dx > xMax) {
396 return false;
mtklein 2016/02/24 19:42:52 // TODO: left and right spans could still get some
397 }
398
399 // A B C
400 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
401 // | *---*|---*---|*---*--||-*---*-|---*---|*---...| |--*---*|---*- --||*---*....
402 // | | | || | | | ... | | ||
403 // | | | || | | | | | ||
404 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
405 // ^ ^
406 // | xMin xMax- 1 | xMax
407 //
408 // *---*---*---... - track of samples. * = sample
409 //
410 // +-+ ||
411 // | | - pixels in source space. || - tile border.
412 // +-+ ||
413 //
414 // The length from A to B is the length in source space or 4 * dx or (co unt - 1) * dx
415 // where dx is the distance between samples. There are 5 destination pix els
416 // corresponding to 5 samples specified in the A, B span. The distance f rom A to the next
417 // span starting at C is 5 * dx, so count * dx.
418 // Remember, count is the number of pixels needed for the destination an d the number of
419 // samples.
420 // Overall Strategy:
421 // * Under - for portions of the span < xMin, take the color at pixel {x Min, y} and use it
422 // to fill in the 5 pixel sampled from A to B.
423 // * Middle - for the portion of the span between xMin and xMax sample n ormally.
424 // * Over - for the portion of the span > xMax, take the color at pixel {xMax-1, y} and
425 // use it to fill in the rest of the destination pixels.
426 if (under) {
427 // It could be that the entire span is off the left edge of the tile .
428 SkScalar EdgeOrXEnd = std::min(xMin, x + length + 1.0f);
mtklein 2016/02/24 19:42:52 +1 ?
429 int underCount = SkScalarFloorToInt((EdgeOrXEnd - x) / dx) + 1;
mtklein 2016/02/24 19:42:51 // There are n dx's between n+1 samples. (5 *'s a
mtklein 2016/02/24 19:42:52 Should be safe to assert (EdgeOrXEnd - x >= 0).
430 if (underCount > 0) {
mtklein 2016/02/24 19:42:52 how can this not be at least 1?
431 // Use the pixel on the edge of the bitmap as the color for the entire span.
432 // Using a length of 0 causes x not to move in the sampler resul ting in the same
433 // pixel being used for the entire span.
434 next->pointSpan({xMin, y}, 0.0f, underCount);
435
436 // The length is not the distance to xMin, but to the next start ing sample.
437 SkScalar lengthToNextStart = dx * underCount;
438 count -= underCount;
439 length -= lengthToNextStart;
440 x += lengthToNextStart;
441 }
442 }
443
444 // If there are more pixels needed, sample from the middle of the tile.
mtklein 2016/02/24 19:42:52 Three cases left: - all in the tile - some in
445 if (count > 0) {
446 // It could be that span continues off the edge of tile; use min for the limit.
447 SkScalar EdgeOrXEnd = std::min(xMax, x + length);
448 int middleCount = SkScalarFloorToInt((EdgeOrXEnd - x) / dx) + 1;
449 SkScalar middleLength = (middleCount - 1) * dx;
mtklein 2016/02/24 19:42:52 // N samples span N-1 dx's.
450 next->pointSpan({x, y}, middleLength, middleCount);
451 count -= middleCount;
452 }
453
454 if (count > 0) {
455 // Use the pixel on the edge of the bitmap as the color for the enti re span.
456 // Using a length of 0 causes x not to move in the sampler resulting in the same
457 // pixel being used for the entire span.
458 next->pointSpan({xMax - 1.0f, y}, 0.0f, count);
459 }
460
461 return true;
378 } 462 }
379 463
380 private: 464 private:
381 const Sk4f fXMin{SK_FloatNegativeInfinity}; 465 const Sk4s fXMin{SK_FloatNegativeInfinity};
382 const Sk4f fYMin{SK_FloatNegativeInfinity}; 466 const Sk4s fYMin{SK_FloatNegativeInfinity};
383 const Sk4f fXMax{SK_FloatInfinity}; 467 const Sk4s fXMax{SK_FloatInfinity};
384 const Sk4f fYMax{SK_FloatInfinity}; 468 const Sk4s fYMax{SK_FloatInfinity};
385 }; 469 };
386 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 470 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
387 using Clamp = BilerpProcessor<ClampStrategy, Next>; 471 using Clamp = BilerpProcessor<ClampStrategy, Next>;
388 472
473 // It would be nice to use fmod, but it uses trunc based rounding where floor ro unding is needed.
mtklein 2016/02/24 19:42:52 remove comment?
474 static SkScalar tile_mod(SkScalar x, SkScalar base) {
475 return x - std::floor(x / base) * base;
476 }
477
389 class RepeatStrategy { 478 class RepeatStrategy {
390 public: 479 public:
391 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } 480 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { }
392 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } 481 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { }
393 RepeatStrategy(SkSize max) 482 RepeatStrategy(SkSize max)
394 : fXMax{X(max)} 483 : fXMax{X(max)}
395 , fXInvMax{1.0f / X(max)} 484 , fXInvMax{1.0f / X(max)}
396 , fYMax{Y(max)} 485 , fYMax{Y(max)}
397 , fYInvMax{1.0f / Y(max)} { } 486 , fYInvMax{1.0f / Y(max)} { }
398 487
399 void processPoints(Sk4f* xs, Sk4f* ys) { 488 void processPoints(Sk4s* xs, Sk4s* ys) {
400 Sk4f divX = (*xs * fXInvMax).floor(); 489 Sk4s divX = (*xs * fXInvMax).floor();
401 Sk4f divY = (*ys * fYInvMax).floor(); 490 Sk4s divY = (*ys * fYInvMax).floor();
402 Sk4f baseX = (divX * fXMax); 491 Sk4s baseX = (divX * fXMax);
403 Sk4f baseY = (divY * fYMax); 492 Sk4s baseY = (divY * fYMax);
404 *xs = *xs - baseX; 493 *xs = *xs - baseX;
405 *ys = *ys - baseY; 494 *ys = *ys - baseY;
406 } 495 }
407 496
408 template <typename Next> 497 template <typename Next>
409 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 498 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
410 return false; 499 // Make x and y in range on the tile.
500 SkScalar x = tile_mod(X(start), fXMax[0]);
501 SkScalar y = tile_mod(Y(start), fYMax[0]);
502 SkScalar xMax = fXMax[0];
503 SkScalar dx = length / (count - 1);
mtklein 2016/02/24 19:42:52 NaN
504 if (dx > xMax) {
505 return false;
mtklein 2016/02/24 19:42:52 // No point to spanning if we're not going to have
506 }
507
508 // A B C D Z
509 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
510 // | | *---|*---*--||-*---*-|---*---|*---*--|| |--*---*| ||
511 // | | | || | | || ... | | ||
512 // | | | || | | || | | ||
513 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
514 // ^^ ^^ ^^
515 // xMax || xMin xMax || xMin xM ax || xMin
516 //
517 // *---*---*---... - track of samples. * = sample
518 //
519 // +-+ ||
520 // | | - pixels in source space. || - tile border.
521 // +-+ ||
522 //
523 //
524 // The given span starts at A and continues on through several tiles to sample point Z.
525 // The idea is to break this into several spans one on each tile the ent ire span
526 // intersects. The A to B span only covers a partial tile and has a coun t of 3 and the
527 // distance from A to B is (count - 1) * dx or 2 * dx. The distance from A to the start of
528 // the next span is count * dx or 3 * dx. Span C to D covers an entire t ile has a count
529 // of 5 and a length of 4 * dx. Remember, count is the number of pixels needed for the
530 // destination and the number of samples.
531 //
532 // Overall Strategy:
533 // While the span hangs over the edge of the tile, draw the span coverin g the tile then
534 // slide the span over to the next tile.
535
536 // The guard could have been count > 0, but then a bunch of math would b e done in the
537 // common case.
538 while (x + length > xMax) {
539 // The number of samples that intersect this tile.
540 int countForTile = SkScalarFloorToInt((xMax - x) / dx) + 1;
541 // The distance between the first and last sample.
542 SkScalar lengthForSpanOnTile = (countForTile - 1) * dx;
543 // Span the samples.
544 next->pointSpan({x, y}, lengthForSpanOnTile, countForTile);
545 // Add one more dx to get to the first sample on the next tile.
546 SkScalar lengthToNextStart = lengthForSpanOnTile + dx;
547 // slide over to the next tile.
548 length -= lengthToNextStart;
549 count -= countForTile;
550 x += lengthToNextStart - xMax;
mtklein 2016/02/24 19:42:51 // step forward the length we've consumed, then mo
551 }
552 // All on a single tile.
553 if (count > 0) {
554 next->pointSpan({x, y}, length, count);
555 }
556
557 return true;
411 } 558 }
412 559
413 private: 560 private:
414 const Sk4f fXMax{0.0f}; 561 const Sk4s fXMax{0.0f};
415 const Sk4f fXInvMax{0.0f}; 562 const Sk4s fXInvMax{0.0f};
416 const Sk4f fYMax{0.0f}; 563 const Sk4s fYMax{0.0f};
417 const Sk4f fYInvMax{0.0f}; 564 const Sk4s fYInvMax{0.0f};
418 }; 565 };
419 566
420 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 567 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
421 using Repeat = BilerpProcessor<RepeatStrategy, Next>; 568 using Repeat = BilerpProcessor<RepeatStrategy, Next>;
422 569
423 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler( 570 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler(
424 SkLinearBitmapPipeline::BilerpProcessorInterface* next, 571 SkLinearBitmapPipeline::BilerpProcessorInterface* next,
425 SkSize dimensions, 572 SkSize dimensions,
426 SkShader::TileMode xMode, 573 SkShader::TileMode xMode,
427 SkShader::TileMode yMode, 574 SkShader::TileMode yMode,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 case SkShader::kMirror_TileMode: 609 case SkShader::kMirror_TileMode:
463 SkFAIL("Not implemented."); 610 SkFAIL("Not implemented.");
464 break; 611 break;
465 } 612 }
466 } 613 }
467 return tileProcXOrBoth->get(); 614 return tileProcXOrBoth->get();
468 } 615 }
469 616
470 class sRGBFast { 617 class sRGBFast {
471 public: 618 public:
472 static Sk4f VECTORCALL sRGBToLinear(Sk4f pixel) { 619 static Sk4s VECTORCALL sRGBToLinear(Sk4s pixel) {
473 Sk4f l = pixel * pixel; 620 Sk4s l = pixel * pixel;
474 return Sk4f{l[0], l[1], l[2], pixel[3]}; 621 return Sk4s{l[0], l[1], l[2], pixel[3]};
475 } 622 }
476 }; 623 };
477 624
478 template <SkColorProfileType colorProfile> 625 template <SkColorProfileType colorProfile>
479 class Passthrough8888 { 626 class Passthrough8888 {
480 public: 627 public:
481 Passthrough8888(int width, const uint32_t* src) 628 Passthrough8888(int width, const uint32_t* src)
482 : fSrc{src}, fWidth{width}{ } 629 : fSrc{src}, fWidth{width}{ }
483 630
484 void VECTORCALL getFewPixels(int n, Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { 631 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) {
485 Sk4i XIs = SkNx_cast<int, float>(xs); 632 Sk4i XIs = SkNx_cast<int, SkScalar>(xs);
486 Sk4i YIs = SkNx_cast<int, float>(ys); 633 Sk4i YIs = SkNx_cast<int, SkScalar>(ys);
487 Sk4i bufferLoc = YIs * fWidth + XIs; 634 Sk4i bufferLoc = YIs * fWidth + XIs;
488 switch (n) { 635 switch (n) {
489 case 3: 636 case 3:
490 *px2 = getPixel(fSrc, bufferLoc[2]); 637 *px2 = getPixel(fSrc, bufferLoc[2]);
491 case 2: 638 case 2:
492 *px1 = getPixel(fSrc, bufferLoc[1]); 639 *px1 = getPixel(fSrc, bufferLoc[1]);
493 case 1: 640 case 1:
494 *px0 = getPixel(fSrc, bufferLoc[0]); 641 *px0 = getPixel(fSrc, bufferLoc[0]);
495 default: 642 default:
496 break; 643 break;
497 } 644 }
498 } 645 }
499 646
500 void VECTORCALL get4Pixels(Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) { 647 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) {
501 Sk4i XIs = SkNx_cast<int, float>(xs); 648 Sk4i XIs = SkNx_cast<int, SkScalar>(xs);
502 Sk4i YIs = SkNx_cast<int, float>(ys); 649 Sk4i YIs = SkNx_cast<int, SkScalar>(ys);
503 Sk4i bufferLoc = YIs * fWidth + XIs; 650 Sk4i bufferLoc = YIs * fWidth + XIs;
504 *px0 = getPixel(fSrc, bufferLoc[0]); 651 *px0 = getPixel(fSrc, bufferLoc[0]);
505 *px1 = getPixel(fSrc, bufferLoc[1]); 652 *px1 = getPixel(fSrc, bufferLoc[1]);
506 *px2 = getPixel(fSrc, bufferLoc[2]); 653 *px2 = getPixel(fSrc, bufferLoc[2]);
507 *px3 = getPixel(fSrc, bufferLoc[3]); 654 *px3 = getPixel(fSrc, bufferLoc[3]);
508 } 655 }
509 656
510 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; } 657 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; }
511 658
512 private: 659 private:
(...skipping 23 matching lines...) Expand all
536 // +--------+--------+ 683 // +--------+--------+
537 // 684 //
538 // 685 //
539 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x 686 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x
540 // and y: 687 // and y:
541 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy 688 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy
542 // * px10 -> x(1 - y) = x - xy 689 // * px10 -> x(1 - y) = x - xy
543 // * px01 -> (1 - x)y = y - xy 690 // * px01 -> (1 - x)y = y - xy
544 // * px11 -> xy 691 // * px11 -> xy
545 // So x * y is calculated first and then used to calculate all the other factors . 692 // 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, 693 static Sk4s VECTORCALL bilerp4(Sk4s xs, Sk4s ys, Sk4f px00, Sk4f px10,
547 Sk4f px01, Sk4f px11) { 694 Sk4f px01, Sk4f px11) {
548 // Calculate fractional xs and ys. 695 // Calculate fractional xs and ys.
549 Sk4f fxs = xs - xs.floor(); 696 Sk4s fxs = xs - xs.floor();
550 Sk4f fys = ys - ys.floor(); 697 Sk4s fys = ys - ys.floor();
551 Sk4f fxys{fxs * fys}; 698 Sk4s fxys{fxs * fys};
552 Sk4f sum = px11 * fxys; 699 Sk4f sum = px11 * fxys;
553 sum = sum + px01 * (fys - fxys); 700 sum = sum + px01 * (fys - fxys);
554 sum = sum + px10 * (fxs - fxys); 701 sum = sum + px10 * (fxs - fxys);
555 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); 702 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys);
556 return sum; 703 return sum;
557 } 704 }
558 705
559 template <typename SourceStrategy> 706 template <typename SourceStrategy>
560 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface { 707 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface {
561 public: 708 public:
562 template <typename... Args> 709 template <typename... Args>
563 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args) 710 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args)
564 : fNext{next} 711 : fNext{next}
565 , fStrategy{std::forward<Args>(args)...} { } 712 , fStrategy{std::forward<Args>(args)...} { }
566 713
567 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 714 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
568 SkASSERT(0 < n && n < 4); 715 SkASSERT(0 < n && n < 4);
569 Sk4f px0, px1, px2; 716 Sk4f px0, px1, px2;
570 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); 717 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2);
571 if (n >= 1) fNext->placePixel(px0); 718 if (n >= 1) fNext->placePixel(px0);
572 if (n >= 2) fNext->placePixel(px1); 719 if (n >= 2) fNext->placePixel(px1);
573 if (n >= 3) fNext->placePixel(px2); 720 if (n >= 3) fNext->placePixel(px2);
574 } 721 }
575 722
576 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 723 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
577 Sk4f px0, px1, px2, px3; 724 Sk4f px0, px1, px2, px3;
578 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); 725 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3);
579 fNext->place4Pixels(px0, px1, px2, px3); 726 fNext->place4Pixels(px0, px1, px2, px3);
580 } 727 }
581 728
582 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { 729 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override {
583 Sk4f px00, px10, px01, px11; 730 Sk4f px00, px10, px01, px11;
584 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); 731 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11);
585 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); 732 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11);
586 fNext->placePixel(pixel); 733 fNext->placePixel(pixel);
587 } 734 }
588 735
589 void pointSpan(SkPoint start, SkScalar length, int count) override { 736 void pointSpan(SkPoint start, SkScalar length, int count) override {
590 span_fallback(start, length, count, this); 737 span_fallback(start, length, count, this);
591 } 738 }
592 739
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp leStage); 837 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp leStage);
691 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage, 838 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage,
692 &fTileYStage); 839 &fTileYStage);
693 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage ); 840 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage );
694 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); 841 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage);
695 } 842 }
696 843
697 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { 844 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
698 SkASSERT(count > 0); 845 SkASSERT(count > 0);
699 fPixelStage->setDestination(dst); 846 fPixelStage->setDestination(dst);
700 // Adjust points by 0.5, 0.5 to sample from the center of the pixels. 847 // The count and length arguments start out in a precise relation in order t o keep the
701 if (count == 1) { 848 // 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}); 849 // Since the code samples at pixel centers, length is the distance from the center of the
703 } else { 850 // 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 851 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 } 852 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698