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

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