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

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