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

Unified Diff: src/core/SkLinearBitmapPipeline_sample.h

Issue 2055513003: Simplify code by breaking general sampler into Nearest and Bilerp. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: sync Created 4 years, 6 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_core.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkLinearBitmapPipeline_sample.h
diff --git a/src/core/SkLinearBitmapPipeline_sample.h b/src/core/SkLinearBitmapPipeline_sample.h
index 15a7c359cc1ab6ace6fa15024ac43e31232f91fa..930759f271ea1a108432a4ac4447209f794cccc7 100644
--- a/src/core/SkLinearBitmapPipeline_sample.h
+++ b/src/core/SkLinearBitmapPipeline_sample.h
@@ -266,22 +266,60 @@ private:
PixelGetter<colorType, colorProfile> fGetter;
};
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// GeneralSampler handles all the different sampling scenarios. It makes runtime decisions to
-// choose the fastest strategy given a particular job. It ultimately uses PixelGetters to access
-// the pixels.
+// We're moving through source space at a rate of 1 source pixel per 1 dst pixel.
+// We'll never re-use pixels, but we can at least load contiguous pixels.
+template <typename Next, typename Strategy>
+static void src_strategy_blend(Span span, Next* next, Strategy* strategy) {
+ SkPoint start;
+ SkScalar length;
+ int count;
+ std::tie(start, length, count) = span;
+ int ix = SkScalarFloorToInt(X(start));
+ const void* row = strategy->row((int)std::floor(Y(start)));
+ if (length > 0) {
+ while (count >= 4) {
+ Sk4f px0, px1, px2, px3;
+ strategy->get4Pixels(row, ix, &px0, &px1, &px2, &px3);
+ next->blend4Pixels(px0, px1, px2, px3);
+ ix += 4;
+ count -= 4;
+ }
+
+ while (count > 0) {
+ next->blendPixel(strategy->getPixelFromRow(row, ix));
+ ix += 1;
+ count -= 1;
+ }
+ } else {
+ while (count >= 4) {
+ Sk4f px0, px1, px2, px3;
+ strategy->get4Pixels(row, ix - 3, &px3, &px2, &px1, &px0);
+ next->blend4Pixels(px0, px1, px2, px3);
+ ix -= 4;
+ count -= 4;
+ }
+
+ while (count > 0) {
+ next->blendPixel(strategy->getPixelFromRow(row, ix));
+ ix -= 1;
+ count -= 1;
+ }
+ }
+}
+
+// NearestNeighborSampler - use nearest neighbor filtering to create runs of destination pixels.
template<SkColorType colorType, SkColorProfileType colorProfile, typename Next>
-class GeneralSampler {
+class NearestNeighborSampler : public SkLinearBitmapPipeline::SampleProcessorInterface {
public:
template<typename... Args>
- GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&& ... args)
- : fNext{next}, fStrategy{std::forward<Args>(args)...} { }
+ NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&& ... args)
+ : fNext{next}, fStrategy{std::forward<Args>(args)...} { }
- GeneralSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next,
- const GeneralSampler& sampler)
- : fNext{next}, fStrategy{sampler.fStrategy} { }
+ NearestNeighborSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next,
+ const NearestNeighborSampler& sampler)
+ : fNext{next}, fStrategy{sampler.fStrategy} { }
- void VECTORCALL nearestListFew(int n, Sk4s xs, Sk4s ys) {
+ void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
SkASSERT(0 < n && n < 4);
Sk4f px0, px1, px2;
fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2);
@@ -290,13 +328,13 @@ public:
if (n >= 3) fNext->blendPixel(px2);
}
- void VECTORCALL nearestList4(Sk4s xs, Sk4s ys) {
+ void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
Sk4f px0, px1, px2, px3;
fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3);
fNext->blend4Pixels(px0, px1, px2, px3);
}
- void nearestSpan(Span span) {
+ void pointSpan(Span span) override {
SkASSERT(!span.isEmpty());
SkPoint start;
SkScalar length;
@@ -304,86 +342,33 @@ public:
std::tie(start, length, count) = span;
SkScalar absLength = SkScalarAbs(length);
if (absLength < (count - 1)) {
- this->nearestSpanSlowRate(span);
+ this->spanSlowRate(span);
} else if (absLength == (count - 1)) {
- this->nearestSpanUnitRate(span);
+ src_strategy_blend(span, fNext, &fStrategy);
} else {
- this->nearestSpanFastRate(span);
+ this->spanFastRate(span);
}
}
- Sk4f bilerpNonEdgePixel(SkScalar x, SkScalar y) {
- Sk4f px00, px10, px01, px11;
- // bilerp4() expects xs, ys are the top-lefts of the 2x2 kernel.
- Sk4f xs = Sk4f{x} - 0.5f;
- Sk4f ys = Sk4f{y} - 0.5f;
- Sk4f sampleXs = xs + Sk4f{0.0f, 1.0f, 0.0f, 1.0f};
- Sk4f sampleYs = ys + Sk4f{0.0f, 0.0f, 1.0f, 1.0f};
- fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11);
- return bilerp4(xs, ys, px00, px10, px01, px11);
- }
-
- void VECTORCALL bilerpListFew(int n, Sk4s xs, Sk4s ys) {
- SkASSERT(0 < n && n < 4);
- auto bilerpPixel = [&](int index) {
- return this->bilerpNonEdgePixel(xs[index], ys[index]);
- };
-
- if (n >= 1) fNext->blendPixel(bilerpPixel(0));
- if (n >= 2) fNext->blendPixel(bilerpPixel(1));
- if (n >= 3) fNext->blendPixel(bilerpPixel(2));
- }
-
- void VECTORCALL bilerpList4(Sk4s xs, Sk4s ys) {
- auto bilerpPixel = [&](int index) {
- return this->bilerpNonEdgePixel(xs[index], ys[index]);
- };
- fNext->blend4Pixels(bilerpPixel(0), bilerpPixel(1), bilerpPixel(2), bilerpPixel(3));
- }
-
- void VECTORCALL bilerpEdge(Sk4s sampleXs, Sk4s sampleYs) {
- Sk4f px00, px10, px01, px11;
- Sk4f xs = Sk4f{sampleXs[0]};
- Sk4f ys = Sk4f{sampleYs[0]};
- fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11);
- Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11);
- fNext->blendPixel(pixel);
+ void repeatSpan(Span span, int32_t repeatCount) override {
+ while (repeatCount > 0) {
+ this->pointSpan(span);
+ repeatCount--;
+ }
}
- void bilerpSpan(Span span) {
- this->bilerpSpanWithY(span, span.startY());
+ void VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override {
+ SkFAIL("Using nearest neighbor sampler, but calling a bilerpEdge.");
}
- void bilerpSpanWithY(Span span, SkScalar y) {
- SkASSERT(!span.isEmpty());
- SkPoint start;
- SkScalar length;
- int count;
- std::tie(start, length, count) = span;
- SkScalar absLength = SkScalarAbs(length);
- if (absLength == 0.0f) {
- this->bilerpSpanZeroRate(span, y);
- } else if (absLength < (count - 1)) {
- this->bilerpSpanSlowRate(span, y);
- } else if (absLength == (count - 1)) {
- if (std::fmod(span.startX() - 0.5f, 1.0f) == 0.0f) {
- if (std::fmod(span.startY() - 0.5f, 1.0f) == 0.0f) {
- this->nearestSpanUnitRate(span);
- } else {
- this->bilerpSpanUnitRateAlignedX(span, y);
- }
- } else {
- this->bilerpSpanUnitRate(span, y);
- }
- } else {
- this->bilerpSpanFastRate(span, y);
- }
+ void bilerpSpan(Span span, SkScalar y) override {
+ SkFAIL("Using nearest neighbor sampler, but calling a bilerpSpan.");
}
private:
// When moving through source space more slowly than dst space (zoomed in),
// we'll be sampling from the same source pixel more than once.
- void nearestSpanSlowRate(Span span) {
+ void spanSlowRate(Span span) {
SkPoint start;
SkScalar length;
int count;
@@ -429,64 +414,110 @@ private:
// We're moving through source space at a rate of 1 source pixel per 1 dst pixel.
// We'll never re-use pixels, but we can at least load contiguous pixels.
- void nearestSpanUnitRate(Span span) {
- SkPoint start;
- SkScalar length;
- int count;
- std::tie(start, length, count) = span;
- int ix = SkScalarFloorToInt(X(start));
- const void* row = fStrategy.row((int)std::floor(Y(start)));
- Next* next = fNext;
- if (length > 0) {
- while (count >= 4) {
- Sk4f px0, px1, px2, px3;
- fStrategy.get4Pixels(row, ix, &px0, &px1, &px2, &px3);
- next->blend4Pixels(px0, px1, px2, px3);
- ix += 4;
- count -= 4;
- }
-
- while (count > 0) {
- next->blendPixel(fStrategy.getPixelFromRow(row, ix));
- ix += 1;
- count -= 1;
- }
- } else {
- while (count >= 4) {
- Sk4f px0, px1, px2, px3;
- fStrategy.get4Pixels(row, ix - 3, &px3, &px2, &px1, &px0);
- next->blend4Pixels(px0, px1, px2, px3);
- ix -= 4;
- count -= 4;
- }
-
- while (count > 0) {
- next->blendPixel(fStrategy.getPixelFromRow(row, ix));
- ix -= 1;
- count -= 1;
- }
- }
+ void spanUnitRate(Span span) {
+ src_strategy_blend(span, fNext, &fStrategy);
}
// We're moving through source space faster than dst (zoomed out),
// so we'll never reuse a source pixel or be able to do contiguous loads.
- void nearestSpanFastRate(Span span) {
- struct NearestWrapper {
- void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) {
- fSampler.nearestListFew(n, xs, ys);
- }
+ void spanFastRate(Span span) {
+ span_fallback(span, this);
+ }
- void VECTORCALL pointList4(Sk4s xs, Sk4s ys) {
- fSampler.nearestList4(xs, ys);
- }
+ Next* const fNext;
+ PixelAccessor<colorType, colorProfile> fStrategy;
+};
+
+// BilerpSampler - use a bilerp filter to create runs of destination pixels.
+template<SkColorType colorType, SkColorProfileType colorProfile, typename Next>
+class BilerpSampler : public SkLinearBitmapPipeline::SampleProcessorInterface {
+public:
+ template<typename... Args>
+ BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next, Args&& ... args)
+ : fNext{next}, fStrategy{std::forward<Args>(args)...} { }
- GeneralSampler& fSampler;
+ BilerpSampler(SkLinearBitmapPipeline::BlendProcessorInterface* next,
+ const BilerpSampler& sampler)
+ : fNext{next}, fStrategy{sampler.fStrategy} { }
+
+ Sk4f bilerpNonEdgePixel(SkScalar x, SkScalar y) {
+ Sk4f px00, px10, px01, px11;
+
+ // bilerp4() expects xs, ys are the top-lefts of the 2x2 kernel.
+ Sk4f xs = Sk4f{x} - 0.5f;
+ Sk4f ys = Sk4f{y} - 0.5f;
+ Sk4f sampleXs = xs + Sk4f{0.0f, 1.0f, 0.0f, 1.0f};
+ Sk4f sampleYs = ys + Sk4f{0.0f, 0.0f, 1.0f, 1.0f};
+ fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11);
+ return bilerp4(xs, ys, px00, px10, px01, px11);
+ }
+
+ void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
+ SkASSERT(0 < n && n < 4);
+ auto bilerpPixel = [&](int index) {
+ return this->bilerpNonEdgePixel(xs[index], ys[index]);
};
- NearestWrapper wrapper{*this};
- span_fallback(span, &wrapper);
+
+ if (n >= 1) fNext->blendPixel(bilerpPixel(0));
+ if (n >= 2) fNext->blendPixel(bilerpPixel(1));
+ if (n >= 3) fNext->blendPixel(bilerpPixel(2));
}
- void bilerpSpanZeroRate(Span span, SkScalar y1) {
+ void VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
+ auto bilerpPixel = [&](int index) {
+ return this->bilerpNonEdgePixel(xs[index], ys[index]);
+ };
+ fNext->blend4Pixels(bilerpPixel(0), bilerpPixel(1), bilerpPixel(2), bilerpPixel(3));
+ }
+
+ void pointSpan(Span span) override {
+ this->bilerpSpan(span, span.startY());
+ }
+
+ void repeatSpan(Span span, int32_t repeatCount) override {
+ while (repeatCount > 0) {
+ this->pointSpan(span);
+ repeatCount--;
+ }
+ }
+
+ void VECTORCALL bilerpEdge(Sk4s sampleXs, Sk4s sampleYs) override {
+ Sk4f px00, px10, px01, px11;
+ Sk4f xs = Sk4f{sampleXs[0]};
+ Sk4f ys = Sk4f{sampleYs[0]};
+ fStrategy.get4Pixels(sampleXs, sampleYs, &px00, &px10, &px01, &px11);
+ Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11);
+ fNext->blendPixel(pixel);
+ }
+
+ void bilerpSpan(Span span, SkScalar y) override {
+ SkASSERT(!span.isEmpty());
+ SkPoint start;
+ SkScalar length;
+ int count;
+ std::tie(start, length, count) = span;
+ SkScalar absLength = SkScalarAbs(length);
+ if (absLength == 0.0f) {
+ this->spanZeroRate(span, y);
+ } else if (absLength < (count - 1)) {
+ this->spanSlowRate(span, y);
+ } else if (absLength == (count - 1)) {
+ if (std::fmod(span.startX() - 0.5f, 1.0f) == 0.0f) {
+ if (std::fmod(span.startY() - 0.5f, 1.0f) == 0.0f) {
+ src_strategy_blend(span, fNext, &fStrategy);
+ } else {
+ this->spanUnitRateAlignedX(span, y);
+ }
+ } else {
+ this->spanUnitRate(span, y);
+ }
+ } else {
+ this->spanFastRate(span, y);
+ }
+ }
+
+private:
+ void spanZeroRate(Span span, SkScalar y1) {
SkScalar y0 = span.startY() - 0.5f;
y1 += 0.5f;
int iy0 = SkScalarFloorToInt(y0);
@@ -510,7 +541,7 @@ private:
// When moving through source space more slowly than dst space (zoomed in),
// we'll be sampling from the same source pixel more than once.
- void bilerpSpanSlowRate(Span span, SkScalar ry1) {
+ void spanSlowRate(Span span, SkScalar ry1) {
SkPoint start;
SkScalar length;
int count;
@@ -579,7 +610,7 @@ private:
// We're moving through source space at a rate of 1 source pixel per 1 dst pixel.
// We'll never re-use pixels, but we can at least load contiguous pixels.
- void bilerpSpanUnitRate(Span span, SkScalar y1) {
+ void spanUnitRate(Span span, SkScalar y1) {
y1 += 0.5f;
SkScalar y0 = span.startY() - 0.5f;
int iy0 = SkScalarFloorToInt(y0);
@@ -684,7 +715,7 @@ private:
}
}
- void bilerpSpanUnitRateAlignedX(Span span, SkScalar y1) {
+ void spanUnitRateAlignedX(Span span, SkScalar y1) {
SkScalar y0 = span.startY() - 0.5f;
y1 += 0.5f;
int iy0 = SkScalarFloorToInt(y0);
@@ -743,30 +774,19 @@ private:
// We're moving through source space faster than dst (zoomed out),
// so we'll never reuse a source pixel or be able to do contiguous loads.
- void bilerpSpanFastRate(Span span, SkScalar y1) {
+ void spanFastRate(Span span, SkScalar y1) {
SkPoint start;
SkScalar length;
int count;
std::tie(start, length, count) = span;
SkScalar x = X(start);
SkScalar y = Y(start);
+
// In this sampler, it is assumed that if span.StartY() and y1 are the same then both
// y-lines are on the same tile.
if (y == y1) {
// Both y-lines are on the same tile.
- struct BilerpWrapper {
- void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) {
- fSampler.bilerpListFew(n, xs, ys);
- }
-
- void VECTORCALL pointList4(Sk4s xs, Sk4s ys) {
- fSampler.bilerpList4(xs, ys);
- }
-
- GeneralSampler& fSampler;
- };
- BilerpWrapper wrapper{*this};
- span_fallback(span, &wrapper);
+ span_fallback(span, this);
} else {
// The y-lines are on different tiles.
SkScalar dx = length / (count - 1);
« no previous file with comments | « src/core/SkLinearBitmapPipeline_core.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698