Chromium Code Reviews| Index: src/core/SkLinearBitmapPipeline.cpp |
| diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp |
| index d1000282da334f286e831cc0029a957662087df0..52782bc87f45e50222d91a7e0642bc23ef821ce2 100644 |
| --- a/src/core/SkLinearBitmapPipeline.cpp |
| +++ b/src/core/SkLinearBitmapPipeline.cpp |
| @@ -55,12 +55,49 @@ private: |
| Strategy fStrategy; |
| }; |
| -class SkippedStage final : public PointProcessorInterface { |
| +template<typename Strategy, typename Next> |
| +class BilerpProcessor : public BilerpProcessorInterface { |
|
mtklein
2016/02/17 20:25:09
final (and PointProcessor too)?
herb_g
2016/02/17 23:40:43
Done.
|
| +public: |
| + template <typename... Args> |
| + BilerpProcessor(Next* next, Args&&... args) |
| + : fNext{next} |
| + , fStrategy{std::forward<Args>(args)...}{ } |
| + |
| void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
| - SkFAIL("Abort tiler."); |
| + Sk4f newXs = xs; |
|
mtklein
2016/02/17 20:25:09
This is so sad. :(
herb_g
2016/02/17 23:40:44
Acknowledged.
|
| + Sk4f newYs = ys; |
| + fStrategy.processPoints(&newXs, &newYs); |
| + fNext->pointListFew(n, newXs, newYs); |
| + } |
| + |
| + void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
| + Sk4f newXs = xs; |
| + Sk4f newYs = ys; |
| + fStrategy.processPoints(&newXs, &newYs); |
| + fNext->pointList4(newXs, newYs); |
| + } |
| + |
| + void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
| + Sk4f newXs = xs; |
| + Sk4f newYs = ys; |
| + fStrategy.processPoints(&newXs, &newYs); |
| + fNext->bilerpList(newXs, newYs); |
| + } |
| + |
| +private: |
| + Next* const fNext; |
| + Strategy fStrategy; |
| +}; |
| + |
| +class SkippedStage final : public BilerpProcessorInterface { |
| + void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
| + SkFAIL("Skipped stage."); |
| } |
| void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { |
| - SkFAIL("Abort point processor."); |
| + SkFAIL("Skipped stage."); |
| + } |
| + virtual void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
|
mtklein
2016/02/17 20:25:09
I think override's plenty.
herb_g
2016/02/17 23:40:44
Done.
|
| + SkFAIL("Skipped stage."); |
| } |
| }; |
| @@ -147,6 +184,47 @@ static PointProcessorInterface* choose_matrix( |
| return matrixProc->get(); |
| } |
| +template <typename Next = BilerpProcessorInterface> |
| +class ExpandBilerp final : public PointProcessorInterface { |
| +public: |
| + ExpandBilerp(Next* next) : fNext{next} { } |
| + |
| + void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
| + SkASSERT(n > 0 && n <= 4); |
|
mtklein
2016/02/17 20:25:09
This seems awkward. It's a bug if we call pointLi
herb_g
2016/02/17 23:40:43
Done.
|
| + if (n >= 1) fNext->bilerpList(Sk4f{xs[0]} + kXOffsets, Sk4f{ys[0]} + kYOffsets); |
| + if (n >= 2) fNext->bilerpList(Sk4f{xs[1]} + kXOffsets, Sk4f{ys[1]} + kYOffsets); |
| + if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); |
| + if (n == 4) fNext->bilerpList(Sk4f{xs[3]} + kXOffsets, Sk4f{ys[3]} + kYOffsets); |
| + } |
| + |
| + void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
| + pointListFew(4, xs, ys); |
|
mtklein
2016/02/17 20:25:09
self calls usually have a this->
herb_g
2016/02/17 23:40:44
Removed
|
| + } |
|
mtklein
2016/02/17 20:25:09
Is this why we distinguish PointProcessor and Bile
herb_g
2016/02/17 23:40:44
There is no sensible bilerp here or at the matrix
|
| + |
| +private: |
| + static const Sk4f kXOffsets; |
| + static const Sk4f kYOffsets; |
| + Next* const fNext; |
| +}; |
| + |
| +template <typename Next> |
| +const Sk4f ExpandBilerp<Next>::kXOffsets = {0.0f, 1.0f, 0.0f, 1.0f}; |
|
mtklein
2016/02/17 20:25:09
This is all sort of awkward and boilerplate-y.
Le
herb_g
2016/02/17 23:40:43
Done.
|
| +template <typename Next> |
| +const Sk4f ExpandBilerp<Next>::kYOffsets = {0.0f, 0.0f, 1.0f, 1.0f}; |
| + |
| +static PointProcessorInterface* choose_filter( |
| + BilerpProcessorInterface* next, |
| + SkFilterQuality filterQuailty, |
| + SkLinearBitmapPipeline::FilterStage* filterProc) { |
| + if (filterQuailty >= SkFilterQuality::kLow_SkFilterQuality) { |
|
mtklein
2016/02/17 20:25:09
Might wanna write as:
none -> skipped
else -
herb_g
2016/02/17 23:40:43
Done.
|
| + filterProc->Initialize<ExpandBilerp<>>(next); |
| + return filterProc->get(); |
| + } else { |
| + filterProc->Initialize<SkippedStage>(); |
| + return next; |
| + } |
| +} |
| + |
| class ClampStrategy { |
| public: |
| ClampStrategy(X max) |
| @@ -172,8 +250,8 @@ private: |
| const Sk4f fXMax{SK_FloatInfinity}; |
| const Sk4f fYMax{SK_FloatInfinity}; |
| }; |
| -template <typename Next = PointProcessorInterface> |
| -using Clamp = PointProcessor<ClampStrategy, Next>; |
| +template <typename Next = BilerpProcessorInterface> |
| +using Clamp = BilerpProcessor<ClampStrategy, Next>; |
| class RepeatStrategy { |
| public: |
| @@ -201,11 +279,11 @@ private: |
| const Sk4f fYInvMax{0.0f}; |
| }; |
| -template <typename Next = PointProcessorInterface> |
| -using Repeat = PointProcessor<RepeatStrategy, Next>; |
| +template <typename Next = BilerpProcessorInterface> |
| +using Repeat = BilerpProcessor<RepeatStrategy, Next>; |
| -static PointProcessorInterface* choose_tiler( |
| - PointProcessorInterface* next, |
| +static BilerpProcessorInterface* choose_tiler( |
| + BilerpProcessorInterface* next, |
| SkSize dimensions, |
| SkShader::TileMode xMode, |
| SkShader::TileMode yMode, |
| @@ -307,8 +385,20 @@ private: |
| const Sk4i fWidth; |
| }; |
| +inline Sk4f bilerp4(SkPoint pt, Sk4f pixel00, Sk4f pixel01, |
|
mtklein
2016/02/17 20:25:09
It's a good habit to get into writing static on al
herb_g
2016/02/17 23:40:44
Done.
|
| + Sk4f pixel10, Sk4f pixel11) { |
| + Sk4f Xs{X(pt) - std::floor(X(pt))}; |
|
mtklein
2016/02/17 20:25:09
If we're using std:: stuff, might want to consider
herb_g
2016/02/17 23:40:43
Redid whole function.
|
| + Sk4f Ys{Y(pt) - std::floor(Y(pt))}; |
| + Sk4f XYs{Xs * Ys}; |
| + Sk4f sum = pixel11 * XYs; |
| + sum = sum + pixel01 * (Xs - XYs); |
| + sum = sum + pixel10 * (Ys - XYs); |
| + sum = sum + pixel00 * (Sk4f{1.0f} - Xs - Ys + XYs); |
|
mtklein
2016/02/17 20:25:09
This would be a really great place for an ASCII ar
herb_g
2016/02/17 23:40:43
Done.
|
| + return sum; |
| +} |
| + |
| template <typename SourceStrategy> |
| -class Sampler final : public PointProcessorInterface { |
| +class Sampler final : public BilerpProcessorInterface { |
| public: |
| template <typename... Args> |
| Sampler(PixelPlacerInterface* next, Args&&... args) |
| @@ -330,12 +420,20 @@ public: |
| fNext->place4Pixels(px0, px1, px2, px3); |
| } |
| + void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
| + SkPoint referencePoint{xs[0], ys[0]}; |
|
mtklein
2016/02/17 20:25:09
Do these all have the same fractional parts? I'm
herb_g
2016/02/17 23:40:43
Done.
|
| + Sk4f px0, px1, px2, px3; |
| + fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); |
| + Sk4f pixel = bilerp4(referencePoint, px0, px1, px2, px3); |
| + fNext->placePixel(pixel); |
| + } |
| + |
| private: |
| PixelPlacerInterface* const fNext; |
| SourceStrategy fStrategy; |
| }; |
| -static PointProcessorInterface* choose_pixel_sampler( |
| +static BilerpProcessorInterface* choose_pixel_sampler( |
| PixelPlacerInterface* next, |
| const SkImageInfo& imageInfo, |
| const void* imageData, |
| @@ -415,6 +513,7 @@ static PixelPlacerInterface* choose_pixel_placer( |
| SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
| const SkMatrix& inverse, |
| + SkFilterQuality filterQuality, |
| SkShader::TileMode xTile, SkShader::TileMode yTile, |
| const SkImageInfo& srcImageInfo, |
| const void* srcImageData) { |
| @@ -428,7 +527,8 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
| srcImageData, &fSampleStage); |
| auto tilerStage = choose_tiler(samplerStage, size, xTile, yTile, &fTileXOrBothStage, |
| &fTileYStage); |
| - fFirstStage = choose_matrix(tilerStage, inverse, &fMatrixStage); |
| + auto filterStage = choose_filter(tilerStage, filterQuality, &fFilterStage); |
| + fFirstStage = choose_matrix(filterStage, inverse, &fMatrixStage); |
| } |
| void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |