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

Unified Diff: src/core/SkLinearBitmapPipeline.cpp

Issue 1705203002: Add bilerp filtering. (Closed) Base URL: https://skia.googlesource.com/skia.git@fp-simple-linear-20160217
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkLinearBitmapPipeline.h ('k') | tests/SkLinearBitmapPipelineTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « src/core/SkLinearBitmapPipeline.h ('k') | tests/SkLinearBitmapPipelineTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698