OLD | NEW |
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 | 9 |
10 #include "SkPM4f.h" | 10 #include "SkPM4f.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 // A span represents sample points that have been mapped from destination sp
ace to source | 58 // A span represents sample points that have been mapped from destination sp
ace to source |
59 // space. Each sample point is then expanded to the four bilerp points by ad
d +/- 0.5. The | 59 // space. Each sample point is then expanded to the four bilerp points by ad
d +/- 0.5. The |
60 // resulting Y values my be off the tile. When y +/- 0.5 are more than 1 apa
rt because of | 60 // resulting Y values my be off the tile. When y +/- 0.5 are more than 1 apa
rt because of |
61 // tiling, the second Y is used to denote the retiled Y value. | 61 // tiling, the second Y is used to denote the retiled Y value. |
62 virtual void bilerpSpan(Span span, SkScalar y) = 0; | 62 virtual void bilerpSpan(Span span, SkScalar y) = 0; |
63 }; | 63 }; |
64 | 64 |
65 class SkLinearBitmapPipeline::DestinationInterface { | 65 class SkLinearBitmapPipeline::DestinationInterface { |
66 public: | 66 public: |
67 virtual ~DestinationInterface() { } | 67 virtual ~DestinationInterface() { } |
68 virtual void setDestination(void* dst, int count) = 0; | |
69 }; | |
70 | |
71 class SkLinearBitmapPipeline::PixelPlacerInterface | |
72 : public SkLinearBitmapPipeline::DestinationInterface { | |
73 public: | |
74 virtual ~PixelPlacerInterface() { } | |
75 // Count is normally not needed, but in these early stages of development it
is useful to | 68 // Count is normally not needed, but in these early stages of development it
is useful to |
76 // check bounds. | 69 // check bounds. |
77 // TODO(herb): 4/6/2016 - remove count when code is stable. | 70 // TODO(herb): 4/6/2016 - remove count when code is stable. |
78 virtual void setDestination(void* dst, int count) = 0; | 71 virtual void setDestination(void* dst, int count) = 0; |
79 virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; | |
80 virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0
; | |
81 }; | 72 }; |
82 | 73 |
| 74 class SkLinearBitmapPipeline::BlendProcessorInterface |
| 75 : public SkLinearBitmapPipeline::DestinationInterface { |
| 76 public: |
| 77 virtual void VECTORCALL blendPixel(Sk4f pixel0) = 0; |
| 78 virtual void VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0
; |
| 79 }; |
| 80 |
| 81 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 82 // SkLinearBitmapPipeline::Stage |
| 83 template<typename Base, size_t kSize, typename Next> |
| 84 SkLinearBitmapPipeline::Stage<Base, kSize, Next>::~Stage() { |
| 85 if (fIsInitialized) { |
| 86 this->get()->~Base(); |
| 87 } |
| 88 } |
| 89 |
| 90 template<typename Base, size_t kSize, typename Next> |
| 91 template<typename Variant, typename... Args> |
| 92 void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initStage(Next* next, Arg
s&& ... args) { |
| 93 SkASSERTF(sizeof(Variant) <= sizeof(fSpace), |
| 94 "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace)); |
| 95 |
| 96 new (&fSpace) Variant(next, std::forward<Args>(args)...); |
| 97 fStageCloner = [this](Next* nextClone, void* addr) { |
| 98 new (addr) Variant(nextClone, (const Variant&)*this->get()); |
| 99 }; |
| 100 fIsInitialized = true; |
| 101 }; |
| 102 |
| 103 template<typename Base, size_t kSize, typename Next> |
| 104 template<typename Variant, typename... Args> |
| 105 void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initSink(Args&& ... args)
{ |
| 106 SkASSERTF(sizeof(Variant) <= sizeof(fSpace), |
| 107 "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace)); |
| 108 new (&fSpace) Variant(std::forward<Args>(args)...); |
| 109 fIsInitialized = true; |
| 110 }; |
| 111 |
| 112 template<typename Base, size_t kSize, typename Next> |
| 113 template <typename To, typename From> |
| 114 To* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::getInterface() { |
| 115 From* down = static_cast<From*>(this->get()); |
| 116 return static_cast<To*>(down); |
| 117 } |
| 118 |
| 119 template<typename Base, size_t kSize, typename Next> |
| 120 Base* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::cloneStageTo( |
| 121 Next* next, Stage* cloneToStage) const |
| 122 { |
| 123 if (!fIsInitialized) return nullptr; |
| 124 fStageCloner(next, &cloneToStage->fSpace); |
| 125 return cloneToStage->get(); |
| 126 } |
| 127 |
83 namespace { | 128 namespace { |
84 | 129 |
85 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 130 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
86 // Matrix Stage | 131 // Matrix Stage |
87 // PointProcessor uses a strategy to help complete the work of the different sta
ges. The strategy | 132 // PointProcessor uses a strategy to help complete the work of the different sta
ges. The strategy |
88 // must implement the following methods: | 133 // must implement the following methods: |
89 // * processPoints(xs, ys) - must mutate the xs and ys for the stage. | 134 // * processPoints(xs, ys) - must mutate the xs and ys for the stage. |
90 // * maybeProcessSpan(span, next) - This represents a horizontal series of pixel
s | 135 // * maybeProcessSpan(span, next) - This represents a horizontal series of pixel
s |
91 // to work over. | 136 // to work over. |
92 // span - encapsulation of span. | 137 // span - encapsulation of span. |
93 // next - a pointer to the next stage. | 138 // next - a pointer to the next stage. |
94 // maybeProcessSpan - returns false if it can not process the span and needs t
o fallback to | 139 // maybeProcessSpan - returns false if it can not process the span and needs t
o fallback to |
95 // point lists for processing. | 140 // point lists for processing. |
96 template<typename Strategy, typename Next> | 141 template<typename Strategy, typename Next> |
97 class MatrixStage final : public SkLinearBitmapPipeline::PointProcessorInterface
{ | 142 class MatrixStage final : public SkLinearBitmapPipeline::PointProcessorInterface
{ |
98 public: | 143 public: |
99 template <typename... Args> | 144 template <typename... Args> |
100 MatrixStage(Next* next, Args&&... args) | 145 MatrixStage(Next* next, Args&&... args) |
101 : fNext{next} | 146 : fNext{next} |
102 , fStrategy{std::forward<Args>(args)...}{ } | 147 , fStrategy{std::forward<Args>(args)...}{ } |
103 | 148 |
| 149 MatrixStage(Next* next, const MatrixStage& stage) |
| 150 : fNext{next} |
| 151 , fStrategy{stage.fStrategy} { } |
| 152 |
104 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | 153 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
105 fStrategy.processPoints(&xs, &ys); | 154 fStrategy.processPoints(&xs, &ys); |
106 fNext->pointListFew(n, xs, ys); | 155 fNext->pointListFew(n, xs, ys); |
107 } | 156 } |
108 | 157 |
109 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { | 158 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
110 fStrategy.processPoints(&xs, &ys); | 159 fStrategy.processPoints(&xs, &ys); |
111 fNext->pointList4(xs, ys); | 160 fNext->pointList4(xs, ys); |
112 } | 161 } |
113 | 162 |
(...skipping 21 matching lines...) Expand all Loading... |
135 | 184 |
136 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> | 185 template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> |
137 using PerspectiveMatrix = MatrixStage<PerspectiveMatrixStrategy, Next>; | 186 using PerspectiveMatrix = MatrixStage<PerspectiveMatrixStrategy, Next>; |
138 | 187 |
139 | 188 |
140 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( | 189 static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( |
141 SkLinearBitmapPipeline::PointProcessorInterface* next, | 190 SkLinearBitmapPipeline::PointProcessorInterface* next, |
142 const SkMatrix& inverse, | 191 const SkMatrix& inverse, |
143 SkLinearBitmapPipeline::MatrixStage* matrixProc) { | 192 SkLinearBitmapPipeline::MatrixStage* matrixProc) { |
144 if (inverse.hasPerspective()) { | 193 if (inverse.hasPerspective()) { |
145 matrixProc->Initialize<PerspectiveMatrix<>>( | 194 matrixProc->initStage<PerspectiveMatrix<>>( |
146 next, | 195 next, |
147 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, | 196 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
148 SkVector{inverse.getScaleX(), inverse.getScaleY()}, | 197 SkVector{inverse.getScaleX(), inverse.getScaleY()}, |
149 SkVector{inverse.getSkewX(), inverse.getSkewY()}, | 198 SkVector{inverse.getSkewX(), inverse.getSkewY()}, |
150 SkVector{inverse.getPerspX(), inverse.getPerspY()}, | 199 SkVector{inverse.getPerspX(), inverse.getPerspY()}, |
151 inverse.get(SkMatrix::kMPersp2)); | 200 inverse.get(SkMatrix::kMPersp2)); |
152 } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) { | 201 } else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) { |
153 matrixProc->Initialize<AffineMatrix<>>( | 202 matrixProc->initStage<AffineMatrix<>>( |
154 next, | 203 next, |
155 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, | 204 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
156 SkVector{inverse.getScaleX(), inverse.getScaleY()}, | 205 SkVector{inverse.getScaleX(), inverse.getScaleY()}, |
157 SkVector{inverse.getSkewX(), inverse.getSkewY()}); | 206 SkVector{inverse.getSkewX(), inverse.getSkewY()}); |
158 } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) { | 207 } else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) { |
159 matrixProc->Initialize<ScaleMatrix<>>( | 208 matrixProc->initStage<ScaleMatrix<>>( |
160 next, | 209 next, |
161 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, | 210 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
162 SkVector{inverse.getScaleX(), inverse.getScaleY()}); | 211 SkVector{inverse.getScaleX(), inverse.getScaleY()}); |
163 } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0
f) { | 212 } else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0
f) { |
164 matrixProc->Initialize<TranslateMatrix<>>( | 213 matrixProc->initStage<TranslateMatrix<>>( |
165 next, | 214 next, |
166 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); | 215 SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); |
167 } else { | 216 } else { |
168 return next; | 217 return next; |
169 } | 218 } |
170 return matrixProc->get(); | 219 return matrixProc->get(); |
171 } | 220 } |
172 | 221 |
173 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 222 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
174 // Tile Stage | 223 // Tile Stage |
175 | 224 |
176 template<typename XStrategy, typename YStrategy, typename Next> | 225 template<typename XStrategy, typename YStrategy, typename Next> |
177 class NearestTileStage final : public SkLinearBitmapPipeline::PointProcessorInte
rface { | 226 class NearestTileStage final : public SkLinearBitmapPipeline::PointProcessorInte
rface { |
178 public: | 227 public: |
179 template <typename... Args> | 228 template <typename... Args> |
180 NearestTileStage(Next* next, SkISize dimensions) | 229 NearestTileStage(Next* next, SkISize dimensions) |
181 : fNext{next} | 230 : fNext{next} |
182 , fXStrategy{dimensions.width()} | 231 , fXStrategy{dimensions.width()} |
183 , fYStrategy{dimensions.height()}{ } | 232 , fYStrategy{dimensions.height()}{ } |
184 | 233 |
| 234 NearestTileStage(Next* next, const NearestTileStage& stage) |
| 235 : fNext{next} |
| 236 , fXStrategy{stage.fXStrategy} |
| 237 , fYStrategy{stage.fYStrategy} { } |
| 238 |
185 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | 239 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
186 fXStrategy.tileXPoints(&xs); | 240 fXStrategy.tileXPoints(&xs); |
187 fYStrategy.tileYPoints(&ys); | 241 fYStrategy.tileYPoints(&ys); |
188 fNext->pointListFew(n, xs, ys); | 242 fNext->pointListFew(n, xs, ys); |
189 } | 243 } |
190 | 244 |
191 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { | 245 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
192 fXStrategy.tileXPoints(&xs); | 246 fXStrategy.tileXPoints(&xs); |
193 fYStrategy.tileYPoints(&ys); | 247 fYStrategy.tileYPoints(&ys); |
194 fNext->pointList4(xs, ys); | 248 fNext->pointList4(xs, ys); |
(...skipping 16 matching lines...) Expand all Loading... |
211 Next* const fNext; | 265 Next* const fNext; |
212 XStrategy fXStrategy; | 266 XStrategy fXStrategy; |
213 YStrategy fYStrategy; | 267 YStrategy fYStrategy; |
214 }; | 268 }; |
215 | 269 |
216 template<typename XStrategy, typename YStrategy, typename Next> | 270 template<typename XStrategy, typename YStrategy, typename Next> |
217 class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInter
face { | 271 class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInter
face { |
218 public: | 272 public: |
219 template <typename... Args> | 273 template <typename... Args> |
220 BilerpTileStage(Next* next, SkISize dimensions) | 274 BilerpTileStage(Next* next, SkISize dimensions) |
221 : fXMax(dimensions.width()) | 275 : fNext{next} |
| 276 , fXMax(dimensions.width()) |
222 , fYMax(dimensions.height()) | 277 , fYMax(dimensions.height()) |
223 , fNext{next} | |
224 , fXStrategy{dimensions.width()} | 278 , fXStrategy{dimensions.width()} |
225 , fYStrategy{dimensions.height()}{ } | 279 , fYStrategy{dimensions.height()} { } |
| 280 |
| 281 BilerpTileStage(Next* next, const BilerpTileStage& stage) |
| 282 : fNext{next} |
| 283 , fXMax{stage.fXMax} |
| 284 , fYMax{stage.fYMax} |
| 285 , fXStrategy{stage.fXStrategy} |
| 286 , fYStrategy{stage.fYStrategy} { } |
226 | 287 |
227 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | 288 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
228 fXStrategy.tileXPoints(&xs); | 289 fXStrategy.tileXPoints(&xs); |
229 fYStrategy.tileYPoints(&ys); | 290 fYStrategy.tileYPoints(&ys); |
230 // TODO: check to see if xs and ys are in range then just call pointList
Few on next. | 291 // TODO: check to see if xs and ys are in range then just call pointList
Few on next. |
231 if (n >= 1) this->bilerpPoint(xs[0], ys[0]); | 292 if (n >= 1) this->bilerpPoint(xs[0], ys[0]); |
232 if (n >= 2) this->bilerpPoint(xs[1], ys[1]); | 293 if (n >= 2) this->bilerpPoint(xs[1], ys[1]); |
233 if (n >= 3) this->bilerpPoint(xs[2], ys[2]); | 294 if (n >= 3) this->bilerpPoint(xs[2], ys[2]); |
234 } | 295 } |
235 | 296 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 this->yProcessSpan(center); | 393 this->yProcessSpan(center); |
333 } | 394 } |
334 if (!leftEdge.isEmpty()) { | 395 if (!leftEdge.isEmpty()) { |
335 this->handleEdges(leftEdge, dx); | 396 this->handleEdges(leftEdge, dx); |
336 } | 397 } |
337 | 398 |
338 } | 399 } |
339 } | 400 } |
340 } | 401 } |
341 | 402 |
| 403 Next* const fNext; |
342 SkScalar fXMax; | 404 SkScalar fXMax; |
343 SkScalar fYMax; | 405 SkScalar fYMax; |
344 Next* const fNext; | |
345 XStrategy fXStrategy; | 406 XStrategy fXStrategy; |
346 YStrategy fYStrategy; | 407 YStrategy fYStrategy; |
347 }; | 408 }; |
348 | 409 |
349 template <typename XStrategy, typename YStrategy, typename Next> | 410 template <typename XStrategy, typename YStrategy, typename Next> |
350 void make_tile_stage( | 411 void make_tile_stage( |
351 SkFilterQuality filterQuality, SkISize dimensions, | 412 SkFilterQuality filterQuality, SkISize dimensions, |
352 Next* next, SkLinearBitmapPipeline::TileStage* tileStage) { | 413 Next* next, SkLinearBitmapPipeline::TileStage* tileStage) { |
353 if (filterQuality == kNone_SkFilterQuality) { | 414 if (filterQuality == kNone_SkFilterQuality) { |
354 tileStage->Initialize<NearestTileStage<XStrategy, YStrategy, Next>>(next
, dimensions); | 415 tileStage->initStage<NearestTileStage<XStrategy, YStrategy, Next>>(next,
dimensions); |
355 } else { | 416 } else { |
356 tileStage->Initialize<BilerpTileStage<XStrategy, YStrategy, Next>>(next,
dimensions); | 417 tileStage->initStage<BilerpTileStage<XStrategy, YStrategy, Next>>(next,
dimensions); |
357 } | 418 } |
358 } | 419 } |
359 template <typename XStrategy> | 420 template <typename XStrategy> |
360 void choose_tiler_ymode( | 421 void choose_tiler_ymode( |
361 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions, | 422 SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions, |
362 SkLinearBitmapPipeline::SampleProcessorInterface* next, | 423 SkLinearBitmapPipeline::SampleProcessorInterface* next, |
363 SkLinearBitmapPipeline::TileStage* tileStage) { | 424 SkLinearBitmapPipeline::TileStage* tileStage) { |
364 switch (yMode) { | 425 switch (yMode) { |
365 case SkShader::kClamp_TileMode: | 426 case SkShader::kClamp_TileMode: |
366 make_tile_stage<XStrategy, YClampStrategy>(filterQuality, dimensions
, next, tileStage); | 427 make_tile_stage<XStrategy, YClampStrategy>(filterQuality, dimensions
, next, tileStage); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 467 |
407 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 468 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
408 // Source Sampling Stage | 469 // Source Sampling Stage |
409 template <typename SourceStrategy, typename Next> | 470 template <typename SourceStrategy, typename Next> |
410 class NearestNeighborSampler final : public SkLinearBitmapPipeline::SampleProces
sorInterface { | 471 class NearestNeighborSampler final : public SkLinearBitmapPipeline::SampleProces
sorInterface { |
411 public: | 472 public: |
412 template <typename... Args> | 473 template <typename... Args> |
413 NearestNeighborSampler(Next* next, Args&&... args) | 474 NearestNeighborSampler(Next* next, Args&&... args) |
414 : fSampler{next, std::forward<Args>(args)...} { } | 475 : fSampler{next, std::forward<Args>(args)...} { } |
415 | 476 |
| 477 NearestNeighborSampler(Next* next, const NearestNeighborSampler& sampler) |
| 478 : fSampler{next, sampler.fSampler} { } |
| 479 |
416 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | 480 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
417 fSampler.nearestListFew(n, xs, ys); | 481 fSampler.nearestListFew(n, xs, ys); |
418 } | 482 } |
419 | 483 |
420 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { | 484 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
421 fSampler.nearestList4(xs, ys); | 485 fSampler.nearestList4(xs, ys); |
422 } | 486 } |
423 | 487 |
424 void pointSpan(Span span) override { | 488 void pointSpan(Span span) override { |
425 fSampler.nearestSpan(span); | 489 fSampler.nearestSpan(span); |
(...skipping 18 matching lines...) Expand all Loading... |
444 GeneralSampler<SourceStrategy, Next> fSampler; | 508 GeneralSampler<SourceStrategy, Next> fSampler; |
445 }; | 509 }; |
446 | 510 |
447 template <typename SourceStrategy, typename Next> | 511 template <typename SourceStrategy, typename Next> |
448 class BilerpSampler final : public SkLinearBitmapPipeline::SampleProcessorInterf
ace { | 512 class BilerpSampler final : public SkLinearBitmapPipeline::SampleProcessorInterf
ace { |
449 public: | 513 public: |
450 template <typename... Args> | 514 template <typename... Args> |
451 BilerpSampler(Next* next, Args&&... args) | 515 BilerpSampler(Next* next, Args&&... args) |
452 : fSampler{next, std::forward<Args>(args)...} { } | 516 : fSampler{next, std::forward<Args>(args)...} { } |
453 | 517 |
| 518 BilerpSampler(Next* next, const BilerpSampler& sampler) |
| 519 : fSampler{next, sampler.fSampler} { } |
| 520 |
454 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { | 521 void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
455 fSampler.bilerpListFew(n, xs, ys); | 522 fSampler.bilerpListFew(n, xs, ys); |
456 } | 523 } |
457 | 524 |
458 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { | 525 void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override { |
459 fSampler.bilerpList4(xs, ys); | 526 fSampler.bilerpList4(xs, ys); |
460 } | 527 } |
461 | 528 |
462 void pointSpan(Span span) override { | 529 void pointSpan(Span span) override { |
463 fSampler.bilerpSpan(span); | 530 fSampler.bilerpSpan(span); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 private: | 614 private: |
548 const uint32_t* pixelAddress(int32_t x, int32_t y) { | 615 const uint32_t* pixelAddress(int32_t x, int32_t y) { |
549 return &fSrc[fWidth * y + x]; | 616 return &fSrc[fWidth * y + x]; |
550 } | 617 } |
551 const uint32_t* const fSrc; | 618 const uint32_t* const fSrc; |
552 const int32_t fWidth; | 619 const int32_t fWidth; |
553 uint32_t* fDest; | 620 uint32_t* fDest; |
554 uint32_t* fEnd; | 621 uint32_t* fEnd; |
555 }; | 622 }; |
556 | 623 |
557 using Placer = SkLinearBitmapPipeline::PixelPlacerInterface; | 624 using Blender = SkLinearBitmapPipeline::BlendProcessorInterface; |
558 | 625 |
559 template<template <typename, typename> class Sampler> | 626 template<template <typename, typename> class Sampler> |
560 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba
se( | 627 static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba
se( |
561 Placer* next, | 628 Blender* next, |
562 const SkPixmap& srcPixmap, | 629 const SkPixmap& srcPixmap, |
563 SkLinearBitmapPipeline::SampleStage* sampleStage) { | 630 SkLinearBitmapPipeline::SampleStage* sampleStage) { |
564 const SkImageInfo& imageInfo = srcPixmap.info(); | 631 const SkImageInfo& imageInfo = srcPixmap.info(); |
565 switch (imageInfo.colorType()) { | 632 switch (imageInfo.colorType()) { |
566 case kRGBA_8888_SkColorType: | 633 case kRGBA_8888_SkColorType: |
567 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { | 634 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
568 sampleStage->Initialize<Sampler<Pixel8888SRGB, Placer>>(next, sr
cPixmap); | 635 sampleStage->initStage<Sampler<Pixel8888SRGB, Blender>>(next, sr
cPixmap); |
569 } else { | 636 } else { |
570 sampleStage->Initialize<Sampler<Pixel8888LRGB, Placer>>(next, sr
cPixmap); | 637 sampleStage->initStage<Sampler<Pixel8888LRGB, Blender>>(next, sr
cPixmap); |
571 } | 638 } |
572 break; | 639 break; |
573 case kBGRA_8888_SkColorType: | 640 case kBGRA_8888_SkColorType: |
574 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { | 641 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
575 sampleStage->Initialize<Sampler<Pixel8888SBGR, Placer>>(next, sr
cPixmap); | 642 sampleStage->initStage<Sampler<Pixel8888SBGR, Blender>>(next, sr
cPixmap); |
576 } else { | 643 } else { |
577 sampleStage->Initialize<Sampler<Pixel8888LBGR, Placer>>(next, sr
cPixmap); | 644 sampleStage->initStage<Sampler<Pixel8888LBGR, Blender>>(next, sr
cPixmap); |
578 } | 645 } |
579 break; | 646 break; |
580 case kIndex_8_SkColorType: | 647 case kIndex_8_SkColorType: |
581 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { | 648 if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
582 sampleStage->Initialize<Sampler<PixelIndex8SRGB, Placer>>(next,
srcPixmap); | 649 sampleStage->initStage<Sampler<PixelIndex8SRGB, Blender>>(next,
srcPixmap); |
583 } else { | 650 } else { |
584 sampleStage->Initialize<Sampler<PixelIndex8LRGB, Placer>>(next,
srcPixmap); | 651 sampleStage->initStage<Sampler<PixelIndex8LRGB, Blender>>(next,
srcPixmap); |
585 } | 652 } |
586 break; | 653 break; |
587 default: | 654 default: |
588 SkFAIL("Not implemented. Unsupported src"); | 655 SkFAIL("Not implemented. Unsupported src"); |
589 break; | 656 break; |
590 } | 657 } |
591 return sampleStage->get(); | 658 return sampleStage->get(); |
592 } | 659 } |
593 | 660 |
594 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( | 661 SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( |
595 Placer* next, | 662 Blender* next, |
596 SkFilterQuality filterQuality, | 663 SkFilterQuality filterQuality, |
597 const SkPixmap& srcPixmap, | 664 const SkPixmap& srcPixmap, |
598 SkLinearBitmapPipeline::SampleStage* sampleStage) { | 665 SkLinearBitmapPipeline::SampleStage* sampleStage) |
| 666 { |
599 if (filterQuality == kNone_SkFilterQuality) { | 667 if (filterQuality == kNone_SkFilterQuality) { |
600 return choose_pixel_sampler_base<NearestNeighborSampler>(next, srcPixmap
, sampleStage); | 668 return choose_pixel_sampler_base<NearestNeighborSampler>(next, srcPixmap
, sampleStage); |
601 } else { | 669 } else { |
602 return choose_pixel_sampler_base<BilerpSampler>(next, srcPixmap, sampleS
tage); | 670 return choose_pixel_sampler_base<BilerpSampler>(next, srcPixmap, sampleS
tage); |
603 } | 671 } |
604 } | 672 } |
605 | 673 |
606 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 674 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
607 // Pixel Placement Stage | 675 // Pixel Blender Stage |
608 template <SkAlphaType alphaType> | 676 template <SkAlphaType alphaType> |
609 class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface { | 677 class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface
{ |
610 public: | 678 public: |
611 PlaceFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } | 679 SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } |
612 | 680 SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} |
613 void VECTORCALL placePixel(Sk4f pixel) override { | 681 void VECTORCALL blendPixel(Sk4f pixel) override { |
614 SkASSERT(fDst + 1 <= fEnd ); | 682 SkASSERT(fDst + 1 <= fEnd ); |
615 PlacePixel(fDst, pixel, 0); | 683 SrcPixel(fDst, pixel, 0); |
616 fDst += 1; | 684 fDst += 1; |
617 } | 685 } |
618 | 686 |
619 void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { | 687 void VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { |
620 SkASSERT(fDst + 4 <= fEnd); | 688 SkASSERT(fDst + 4 <= fEnd); |
621 SkPM4f* dst = fDst; | 689 SkPM4f* dst = fDst; |
622 PlacePixel(dst, p0, 0); | 690 SrcPixel(dst, p0, 0); |
623 PlacePixel(dst, p1, 1); | 691 SrcPixel(dst, p1, 1); |
624 PlacePixel(dst, p2, 2); | 692 SrcPixel(dst, p2, 2); |
625 PlacePixel(dst, p3, 3); | 693 SrcPixel(dst, p3, 3); |
626 fDst += 4; | 694 fDst += 4; |
627 } | 695 } |
628 | 696 |
629 void setDestination(void* dst, int count) override { | 697 void setDestination(void* dst, int count) override { |
630 fDst = static_cast<SkPM4f*>(dst); | 698 fDst = static_cast<SkPM4f*>(dst); |
631 fEnd = fDst + count; | 699 fEnd = fDst + count; |
632 } | 700 } |
633 | 701 |
634 private: | 702 private: |
635 void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) { | 703 void VECTORCALL SrcPixel(SkPM4f* dst, Sk4f pixel, int index) { |
636 Sk4f newPixel = pixel; | 704 Sk4f newPixel = pixel; |
637 if (alphaType == kUnpremul_SkAlphaType) { | 705 if (alphaType == kUnpremul_SkAlphaType) { |
638 newPixel = Premultiply(pixel); | 706 newPixel = Premultiply(pixel); |
639 } | 707 } |
640 newPixel = newPixel * fPostAlpha; | 708 newPixel = newPixel * fPostAlpha; |
641 newPixel.store(dst + index); | 709 newPixel.store(dst + index); |
642 } | 710 } |
643 static Sk4f VECTORCALL Premultiply(Sk4f pixel) { | 711 static Sk4f VECTORCALL Premultiply(Sk4f pixel) { |
644 float alpha = pixel[3]; | 712 float alpha = pixel[3]; |
645 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; | 713 return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; |
646 } | 714 } |
647 | 715 |
648 SkPM4f* fDst; | 716 SkPM4f* fDst; |
649 SkPM4f* fEnd; | 717 SkPM4f* fEnd; |
650 Sk4f fPostAlpha; | 718 Sk4f fPostAlpha; |
651 }; | 719 }; |
652 | 720 |
653 static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer( | 721 static SkLinearBitmapPipeline::BlendProcessorInterface* choose_blender( |
654 SkAlphaType alphaType, | 722 SkAlphaType alphaType, |
655 float postAlpha, | 723 float postAlpha, |
656 SkLinearBitmapPipeline::PixelStage* placerStage) { | 724 SkLinearBitmapPipeline::BlenderStage* blenderStage) { |
657 if (alphaType == kUnpremul_SkAlphaType) { | 725 if (alphaType == kUnpremul_SkAlphaType) { |
658 placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(postAlpha); | 726 blenderStage->initSink<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha); |
659 } else { | 727 } else { |
660 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType | 728 // kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType |
661 placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(postAlpha); | 729 blenderStage->initSink<SrcFPPixel<kPremul_SkAlphaType>>(postAlpha); |
662 } | 730 } |
663 return placerStage->get(); | 731 return blenderStage->get(); |
664 } | 732 } |
665 } // namespace | 733 } // namespace |
666 | 734 |
667 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | 735 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 736 // SkLinearBitmapPipeline |
668 SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {} | 737 SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {} |
669 | 738 |
670 SkLinearBitmapPipeline::SkLinearBitmapPipeline( | 739 SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
671 const SkMatrix& inverse, | 740 const SkMatrix& inverse, |
672 SkFilterQuality filterQuality, | 741 SkFilterQuality filterQuality, |
673 SkShader::TileMode xTile, SkShader::TileMode yTile, | 742 SkShader::TileMode xTile, SkShader::TileMode yTile, |
674 float postAlpha, | 743 float postAlpha, |
675 const SkPixmap& srcPixmap) | 744 const SkPixmap& srcPixmap) |
676 { | 745 { |
677 SkISize dimensions = srcPixmap.info().dimensions(); | 746 SkISize dimensions = srcPixmap.info().dimensions(); |
(...skipping 14 matching lines...) Expand all Loading... |
692 SkScalar dx = adjustedInverse.getScaleX(); | 761 SkScalar dx = adjustedInverse.getScaleX(); |
693 | 762 |
694 // If it is an index 8 color type, the sampler converts to unpremul for bett
er fidelity. | 763 // If it is an index 8 color type, the sampler converts to unpremul for bett
er fidelity. |
695 SkAlphaType alphaType = srcImageInfo.alphaType(); | 764 SkAlphaType alphaType = srcImageInfo.alphaType(); |
696 if (srcPixmap.colorType() == kIndex_8_SkColorType) { | 765 if (srcPixmap.colorType() == kIndex_8_SkColorType) { |
697 alphaType = kUnpremul_SkAlphaType; | 766 alphaType = kUnpremul_SkAlphaType; |
698 } | 767 } |
699 | 768 |
700 // As the stages are built, the chooser function may skip a stage. For examp
le, with the | 769 // As the stages are built, the chooser function may skip a stage. For examp
le, with the |
701 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. | 770 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. |
702 auto placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage
); | 771 auto blenderStage = choose_blender(alphaType, postAlpha, &fBlenderStage); |
703 auto samplerStage = choose_pixel_sampler(placementStage, | 772 auto samplerStage = choose_pixel_sampler(blenderStage, filterQuality, srcPix
map, &fSampleStage); |
704 filterQuality, srcPixmap, &fSampl
eStage); | 773 auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile, |
705 auto tilerStage = choose_tiler(samplerStage, | 774 filterQuality, dx, &fTileStage); |
706 dimensions, xTile, yTile, filterQuality,
dx, &fTiler); | 775 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage
); |
707 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixSta
ge); | 776 fLastStage = blenderStage; |
708 fLastStage = placementStage; | |
709 | |
710 } | 777 } |
711 | 778 |
712 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { | 779 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
713 SkASSERT(count > 0); | 780 SkASSERT(count > 0); |
714 fLastStage->setDestination(dst, count); | 781 fLastStage->setDestination(dst, count); |
715 | 782 |
716 // The count and length arguments start out in a precise relation in order t
o keep the | 783 // The count and length arguments start out in a precise relation in order t
o keep the |
717 // math correct through the different stages. Count is the number of pixel t
o produce. | 784 // math correct through the different stages. Count is the number of pixel t
o produce. |
718 // Since the code samples at pixel centers, length is the distance from the
center of the | 785 // Since the code samples at pixel centers, length is the distance from the
center of the |
719 // first pixel to the center of the last pixel. This implies that length is
count-1. | 786 // first pixel to the center of the last pixel. This implies that length is
count-1. |
720 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); | 787 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); |
721 } | 788 } |
OLD | NEW |