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

Unified Diff: src/core/SkLinearBitmapPipeline_tile.h

Issue 1861253003: Use a faster repeat tiler when translate only matrix. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments. Created 4 years, 8 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.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkLinearBitmapPipeline_tile.h
diff --git a/src/core/SkLinearBitmapPipeline_tile.h b/src/core/SkLinearBitmapPipeline_tile.h
index 60cc2a5ef09acb8eb01f4f71d1f5608ebe0484f3..997ab65c4730cd11dd475edb96c8ad6b6d584859 100644
--- a/src/core/SkLinearBitmapPipeline_tile.h
+++ b/src/core/SkLinearBitmapPipeline_tile.h
@@ -234,6 +234,95 @@ private:
const Sk4s fXsInvMax;
};
+// The XRepeatUnitScaleStrategy exploits the situation where dx = 1.0. The main advantage is that
+// the relationship between the sample points and the source pixels does not change from tile to
+// repeated tile. This allows the tiler to calculate the span once and re-use it for each
+// repeated tile. This is later exploited by some samplers to avoid converting pixels to linear
+// space allowing the use of memmove to place pixel in the destination.
+class XRepeatUnitScaleStrategy {
+public:
+ XRepeatUnitScaleStrategy(int32_t max)
+ : fXMax{SkScalar(max)}
+ , fXsMax{SkScalar(max)}
+ , fXsCap{SkScalar(nextafterf(SkScalar(max), 0.0f))}
+ , fXsInvMax{1.0f / SkScalar(max)} { }
+
+ void tileXPoints(Sk4s* xs) {
+ Sk4s divX = *xs * fXsInvMax;
+ Sk4s modX = *xs - divX.floor() * fXsMax;
+ *xs = Sk4s::Min(fXsCap, modX);
+ SkASSERT(0 <= (*xs)[0] && (*xs)[0] < fXMax);
+ SkASSERT(0 <= (*xs)[1] && (*xs)[1] < fXMax);
+ SkASSERT(0 <= (*xs)[2] && (*xs)[2] < fXMax);
+ SkASSERT(0 <= (*xs)[3] && (*xs)[3] < fXMax);
+ }
+
+ template<typename Next>
+ bool maybeProcessSpan(Span originalSpan, Next* next) {
+ SkASSERT(!originalSpan.isEmpty());
+ SkPoint start; SkScalar length; int count;
+ std::tie(start, length, count) = originalSpan;
+ // Make x and y in range on the tile.
+ SkScalar x = tile_mod(X(start), fXMax);
+ SkScalar y = Y(start);
+
+ // No need trying to go fast because the steps are larger than a tile or there is one point.
+ if (fXMax == 1 || count <= 1) {
+ return false;
+ }
+
+ // x should be on the tile.
+ SkASSERT(0.0f <= x && x < fXMax);
+ Span span({x, y}, length, count);
+
+ if (SkScalarFloorToScalar(x) != 0.0f) {
+ Span toDraw = span.breakAt(fXMax, 1.0f);
+ SkASSERT(0.0f <= toDraw.startX() && toDraw.endX() < fXMax);
+ next->pointSpan(toDraw);
+ span.offset(-fXMax);
+ }
+
+ // All of the span could have been on the first tile. If so, then no work to do.
+ if (span.isEmpty()) return true;
+
+ // At this point the span should be aligned to zero.
+ SkASSERT(SkScalarFloorToScalar(span.startX()) == 0.0f);
+
+ // Note: The span length has an unintuitive relation to the tile width. The tile width is
+ // a half open interval [tb, te), but the span is a closed interval [sb, se]. In order to
+ // compare the two, you need to convert the span to a half open interval. This is done by
+ // adding dx to se. So, the span becomes: [sb, se + dx). Hence the + 1.0f below.
+ SkScalar div = (span.length() + 1.0f) / fXMax;
+ int32_t repeatCount = SkScalarFloorToInt(div);
+ Span repeatableSpan{{0.0f, y}, fXMax - 1.0f, SkScalarFloorToInt(fXMax)};
+
+ // Repeat the center section.
+ SkASSERT(0.0f <= repeatableSpan.startX() && repeatableSpan.endX() < fXMax);
+ next->repeatSpan(repeatableSpan, repeatCount);
+
+ // Calculate the advance past the center portion.
+ SkScalar advance = SkScalar(repeatCount) * fXMax;
+
+ // There may be some of the span left over.
+ span.breakAt(advance, 1.0f);
+
+ // All on a single tile.
+ if (!span.isEmpty()) {
+ span.offset(-advance);
+ SkASSERT(0.0f <= span.startX() && span.endX() < fXMax);
+ next->pointSpan(span);
+ }
+
+ return true;
+ }
+
+private:
+ const SkScalar fXMax;
+ const Sk4s fXsMax;
+ const Sk4s fXsCap;
+ const Sk4s fXsInvMax;
+};
+
class YRepeatStrategy {
public:
YRepeatStrategy(int32_t max)
« no previous file with comments | « src/core/SkLinearBitmapPipeline.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698