| 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 |