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

Unified Diff: src/core/SkLinearBitmapPipeline.cpp

Issue 1751943002: Introduce bilerp spans (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Sync 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 | « no previous file | no next file » | 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 236f5bf8768712e13a19096d9b1fd55148229827..4ab0b90f550ef87063943f6fac9ac2816dc81236 100644
--- a/src/core/SkLinearBitmapPipeline.cpp
+++ b/src/core/SkLinearBitmapPipeline.cpp
@@ -132,6 +132,39 @@ private:
SkScalar fLength;
int fCount;
};
+
+// BilerpSpans are similar to Spans, but they represent four source samples converting to single
+// destination pixel per count. The pixels for the four samples are collect along two horizontal
+// lines; one starting at {x, y0} and the other starting at {x, y1}. There are two distinct lines
+// to deal with the edge case of the tile mode. For example, y0 may be at the last y position in
+// a tile while y1 would be at the first.
+// The step of a Bilerp (dx) is still length / (count - 1) and the start to the next sample is
+// still dx * count, but the bounds are complicated by the sampling kernel so that the pixels
+// touched are from x to x + length + 1.
+class BilerpSpan {
+public:
+ BilerpSpan(SkScalar x, SkScalar y0, SkScalar y1, SkScalar length, int count)
+ : fX{x}, fY0{y0}, fY1{y1}, fLength{length}, fCount{count} {
+ SkASSERT(count >= 0);
+ SkASSERT(std::isfinite(length));
+ SkASSERT(std::isfinite(x));
+ SkASSERT(std::isfinite(y0));
+ SkASSERT(std::isfinite(y1));
+ }
+
+ operator std::tuple<SkScalar&, SkScalar&, SkScalar&, SkScalar&, int&>() {
+ return std::tie(fX, fY0, fY1, fLength, fCount);
+ }
+
+ bool isEmpty() const { return 0 == fCount; }
+
+private:
+ SkScalar fX;
+ SkScalar fY0;
+ SkScalar fY1;
+ SkScalar fLength;
+ int fCount;
+};
} // namespace
class SkLinearBitmapPipeline::PointProcessorInterface {
@@ -158,6 +191,7 @@ public:
// These pixels coordinates are arranged in the following order in xs and ys:
// px00 px10 px01 px11
virtual void VECTORCALL bilerpList(Sk4s xs, Sk4s ys) = 0;
+ virtual void bilerpSpan(BilerpSpan span) = 0;
};
class SkLinearBitmapPipeline::PixelPlacerInterface {
@@ -197,6 +231,26 @@ void span_fallback(Span span, Stage* stage) {
}
}
+template <typename Next>
+void bilerp_span_fallback(BilerpSpan span, Next* next) {
+ SkScalar x, y0, y1; SkScalar length; int count;
+ std::tie(x, y0, y1, length, count) = span;
+
+ SkASSERT(!span.isEmpty());
+ float dx = length / (count - 1);
+
+ Sk4f xs = Sk4f{x} + Sk4f{0.0f, 1.0f, 0.0f, 1.0f};
+ Sk4f ys = Sk4f{y0, y0, y1, y1};
+
+ // If count == 1 then dx will be inf or NaN, but that is ok because the resulting addition is
+ // never used.
+ while (count > 0) {
+ next->bilerpList(xs, ys);
+ xs = xs + dx;
+ count -= 1;
+ }
+}
+
// PointProcessor uses a strategy to help complete the work of the different stages. The strategy
// must implement the following methods:
// * processPoints(xs, ys) - must mutate the xs and ys for the stage.
@@ -268,6 +322,13 @@ public:
}
}
+ void bilerpSpan(BilerpSpan bSpan) override {
+ SkASSERT(!bSpan.isEmpty());
+ if (!fStrategy.maybeProcessBilerpSpan(bSpan, fNext)) {
+ bilerp_span_fallback(bSpan, this);
+ }
+ }
+
private:
Next* const fNext;
Strategy fStrategy;
@@ -409,17 +470,9 @@ public:
SkASSERT(!span.isEmpty());
SkPoint start; SkScalar length; int count;
std::tie(start, length, count) = span;
- float dx = length / (count - 1);
-
- Sk4f Xs = Sk4f{X(start)} + Sk4f{-0.5f, 0.5f, -0.5f, 0.5f};
- Sk4f Ys = Sk4f{Y(start)} + Sk4f{-0.5f, -0.5f, 0.5f, 0.5f};
-
- Sk4f dXs{dx};
- while (count > 0) {
- fNext->bilerpList(Xs, Ys);
- Xs = Xs + dXs;
- count -= 1;
- }
+ // Adjust the span so that it is in the correct phase with the pixel.
+ BilerpSpan bSpan{X(start) - 0.5f, Y(start) - 0.5f, Y(start) + 0.5f, length, count};
+ fNext->bilerpSpan(bSpan);
}
private:
@@ -540,6 +593,11 @@ public:
return true;
}
+ template <typename Next>
+ bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) {
+ return false;
+ }
+
private:
const Sk4s fXMin{SK_FloatNegativeInfinity};
const Sk4s fYMin{SK_FloatNegativeInfinity};
@@ -643,6 +701,11 @@ public:
return true;
}
+ template <typename Next>
+ bool maybeProcessBilerpSpan(BilerpSpan bSpan, Next* next) {
+ return false;
+ }
+
private:
const Sk4s fXMax{0.0f};
const Sk4s fXInvMax{0.0f};
@@ -924,6 +987,10 @@ private:
span_fallback(span, this);
}
+ void bilerpSpan(BilerpSpan span) override {
+ bilerp_span_fallback(span, this);
+ }
+
private:
SkLinearBitmapPipeline::PixelPlacerInterface* const fNext;
SourceStrategy fStrategy;
« 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