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

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, 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 | « 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
mtklein 2016/02/23 23:49:57 Seems like it's all the other lines that are wrong
herb_g 2016/02/24 18:16:06 Done.
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 float fVal;
mtklein 2016/02/23 23:49:57 SkScalar
herb_g 2016/02/24 18:16:06 Done.
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 float 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.
97 SkASSERT(count > 1);
98
99 float dx = length / (count - 1); 96 float dx = length / (count - 1);
mtklein 2016/02/23 23:49:57 Let's do a careful search for all 'float' in here.
herb_g 2016/02/24 18:16:06 Done.
100 Sk4f Xs = Sk4f(X(start)) + Sk4f{0.0f, 1.0f, 2.0f, 3.0f} * Sk4f{dx}; 97 // Xs must be calculated in the following manner instead of dx * {0.0, 1.0, 2.0, 3.0} because
mtklein 2016/02/23 23:49:57 Seems fine to branch on count too, if that makes t
herb_g 2016/02/24 18:16:06 Done.
101 Sk4f Ys{Y(start)}; 98 // dx may be nan (in the case where length and count - 1 are zero). The foll owing produces a
102 Sk4f fourDx = {4.0f * dx}; 99 // 0.0f in lane 0 which is required for handling the length = 0 and count = 1 case.
100 Sk4s Xs = Sk4s(X(start)) + Sk4s{0.0f, dx, 2.0f * dx, 3.0f * dx};
101 Sk4s Ys{Y(start)};
102 Sk4s fourDx = {4.0f * dx};
103 103
104 while (count >= 4) { 104 while (count >= 4) {
105 stage->pointList4(Xs, Ys); 105 stage->pointList4(Xs, Ys);
106 Xs = Xs + fourDx; 106 Xs = Xs + fourDx;
107 count -= 4; 107 count -= 4;
108 } 108 }
109 if (count > 0) { 109 if (count > 0) {
110 stage->pointListFew(count, Xs, Ys); 110 stage->pointListFew(count, Xs, Ys);
111 } 111 }
112 } 112 }
(...skipping 12 matching lines...) Expand all
125 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to 125 // maybeProcessSpan - returns false if it can not process the span and needs t o fallback to
126 // point lists for processing. 126 // point lists for processing.
127 template<typename Strategy, typename Next> 127 template<typename Strategy, typename Next>
128 class PointProcessor final : public SkLinearBitmapPipeline::PointProcessorInterf ace { 128 class PointProcessor final : public SkLinearBitmapPipeline::PointProcessorInterf ace {
129 public: 129 public:
130 template <typename... Args> 130 template <typename... Args>
131 PointProcessor(Next* next, Args&&... args) 131 PointProcessor(Next* next, Args&&... args)
132 : fNext{next} 132 : fNext{next}
133 , fStrategy{std::forward<Args>(args)...}{ } 133 , fStrategy{std::forward<Args>(args)...}{ }
134 134
135 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 135 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
136 fStrategy.processPoints(&xs, &ys); 136 fStrategy.processPoints(&xs, &ys);
137 fNext->pointListFew(n, xs, ys); 137 fNext->pointListFew(n, xs, ys);
138 } 138 }
139 139
140 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 140 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
141 fStrategy.processPoints(&xs, &ys); 141 fStrategy.processPoints(&xs, &ys);
142 fNext->pointList4(xs, ys); 142 fNext->pointList4(xs, ys);
143 } 143 }
144 144
145 void pointSpan(SkPoint start, SkScalar length, int count) override { 145 void pointSpan(SkPoint start, SkScalar length, int count) override {
146 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { 146 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) {
147 span_fallback(start, length, count, this); 147 span_fallback(start, length, count, this);
148 } 148 }
149 } 149 }
150 150
151 private: 151 private:
152 Next* const fNext; 152 Next* const fNext;
153 Strategy fStrategy; 153 Strategy fStrategy;
154 }; 154 };
155 155
156 // See PointProcessor for responsibilities of Strategy. 156 // See PointProcessor for responsibilities of Strategy.
157 template<typename Strategy, typename Next> 157 template<typename Strategy, typename Next>
158 class BilerpProcessor final : public SkLinearBitmapPipeline::BilerpProcessorInte rface { 158 class BilerpProcessor final : public SkLinearBitmapPipeline::BilerpProcessorInte rface {
159 public: 159 public:
160 template <typename... Args> 160 template <typename... Args>
161 BilerpProcessor(Next* next, Args&&... args) 161 BilerpProcessor(Next* next, Args&&... args)
162 : fNext{next} 162 : fNext{next}
163 , fStrategy{std::forward<Args>(args)...}{ } 163 , fStrategy{std::forward<Args>(args)...}{ }
164 164
165 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 165 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
166 fStrategy.processPoints(&xs, &ys); 166 fStrategy.processPoints(&xs, &ys);
167 fNext->pointListFew(n, xs, ys); 167 fNext->pointListFew(n, xs, ys);
168 } 168 }
169 169
170 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 170 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
171 fStrategy.processPoints(&xs, &ys); 171 fStrategy.processPoints(&xs, &ys);
172 fNext->pointList4(xs, ys); 172 fNext->pointList4(xs, ys);
173 } 173 }
174 174
175 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { 175 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override {
176 fStrategy.processPoints(&xs, &ys); 176 fStrategy.processPoints(&xs, &ys);
177 fNext->bilerpList(xs, ys); 177 fNext->bilerpList(xs, ys);
178 } 178 }
179 179
180 void pointSpan(SkPoint start, SkScalar length, int count) override { 180 void pointSpan(SkPoint start, SkScalar length, int count) override {
181 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) { 181 if (!fStrategy.maybeProcessSpan(start, length, count, fNext)) {
182 span_fallback(start, length, count, this); 182 span_fallback(start, length, count, this);
183 } 183 }
184 } 184 }
185 185
186 private: 186 private:
187 Next* const fNext; 187 Next* const fNext;
188 Strategy fStrategy; 188 Strategy fStrategy;
189 }; 189 };
190 190
191 class SkippedStage final : public SkLinearBitmapPipeline::BilerpProcessorInterfa ce { 191 class SkippedStage final : public SkLinearBitmapPipeline::BilerpProcessorInterfa ce {
192 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 192 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
193 SkFAIL("Skipped stage."); 193 SkFAIL("Skipped stage.");
194 } 194 }
195 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 195 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
196 SkFAIL("Skipped stage."); 196 SkFAIL("Skipped stage.");
197 } 197 }
198 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { 198 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override {
199 SkFAIL("Skipped stage."); 199 SkFAIL("Skipped stage.");
200 } 200 }
201 void pointSpan(SkPoint start, SkScalar length, int count) override { 201 void pointSpan(SkPoint start, SkScalar length, int count) override {
202 SkFAIL("Skipped stage."); 202 SkFAIL("Skipped stage.");
203 } 203 }
204 }; 204 };
205 205
206 class TranslateMatrixStrategy { 206 class TranslateMatrixStrategy {
207 public: 207 public:
208 TranslateMatrixStrategy(SkVector offset) 208 TranslateMatrixStrategy(SkVector offset)
209 : fXOffset{X(offset)} 209 : fXOffset{X(offset)}
210 , fYOffset{Y(offset)} { } 210 , fYOffset{Y(offset)} { }
211 211
212 void processPoints(Sk4f* xs, Sk4f* ys) { 212 void processPoints(Sk4s* xs, Sk4s* ys) {
213 *xs = *xs + fXOffset; 213 *xs = *xs + fXOffset;
214 *ys = *ys + fYOffset; 214 *ys = *ys + fYOffset;
215 } 215 }
216 216
217 template <typename Next> 217 template <typename Next>
218 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 218 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
219 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count ); 219 next->pointSpan(start + SkPoint{fXOffset[0], fYOffset[0]}, length, count );
220 return true; 220 return true;
221 } 221 }
222 222
223 private: 223 private:
224 const Sk4f fXOffset, fYOffset; 224 const Sk4s fXOffset, fYOffset;
225 }; 225 };
226 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> 226 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
227 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; 227 using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>;
228 228
229 class ScaleMatrixStrategy { 229 class ScaleMatrixStrategy {
230 public: 230 public:
231 ScaleMatrixStrategy(SkVector offset, SkVector scale) 231 ScaleMatrixStrategy(SkVector offset, SkVector scale)
232 : fXOffset{X(offset)}, fYOffset{Y(offset)} 232 : fXOffset{X(offset)}, fYOffset{Y(offset)}
233 , fXScale{X(scale)}, fYScale{Y(scale)} { } 233 , fXScale{X(scale)}, fYScale{Y(scale)} { }
234 void processPoints(Sk4f* xs, Sk4f* ys) { 234 void processPoints(Sk4s* xs, Sk4s* ys) {
235 *xs = *xs * fXScale + fXOffset; 235 *xs = *xs * fXScale + fXOffset;
236 *ys = *ys * fYScale + fYOffset; 236 *ys = *ys * fYScale + fYOffset;
237 } 237 }
238 238
239 template <typename Next> 239 template <typename Next>
240 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 240 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
241 SkPoint newStart = 241 SkPoint newStart =
242 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]}; 242 SkPoint{X(start) * fXScale[0] + fXOffset[0], Y(start) * fYScale[0] + fYOffset[0]};
243 SkScalar newLength = length * fXScale[0]; 243 SkScalar newLength = length * fXScale[0];
244 next->pointSpan(newStart, newLength, count); 244 next->pointSpan(newStart, newLength, count);
245 return true; 245 return true;
246 } 246 }
247 247
248 private: 248 private:
249 const Sk4f fXOffset, fYOffset; 249 const Sk4s fXOffset, fYOffset;
250 const Sk4f fXScale, fYScale; 250 const Sk4s fXScale, fYScale;
251 }; 251 };
252 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> 252 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
253 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; 253 using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>;
254 254
255 class AffineMatrixStrategy { 255 class AffineMatrixStrategy {
256 public: 256 public:
257 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew) 257 AffineMatrixStrategy(SkVector offset, SkVector scale, SkVector skew)
258 : fXOffset{X(offset)}, fYOffset{Y(offset)} 258 : fXOffset{X(offset)}, fYOffset{Y(offset)}
259 , fXScale{X(scale)}, fYScale{Y(scale)} 259 , fXScale{X(scale)}, fYScale{Y(scale)}
260 , fXSkew{X(skew)}, fYSkew{Y(skew)} { } 260 , fXSkew{X(skew)}, fYSkew{Y(skew)} { }
261 void processPoints(Sk4f* xs, Sk4f* ys) { 261 void processPoints(Sk4s* xs, Sk4s* ys) {
262 Sk4f newXs = fXScale * *xs + fXSkew * *ys + fXOffset; 262 Sk4s newXs = fXScale * *xs + fXSkew * *ys + fXOffset;
263 Sk4f newYs = fYSkew * *xs + fYScale * *ys + fYOffset; 263 Sk4s newYs = fYSkew * *xs + fYScale * *ys + fYOffset;
264 264
265 *xs = newXs; 265 *xs = newXs;
266 *ys = newYs; 266 *ys = newYs;
267 } 267 }
268 268
269 template <typename Next> 269 template <typename Next>
270 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 270 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
271 return false; 271 return false;
272 } 272 }
273 273
274 private: 274 private:
275 const Sk4f fXOffset, fYOffset; 275 const Sk4s fXOffset, fYOffset;
276 const Sk4f fXScale, fYScale; 276 const Sk4s fXScale, fYScale;
277 const Sk4f fXSkew, fYSkew; 277 const Sk4s fXSkew, fYSkew;
278 }; 278 };
279 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> 279 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface>
280 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; 280 using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>;
281 281
282 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( 282 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix(
283 SkLinearBitmapPipeline::PointProcessorInterface* next, 283 SkLinearBitmapPipeline::PointProcessorInterface* next,
284 const SkMatrix& inverse, 284 const SkMatrix& inverse,
285 SkLinearBitmapPipeline::MatrixStage* matrixProc) { 285 SkLinearBitmapPipeline::MatrixStage* matrixProc) {
286 if (inverse.hasPerspective()) { 286 if (inverse.hasPerspective()) {
287 SkFAIL("Not implemented."); 287 SkFAIL("Not implemented.");
(...skipping 17 matching lines...) Expand all
305 return next; 305 return next;
306 } 306 }
307 return matrixProc->get(); 307 return matrixProc->get();
308 } 308 }
309 309
310 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 310 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
311 class ExpandBilerp final : public SkLinearBitmapPipeline::PointProcessorInterfac e { 311 class ExpandBilerp final : public SkLinearBitmapPipeline::PointProcessorInterfac e {
312 public: 312 public:
313 ExpandBilerp(Next* next) : fNext{next} { } 313 ExpandBilerp(Next* next) : fNext{next} { }
314 314
315 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 315 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
316 SkASSERT(0 < n && n < 4); 316 SkASSERT(0 < n && n < 4);
317 // px00 px10 px01 px11 317 // px00 px10 px01 px11
318 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, 318 const Sk4s kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f},
319 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; 319 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f};
320 if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYO ffsets); 320 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); 321 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); 322 if (n >= 3) fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYO ffsets);
323 } 323 }
324 324
325 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 325 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override {
326 // px00 px10 px01 px11 326 // px00 px10 px01 px11
327 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, 327 const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f},
328 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; 328 kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f};
329 fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); 329 fNext->bilerpList(Sk4s{xs[0]} + kXOffsets, Sk4s{ys[0]} + kYOffsets);
330 fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); 330 fNext->bilerpList(Sk4s{xs[1]} + kXOffsets, Sk4s{ys[1]} + kYOffsets);
331 fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); 331 fNext->bilerpList(Sk4s{xs[2]} + kXOffsets, Sk4s{ys[2]} + kYOffsets);
332 fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); 332 fNext->bilerpList(Sk4s{xs[3]} + kXOffsets, Sk4s{ys[3]} + kYOffsets);
333 } 333 }
334 334
335 void pointSpan(SkPoint start, SkScalar length, int count) override { 335 void pointSpan(SkPoint start, SkScalar length, int count) override {
336 span_fallback(start, length, count, this); 336 span_fallback(start, length, count, this);
337 } 337 }
338 338
339 private: 339 private:
340 Next* const fNext; 340 Next* const fNext;
341 }; 341 };
342 342
(...skipping 17 matching lines...) Expand all
360 , fXMax{max - 1.0f} { } 360 , fXMax{max - 1.0f} { }
361 ClampStrategy(Y max) 361 ClampStrategy(Y max)
362 : fYMin{0.0f} 362 : fYMin{0.0f}
363 , fYMax{max - 1.0f} { } 363 , fYMax{max - 1.0f} { }
364 ClampStrategy(SkSize max) 364 ClampStrategy(SkSize max)
365 : fXMin{0.0f} 365 : fXMin{0.0f}
366 , fYMin{0.0f} 366 , fYMin{0.0f}
367 , fXMax{X(max) - 1.0f} 367 , fXMax{X(max) - 1.0f}
368 , fYMax{Y(max) - 1.0f} { } 368 , fYMax{Y(max) - 1.0f} { }
369 369
370 void processPoints(Sk4f* xs, Sk4f* ys) { 370 void processPoints(Sk4s* xs, Sk4s* ys) {
371 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); 371 *xs = Sk4s::Min(Sk4s::Max(*xs, fXMin), fXMax);
372 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); 372 *ys = Sk4s::Min(Sk4s::Max(*ys, fYMin), fYMax);
373 } 373 }
374 374
375 template <typename Next> 375 template <typename Next>
376 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 376 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
377 return false; 377 SkScalar xMin = fXMin[0];
378 SkScalar xMax = fXMax[0];
379 SkScalar yMin = fYMin[0];
380 SkScalar yMax = fYMax[0];
381 SkScalar x = X(start);
382 SkScalar y = std::min(std::max<float>(yMin, Y(start)), yMax);
383
384 bool under = x < xMin;
385
386 if (!under && x + length < xMax) {
387 next->pointSpan(start, length, count);
388 return true;
389 }
390
391 SkScalar dx = length / (count - 1);
392
393 // A B C
394 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
395 // | *---*|---*---|*---*--||-*---*-|---*---|*---...| |--*---*|---*- --||*---*....
396 // | | | || | | | ... | | ||
397 // | | | || | | | | | ||
398 // +-------+-------+-------++-------+-------+-------+ +-------+----- --++------
399 // ^ ^
400 // | xMin xMax- 1 | xMax
401 //
402 // *---*---*---... - track of samples. * = sample
403 //
404 // +-+ ||
405 // | | - pixels in source space. || - tile border.
406 // +-+ ||
407 //
408 // The length from A to B is the length in source space or 4 * dx ((coun t - 1) * dx)
mtklein 2016/02/23 23:49:57 4 * dx ((count - 1) * dx) reads like one expressio
herb_g 2016/02/24 18:16:06 Done.
409 // where dx is the distance between samples. There are 5 pixels specifie d in the A, B
mtklein 2016/02/23 23:49:57 There are 5 destination pixels ... ? Or 5 samples
herb_g 2016/02/24 18:16:06 Add explanation.
410 // span. The distance from A to the next span starting at C is 5 * dx, s o count * dx.
411 // Overall Strategy:
412 // * Under - for portions of the span < xMin, take the color at pixel {x Min, y} and use it
413 // to fill in the 5 pixel sampled from A to B.
414 // * Middle - for the portion of the span between xMin and xMax sample n ormally.
415 // * Over - for the portion of the span > xMax, take the color at pixel {xMax-1, y} and
416 // use it to fill in the rest of the destination pixels.
417 if (under) {
418 // It could be that the entire span is off the left edge of the tile .
419 SkScalar EdgeOrXEnd = std::min(xMin, x + length + 1.0f);
420 int underCount = SkScalarFloorToInt((EdgeOrXEnd - x) / dx) + 1;
421 if (underCount > 0) {
422 // Use the pixel on the edge of the bitmap as the color for the entire span.
423 // Using a length of 0 causes x not to move in the sampler resul ting in the same
424 // pixel being used for the entire span.
425 next->pointSpan({xMin, y}, 0.0f, underCount);
426
427 // The length is not the distance to xMin, but to the next start ing sample.
428 SkScalar lengthToNextStart = dx * underCount;
429 count -= underCount;
430 length -= lengthToNextStart;
431 x += lengthToNextStart;
432 }
433 }
434
435 // If there are more pixels needed, sample from the middle of the tile.
436 if (count > 0) {
437 // It could be that span continues off the edge of tile; use min for the limit.
438 SkScalar EdgeOrXEnd = std::min(xMax, x + length);
439 int middleCount = SkScalarFloorToInt((EdgeOrXEnd - x) / dx) + 1;
440 SkScalar middleLength = (middleCount - 1) * dx;
441 next->pointSpan({x, y}, middleLength, middleCount);
442 count -= middleCount;
443 }
444
445 if (count > 0) {
446 // Use the pixel on the edge of the bitmap as the color for the enti re span.
447 // Using a length of 0 causes x not to move in the sampler resulting in the same
448 // pixel being used for the entire span.
449 next->pointSpan({xMax - 1.0f, y}, 0.0f, count);
450 }
451
452 return true;
378 } 453 }
379 454
380 private: 455 private:
381 const Sk4f fXMin{SK_FloatNegativeInfinity}; 456 const Sk4s fXMin{SK_FloatNegativeInfinity};
382 const Sk4f fYMin{SK_FloatNegativeInfinity}; 457 const Sk4s fYMin{SK_FloatNegativeInfinity};
383 const Sk4f fXMax{SK_FloatInfinity}; 458 const Sk4s fXMax{SK_FloatInfinity};
384 const Sk4f fYMax{SK_FloatInfinity}; 459 const Sk4s fYMax{SK_FloatInfinity};
385 }; 460 };
386 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 461 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
387 using Clamp = BilerpProcessor<ClampStrategy, Next>; 462 using Clamp = BilerpProcessor<ClampStrategy, Next>;
388 463
464 // It would be nice to use fmod, but it uses trunc based rounding where floor ro unding is needed.
465 static SkScalar tile_mod(SkScalar x, SkScalar base) {
466 return x - std::floor(x / base) * base;
467 }
468
389 class RepeatStrategy { 469 class RepeatStrategy {
390 public: 470 public:
391 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } 471 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { }
392 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } 472 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { }
393 RepeatStrategy(SkSize max) 473 RepeatStrategy(SkSize max)
394 : fXMax{X(max)} 474 : fXMax{X(max)}
395 , fXInvMax{1.0f / X(max)} 475 , fXInvMax{1.0f / X(max)}
396 , fYMax{Y(max)} 476 , fYMax{Y(max)}
397 , fYInvMax{1.0f / Y(max)} { } 477 , fYInvMax{1.0f / Y(max)} { }
398 478
399 void processPoints(Sk4f* xs, Sk4f* ys) { 479 void processPoints(Sk4s* xs, Sk4s* ys) {
400 Sk4f divX = (*xs * fXInvMax).floor(); 480 Sk4s divX = (*xs * fXInvMax).floor();
401 Sk4f divY = (*ys * fYInvMax).floor(); 481 Sk4s divY = (*ys * fYInvMax).floor();
402 Sk4f baseX = (divX * fXMax); 482 Sk4s baseX = (divX * fXMax);
403 Sk4f baseY = (divY * fYMax); 483 Sk4s baseY = (divY * fYMax);
404 *xs = *xs - baseX; 484 *xs = *xs - baseX;
405 *ys = *ys - baseY; 485 *ys = *ys - baseY;
406 } 486 }
407 487
408 template <typename Next> 488 template <typename Next>
409 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { 489 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) {
410 return false; 490 // Make x and y in range on the tile.
491 SkScalar x = tile_mod(X(start), fXMax[0]);
492 SkScalar y = tile_mod(Y(start), fYMax[0]);
493 SkScalar xMax = fXMax[0];
494 SkScalar dx = length / (count - 1);
495
496 // A B C D Z
497 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
498 // | | *---|*---*--||-*---*-|---*---|*---*--|| |--*---*| ||
499 // | | | || | | || ... | | ||
500 // | | | || | | || | | ||
501 // +-------+-------+-------++-------+-------+-------++ +-------+---- ---++------
502 // ^^ ^^ ^^
503 // xMax || xMin xMax || xMin xM ax || xMin
504 //
505 // *---*---*---... - track of samples. * = sample
506 //
507 // +-+ ||
508 // | | - pixels in source space. || - tile border.
509 // +-+ ||
510 //
511 //
512 // The given span starts at A and continues on through several tiles to sample point Z.
513 // The idea is to break this into several spans one on each tile the ent ire span
514 // intersects. The A to B span only covers a partial tile and has a coun t of 3 and the
515 // distance from A to B is (count - 1) * dx or 2 * dx. The distance from A to the start of
516 // the next span is count * dx or 3 * dx. Span C to D covers an entire t ile has a count
517 // of 5 and a length of 4 * dx.
518 //
519 // Overall Strategy:
520 // While the span hangs over the edge of the tile. Draw the span coverin g the tile then
mtklein 2016/02/23 23:49:57 While the span hangs over the edge of the tile. ?
herb_g 2016/02/24 18:16:06 Fixed sentence fragment.
521 // slide the span over to the next tile.
522
523 // The guard could have been count > 0, but then a bunch of math would b e done in the
524 // common case.
525 while (x + length > xMax) {
526 // The number of samples that intersect this tile.
527 int countForTile = SkScalarFloorToInt((xMax - x) / dx) + 1;
528 // The distance between the first and last sample.
529 SkScalar lengthForSpanOnTile = (countForTile - 1) * dx;
530 // Span the samples.
531 next->pointSpan({x, y}, lengthForSpanOnTile, countForTile);
532 // Add one more dx to get to the first sample on the next tile.
533 SkScalar lengthToNextStart = lengthForSpanOnTile + dx;
534 // slide over to the next tile.
535 length -= lengthToNextStart;
536 count -= countForTile;
537 x += lengthToNextStart - xMax;
538 }
539 // All on a single tile.
540 if (count > 0) {
541 next->pointSpan({x, y}, length, count);
542 }
543
544 return true;
411 } 545 }
412 546
413 private: 547 private:
414 const Sk4f fXMax{0.0f}; 548 const Sk4s fXMax{0.0f};
415 const Sk4f fXInvMax{0.0f}; 549 const Sk4s fXInvMax{0.0f};
416 const Sk4f fYMax{0.0f}; 550 const Sk4s fYMax{0.0f};
417 const Sk4f fYInvMax{0.0f}; 551 const Sk4s fYInvMax{0.0f};
418 }; 552 };
419 553
420 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> 554 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface>
421 using Repeat = BilerpProcessor<RepeatStrategy, Next>; 555 using Repeat = BilerpProcessor<RepeatStrategy, Next>;
422 556
423 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler( 557 static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler(
424 SkLinearBitmapPipeline::BilerpProcessorInterface* next, 558 SkLinearBitmapPipeline::BilerpProcessorInterface* next,
425 SkSize dimensions, 559 SkSize dimensions,
426 SkShader::TileMode xMode, 560 SkShader::TileMode xMode,
427 SkShader::TileMode yMode, 561 SkShader::TileMode yMode,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 case SkShader::kMirror_TileMode: 596 case SkShader::kMirror_TileMode:
463 SkFAIL("Not implemented."); 597 SkFAIL("Not implemented.");
464 break; 598 break;
465 } 599 }
466 } 600 }
467 return tileProcXOrBoth->get(); 601 return tileProcXOrBoth->get();
468 } 602 }
469 603
470 class sRGBFast { 604 class sRGBFast {
471 public: 605 public:
472 static Sk4f VECTORCALL sRGBToLinear(Sk4f pixel) { 606 static Sk4s VECTORCALL sRGBToLinear(Sk4s pixel) {
473 Sk4f l = pixel * pixel; 607 Sk4s l = pixel * pixel;
474 return Sk4f{l[0], l[1], l[2], pixel[3]}; 608 return Sk4s{l[0], l[1], l[2], pixel[3]};
475 } 609 }
476 }; 610 };
477 611
478 template <SkColorProfileType colorProfile> 612 template <SkColorProfileType colorProfile>
479 class Passthrough8888 { 613 class Passthrough8888 {
480 public: 614 public:
481 Passthrough8888(int width, const uint32_t* src) 615 Passthrough8888(int width, const uint32_t* src)
482 : fSrc{src}, fWidth{width}{ } 616 : fSrc{src}, fWidth{width}{ }
483 617
484 void VECTORCALL getFewPixels(int n, Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { 618 void VECTORCALL getFewPixels(int n, Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) {
485 Sk4i XIs = SkNx_cast<int, float>(xs); 619 Sk4i XIs = SkNx_cast<int, float>(xs);
486 Sk4i YIs = SkNx_cast<int, float>(ys); 620 Sk4i YIs = SkNx_cast<int, float>(ys);
487 Sk4i bufferLoc = YIs * fWidth + XIs; 621 Sk4i bufferLoc = YIs * fWidth + XIs;
488 switch (n) { 622 switch (n) {
489 case 3: 623 case 3:
490 *px2 = getPixel(fSrc, bufferLoc[2]); 624 *px2 = getPixel(fSrc, bufferLoc[2]);
491 case 2: 625 case 2:
492 *px1 = getPixel(fSrc, bufferLoc[1]); 626 *px1 = getPixel(fSrc, bufferLoc[1]);
493 case 1: 627 case 1:
494 *px0 = getPixel(fSrc, bufferLoc[0]); 628 *px0 = getPixel(fSrc, bufferLoc[0]);
495 default: 629 default:
496 break; 630 break;
497 } 631 }
498 } 632 }
499 633
500 void VECTORCALL get4Pixels(Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) { 634 void VECTORCALL get4Pixels(Sk4s xs, Sk4s ys, Sk4f* px0, Sk4f* px1, Sk4f* px2 , Sk4f* px3) {
501 Sk4i XIs = SkNx_cast<int, float>(xs); 635 Sk4i XIs = SkNx_cast<int, float>(xs);
502 Sk4i YIs = SkNx_cast<int, float>(ys); 636 Sk4i YIs = SkNx_cast<int, float>(ys);
503 Sk4i bufferLoc = YIs * fWidth + XIs; 637 Sk4i bufferLoc = YIs * fWidth + XIs;
504 *px0 = getPixel(fSrc, bufferLoc[0]); 638 *px0 = getPixel(fSrc, bufferLoc[0]);
505 *px1 = getPixel(fSrc, bufferLoc[1]); 639 *px1 = getPixel(fSrc, bufferLoc[1]);
506 *px2 = getPixel(fSrc, bufferLoc[2]); 640 *px2 = getPixel(fSrc, bufferLoc[2]);
507 *px3 = getPixel(fSrc, bufferLoc[3]); 641 *px3 = getPixel(fSrc, bufferLoc[3]);
508 } 642 }
509 643
510 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; } 644 const uint32_t* row(int y) { return fSrc + y * fWidth[0]; }
(...skipping 25 matching lines...) Expand all
536 // +--------+--------+ 670 // +--------+--------+
537 // 671 //
538 // 672 //
539 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x 673 // Given a pixelxy each is multiplied by a different factor derived from the fra ctional part of x
540 // and y: 674 // and y:
541 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy 675 // * px00 -> (1 - x)(1 - y) = 1 - x - y + xy
542 // * px10 -> x(1 - y) = x - xy 676 // * px10 -> x(1 - y) = x - xy
543 // * px01 -> (1 - x)y = y - xy 677 // * px01 -> (1 - x)y = y - xy
544 // * px11 -> xy 678 // * px11 -> xy
545 // So x * y is calculated first and then used to calculate all the other factors . 679 // 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, 680 static Sk4s VECTORCALL bilerp4(Sk4s xs, Sk4s ys, Sk4f px00, Sk4f px10,
547 Sk4f px01, Sk4f px11) { 681 Sk4f px01, Sk4f px11) {
548 // Calculate fractional xs and ys. 682 // Calculate fractional xs and ys.
549 Sk4f fxs = xs - xs.floor(); 683 Sk4s fxs = xs - xs.floor();
550 Sk4f fys = ys - ys.floor(); 684 Sk4s fys = ys - ys.floor();
551 Sk4f fxys{fxs * fys}; 685 Sk4s fxys{fxs * fys};
552 Sk4f sum = px11 * fxys; 686 Sk4f sum = px11 * fxys;
553 sum = sum + px01 * (fys - fxys); 687 sum = sum + px01 * (fys - fxys);
554 sum = sum + px10 * (fxs - fxys); 688 sum = sum + px10 * (fxs - fxys);
555 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys); 689 sum = sum + px00 * (Sk4f{1.0f} - fxs - fys + fxys);
556 return sum; 690 return sum;
557 } 691 }
558 692
559 template <typename SourceStrategy> 693 template <typename SourceStrategy>
560 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface { 694 class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface {
561 public: 695 public:
562 template <typename... Args> 696 template <typename... Args>
563 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args) 697 Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args)
564 : fNext{next} 698 : fNext{next}
565 , fStrategy{std::forward<Args>(args)...} { } 699 , fStrategy{std::forward<Args>(args)...} { }
566 700
567 void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { 701 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
568 SkASSERT(0 < n && n < 4); 702 SkASSERT(0 < n && n < 4);
569 Sk4f px0, px1, px2; 703 Sk4f px0, px1, px2;
570 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); 704 fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2);
571 if (n >= 1) fNext->placePixel(px0); 705 if (n >= 1) fNext->placePixel(px0);
572 if (n >= 2) fNext->placePixel(px1); 706 if (n >= 2) fNext->placePixel(px1);
573 if (n >= 3) fNext->placePixel(px2); 707 if (n >= 3) fNext->placePixel(px2);
574 } 708 }
575 709
576 void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { 710 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
577 Sk4f px0, px1, px2, px3; 711 Sk4f px0, px1, px2, px3;
578 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); 712 fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3);
579 fNext->place4Pixels(px0, px1, px2, px3); 713 fNext->place4Pixels(px0, px1, px2, px3);
580 } 714 }
581 715
582 void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { 716 void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) override {
583 Sk4f px00, px10, px01, px11; 717 Sk4f px00, px10, px01, px11;
584 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); 718 fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11);
585 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); 719 Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11);
586 fNext->placePixel(pixel); 720 fNext->placePixel(pixel);
587 } 721 }
588 722
589 void pointSpan(SkPoint start, SkScalar length, int count) override { 723 void pointSpan(SkPoint start, SkScalar length, int count) override {
590 span_fallback(start, length, count, this); 724 span_fallback(start, length, count, this);
591 } 725 }
592 726
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp leStage); 824 auto samplerStage = choose_pixel_sampler(placementStage, srcPixmap, &fSamp leStage);
691 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage, 825 auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileX OrBothStage,
692 &fTileYStage); 826 &fTileYStage);
693 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage ); 827 auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage );
694 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); 828 fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage);
695 } 829 }
696 830
697 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { 831 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
698 SkASSERT(count > 0); 832 SkASSERT(count > 0);
699 fPixelStage->setDestination(dst); 833 fPixelStage->setDestination(dst);
700 // Adjust points by 0.5, 0.5 to sample from the center of the pixels. 834 // The count and length arguments start out in a precise relation in order t o keep the
701 if (count == 1) { 835 // 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}); 836 // Since the code samples at pixel centers, length is the distance from the center of the
703 } else { 837 // 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 838 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 } 839 }
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