Index: src/core/SkLinearBitmapPipeline_core.h |
diff --git a/src/core/SkLinearBitmapPipeline_core.h b/src/core/SkLinearBitmapPipeline_core.h |
index 0541f3cce5ca45804ecd14abd2ab0baf38517d41..2759f0bb8ccc728472bb68a23d72c8bedf073007 100644 |
--- a/src/core/SkLinearBitmapPipeline_core.h |
+++ b/src/core/SkLinearBitmapPipeline_core.h |
@@ -10,6 +10,16 @@ |
#include <cmath> |
+// New bilerp strategy: |
+// Pass through on bilerpList4 and bilerpListFew (analogs to pointList), introduce bilerpEdge |
+// which takes 4 points. If the sample spans an edge, then break it into a bilerpEdge. Bilerp |
+// span then becomes a normal span except in special cases where an extra Y is given. The bilerp |
+// need to stay single point calculations until the tile layer. |
+// TODO: |
+// - edge span predicate. |
+// - introduce new point API |
+// - Add tile for new api. |
+ |
// Tweak ABI of functions that pass Sk4f by value to pass them via registers. |
#if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 |
#define VECTORCALL __vectorcall |
@@ -65,12 +75,13 @@ public: |
} |
bool isEmpty() const { return 0 == fCount; } |
+ void clear() { fCount = 0; } |
+ int count() const { return fCount; } |
SkScalar length() const { return fLength; } |
SkScalar startX() const { return X(fStart); } |
- SkScalar endX() const { return startX() + length(); } |
- void clear() { |
- fCount = 0; |
- } |
+ SkScalar endX() const { return this->startX() + this->length(); } |
+ SkScalar startY() const { return Y(fStart); } |
+ Span emptySpan() { return Span{{0.0, 0.0}, 0.0f, 0}; } |
bool completelyWithin(SkScalar xMin, SkScalar xMax) const { |
SkScalar sMin, sMax; |
@@ -88,17 +99,14 @@ public: |
SkASSERT(dx != 0.0f); |
if (this->isEmpty()) { |
- return Span{{0.0, 0.0}, 0.0f, 0}; |
+ return this->emptySpan(); |
} |
int dxSteps = SkScalarFloorToInt((breakX - this->startX()) / dx); |
- // Calculate the values for the span to cleave off. |
- SkScalar newLength = dxSteps * dx; |
- |
if (dxSteps < 0) { |
// The span is wholly after breakX. |
- return Span{{0.0, 0.0}, 0.0f, 0}; |
+ return this->emptySpan(); |
} else if (dxSteps >= fCount) { |
// The span is wholly before breakX. |
Span answer = *this; |
@@ -106,6 +114,9 @@ public: |
return answer; |
} |
+ // Calculate the values for the span to cleave off. |
+ SkScalar newLength = dxSteps * dx; |
+ |
// If the last (or first if count = 1) sample lands directly on the boundary. Include it |
// when dx < 0 and exclude it when dx > 0. |
// Reasoning: |
@@ -113,15 +124,16 @@ public: |
// pixel is after the boundary. |
// dx < 0: The sample point on the boundary is part of the current span because the |
// entire pixel is before the boundary. |
- if (startX() + newLength == breakX && dx > 0) { |
- if (dxSteps != 0) { |
+ if (this->startX() + newLength == breakX && dx > 0) { |
+ if (dxSteps > 0) { |
dxSteps -= 1; |
newLength -= dx; |
} else { |
- return Span{{0.0, 0.0}, 0.0f, 0}; |
+ return this->emptySpan(); |
} |
} |
+ // Calculate new span parameters |
SkPoint newStart = fStart; |
int newCount = dxSteps + 1; |
SkASSERT(newCount > 0); |
@@ -146,39 +158,6 @@ private: |
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; |
-}; |
- |
template<typename Stage> |
void span_fallback(Span span, Stage* stage) { |
SkPoint start; |
@@ -206,26 +185,6 @@ void span_fallback(Span span, Stage* stage) { |
stage->pointListFew(count, xs, ys); |
} |
} |
- |
-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; |
- } |
-} |
} // namespace |
#endif // SkLinearBitmapPipeline_core_DEFINED |