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

Unified Diff: src/core/SkLinearBitmapPipeline.cpp

Issue 2174793002: Revert of Redo Tiling (Closed) Base URL: https://skia.googlesource.com/skia.git@reduce-LBP-sample
Patch Set: Created 4 years, 5 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') | src/core/SkLinearBitmapPipeline_core.h » ('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 01227657098d9aaf2479a9f0cff29d419f8a09cf..088e829345f016f3b06a84dc83cdef2f13dcbef2 100644
--- a/src/core/SkLinearBitmapPipeline.cpp
+++ b/src/core/SkLinearBitmapPipeline.cpp
@@ -165,14 +165,15 @@
// Tile Stage
template<typename XStrategy, typename YStrategy, typename Next>
-class CombinedTileStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
+class NearestTileStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
public:
- CombinedTileStage(Next* next, SkISize dimensions)
+ template <typename... Args>
+ NearestTileStage(Next* next, SkISize dimensions)
: fNext{next}
, fXStrategy{dimensions.width()}
, fYStrategy{dimensions.height()}{ }
- CombinedTileStage(Next* next, const CombinedTileStage& stage)
+ NearestTileStage(Next* next, const NearestTileStage& stage)
: fNext{next}
, fXStrategy{stage.fXStrategy}
, fYStrategy{stage.fYStrategy} { }
@@ -194,16 +195,9 @@
SkASSERT(!span.isEmpty());
SkPoint start; SkScalar length; int count;
std::tie(start, length, count) = span;
-
- if (span.count() == 1) {
- this->pointListFew(1, span.startX(), span.startY());
- return;
- }
-
SkScalar x = X(start);
SkScalar y = fYStrategy.tileY(Y(start));
Span yAdjustedSpan{{x, y}, length, count};
-
if (!fXStrategy.maybeProcessSpan(yAdjustedSpan, fNext)) {
span_fallback(span, this);
}
@@ -215,27 +209,173 @@
YStrategy fYStrategy;
};
-template <typename XStrategy, typename Next>
+template<typename XStrategy, typename YStrategy, typename Next>
+class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInterface {
+public:
+ template <typename... Args>
+ BilerpTileStage(Next* next, SkISize dimensions)
+ : fNext{next}
+ , fXMax(dimensions.width())
+ , fYMax(dimensions.height())
+ , fXStrategy{dimensions.width()}
+ , fYStrategy{dimensions.height()} { }
+
+ BilerpTileStage(Next* next, const BilerpTileStage& stage)
+ : fNext{next}
+ , fXMax{stage.fXMax}
+ , fYMax{stage.fYMax}
+ , fXStrategy{stage.fXStrategy}
+ , fYStrategy{stage.fYStrategy} { }
+
+ void SK_VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override {
+ fXStrategy.tileXPoints(&xs);
+ fYStrategy.tileYPoints(&ys);
+ // TODO: check to see if xs and ys are in range then just call pointListFew on next.
+ if (n >= 1) this->bilerpPoint(xs[0], ys[0]);
+ if (n >= 2) this->bilerpPoint(xs[1], ys[1]);
+ if (n >= 3) this->bilerpPoint(xs[2], ys[2]);
+ }
+
+ void SK_VECTORCALL pointList4(Sk4s xs, Sk4s ys) override {
+ fXStrategy.tileXPoints(&xs);
+ fYStrategy.tileYPoints(&ys);
+ // TODO: check to see if xs and ys are in range then just call pointList4 on next.
+ this->bilerpPoint(xs[0], ys[0]);
+ this->bilerpPoint(xs[1], ys[1]);
+ this->bilerpPoint(xs[2], ys[2]);
+ this->bilerpPoint(xs[3], ys[3]);
+ }
+
+ struct Wrapper {
+ void pointSpan(Span span) {
+ processor->breakIntoEdges(span);
+ }
+
+ void repeatSpan(Span span, int32_t repeatCount) {
+ while (repeatCount --> 0) {
+ processor->pointSpan(span);
+ }
+ }
+
+ BilerpTileStage* processor;
+ };
+
+ // The span you pass must not be empty.
+ void pointSpan(Span span) override {
+ SkASSERT(!span.isEmpty());
+
+ Wrapper wrapper = {this};
+ if (!fXStrategy.maybeProcessSpan(span, &wrapper)) {
+ span_fallback(span, this);
+ }
+ }
+
+private:
+ void bilerpPoint(SkScalar x, SkScalar y) {
+ Sk4f txs = Sk4f{x} + Sk4f{-0.5f, 0.5f, -0.5f, 0.5f};
+ Sk4f tys = Sk4f{y} + Sk4f{-0.5f, -0.5f, 0.5f, 0.5f};
+ fXStrategy.tileXPoints(&txs);
+ fYStrategy.tileYPoints(&tys);
+ fNext->bilerpEdge(txs, tys);
+ }
+
+ void handleEdges(Span span, SkScalar dx) {
+ SkPoint start; SkScalar length; int count;
+ std::tie(start, length, count) = span;
+ SkScalar x = X(start);
+ SkScalar y = Y(start);
+ SkScalar tiledY = fYStrategy.tileY(y);
+ while (count > 0) {
+ this->bilerpPoint(x, tiledY);
+ x += dx;
+ count -= 1;
+ }
+ }
+
+ void yProcessSpan(Span span) {
+ SkScalar tiledY = fYStrategy.tileY(span.startY());
+ if (0.5f <= tiledY && tiledY < fYMax - 0.5f ) {
+ Span tiledSpan{{span.startX(), tiledY}, span.length(), span.count()};
+ fNext->pointSpan(tiledSpan);
+ } else {
+ // Convert to the Y0 bilerp sample set by shifting by -0.5f. Then tile that new y
+ // value and shift it back resulting in the working Y0. Do the same thing with Y1 but
+ // in the opposite direction.
+ SkScalar y0 = fYStrategy.tileY(span.startY() - 0.5f) + 0.5f;
+ SkScalar y1 = fYStrategy.tileY(span.startY() + 0.5f) - 0.5f;
+ Span newSpan{{span.startX(), y0}, span.length(), span.count()};
+ fNext->bilerpSpan(newSpan, y1);
+ }
+ }
+ void breakIntoEdges(Span span) {
+ if (span.count() == 1) {
+ this->bilerpPoint(span.startX(), span.startY());
+ } else if (span.length() == 0) {
+ yProcessSpan(span);
+ } else {
+ SkScalar dx = span.length() / (span.count() - 1);
+ if (span.length() > 0) {
+ Span leftBorder = span.breakAt(0.5f, dx);
+ if (!leftBorder.isEmpty()) {
+ this->handleEdges(leftBorder, dx);
+ }
+ Span center = span.breakAt(fXMax - 0.5f, dx);
+ if (!center.isEmpty()) {
+ this->yProcessSpan(center);
+ }
+
+ if (!span.isEmpty()) {
+ this->handleEdges(span, dx);
+ }
+ } else {
+ Span center = span.breakAt(fXMax + 0.5f, dx);
+ if (!span.isEmpty()) {
+ this->handleEdges(span, dx);
+ }
+ Span leftEdge = center.breakAt(0.5f, dx);
+ if (!center.isEmpty()) {
+ this->yProcessSpan(center);
+ }
+ if (!leftEdge.isEmpty()) {
+ this->handleEdges(leftEdge, dx);
+ }
+
+ }
+ }
+ }
+
+ Next* const fNext;
+ SkScalar fXMax;
+ SkScalar fYMax;
+ XStrategy fXStrategy;
+ YStrategy fYStrategy;
+};
+
+template <typename XStrategy, typename YStrategy, typename Next>
+void make_tile_stage(
+ SkFilterQuality filterQuality, SkISize dimensions,
+ Next* next, SkLinearBitmapPipeline::TileStage* tileStage) {
+ if (filterQuality == kNone_SkFilterQuality) {
+ tileStage->initStage<NearestTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
+ } else {
+ tileStage->initStage<BilerpTileStage<XStrategy, YStrategy, Next>>(next, dimensions);
+ }
+}
+template <typename XStrategy>
void choose_tiler_ymode(
SkShader::TileMode yMode, SkFilterQuality filterQuality, SkISize dimensions,
- Next* next,
+ SkLinearBitmapPipeline::SampleProcessorInterface* next,
SkLinearBitmapPipeline::TileStage* tileStage) {
switch (yMode) {
- case SkShader::kClamp_TileMode: {
- using Tiler = CombinedTileStage<XStrategy, YClampStrategy, Next>;
- tileStage->initStage<Tiler>(next, dimensions);
- break;
- }
- case SkShader::kRepeat_TileMode: {
- using Tiler = CombinedTileStage<XStrategy, YRepeatStrategy, Next>;
- tileStage->initStage<Tiler>(next, dimensions);
- break;
- }
- case SkShader::kMirror_TileMode: {
- using Tiler = CombinedTileStage<XStrategy, YMirrorStrategy, Next>;
- tileStage->initStage<Tiler>(next, dimensions);
- break;
- }
+ case SkShader::kClamp_TileMode:
+ make_tile_stage<XStrategy, YClampStrategy>(filterQuality, dimensions, next, tileStage);
+ break;
+ case SkShader::kRepeat_TileMode:
+ make_tile_stage<XStrategy, YRepeatStrategy>(filterQuality, dimensions, next, tileStage);
+ break;
+ case SkShader::kMirror_TileMode:
+ make_tile_stage<XStrategy, YMirrorStrategy>(filterQuality, dimensions, next, tileStage);
+ break;
}
};
@@ -327,6 +467,10 @@
fDest = dest;
}
+ void SK_VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Implemented"); }
+
+ void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented"); }
+
void setDestination(void* dst, int count) override {
fDest = static_cast<uint32_t*>(dst);
fEnd = fDest + count;
@@ -393,6 +537,10 @@
SkASSERT(fDest <= fEnd);
}
+
+ void SK_VECTORCALL bilerpEdge(Sk4s xs, Sk4s ys) override { SkFAIL("Not Implemented"); }
+
+ void bilerpSpan(Span span, SkScalar y) override { SkFAIL("Not Implemented"); }
void setDestination(void* dst, int count) override {
SkASSERT(count > 0);
@@ -434,9 +582,12 @@
}
}
-static SkLinearBitmapPipeline::PixelAccessorInterface* choose_pixel_accessor(
+template<template <typename, typename> class Sampler>
+static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_base(
+ Blender* next,
const SkPixmap& srcPixmap,
const SkColor A8TintColor,
+ SkLinearBitmapPipeline::SampleStage* sampleStage,
SkLinearBitmapPipeline::Accessor* accessor)
{
const SkImageInfo& imageInfo = srcPixmap.info();
@@ -478,19 +629,19 @@
break;
}
- return pixelAccessor;
+ using S = Sampler<PixelAccessorShim, Blender>;
+ sampleStage->initStage<S>(next, pixelAccessor);
+ return sampleStage->get();
}
SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler(
Blender* next,
SkFilterQuality filterQuality,
- SkShader::TileMode xTile, SkShader::TileMode yTile,
const SkPixmap& srcPixmap,
const SkColor A8TintColor,
SkLinearBitmapPipeline::SampleStage* sampleStage,
SkLinearBitmapPipeline::Accessor* accessor) {
const SkImageInfo& imageInfo = srcPixmap.info();
- SkISize dimensions = imageInfo.dimensions();
// Special case samplers with fully expanded templates
if (imageInfo.gammaCloseToSRGB()) {
@@ -519,14 +670,14 @@
using S =
BilerpSampler<
PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
- sampleStage->initStage<S>(next, dimensions, xTile, yTile, srcPixmap);
+ sampleStage->initStage<S>(next, srcPixmap);
return sampleStage->get();
}
case kIndex_8_SkColorType: {
using S =
BilerpSampler<
PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
- sampleStage->initStage<S>(next, dimensions, xTile, yTile, srcPixmap);
+ sampleStage->initStage<S>(next, srcPixmap);
return sampleStage->get();
}
default:
@@ -535,16 +686,14 @@
}
}
- auto pixelAccessor = choose_pixel_accessor(srcPixmap, A8TintColor, accessor);
// General cases.
if (filterQuality == kNone_SkFilterQuality) {
- using S = NearestNeighborSampler<PixelAccessorShim, Blender>;
- sampleStage->initStage<S>(next, pixelAccessor);
+ return choose_pixel_sampler_base<NearestNeighborSampler>(
+ next, srcPixmap, A8TintColor, sampleStage, accessor);
} else {
- using S = BilerpSampler<PixelAccessorShim, Blender>;
- sampleStage->initStage<S>(next, dimensions, xTile, yTile, pixelAccessor);
- }
- return sampleStage->get();
+ return choose_pixel_sampler_base<BilerpSampler>(
+ next, srcPixmap, A8TintColor, sampleStage, accessor);
+ }
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -556,17 +705,17 @@
SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {}
void SK_VECTORCALL blendPixel(Sk4f pixel) override {
SkASSERT(fDst + 1 <= fEnd );
- this->srcPixel(fDst, pixel, 0);
+ SrcPixel(fDst, pixel, 0);
fDst += 1;
}
void SK_VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override {
SkASSERT(fDst + 4 <= fEnd);
SkPM4f* dst = fDst;
- this->srcPixel(dst, p0, 0);
- this->srcPixel(dst, p1, 1);
- this->srcPixel(dst, p2, 2);
- this->srcPixel(dst, p3, 3);
+ SrcPixel(dst, p0, 0);
+ SrcPixel(dst, p1, 1);
+ SrcPixel(dst, p2, 2);
+ SrcPixel(dst, p3, 3);
fDst += 4;
}
@@ -576,9 +725,7 @@
}
private:
- void SK_VECTORCALL srcPixel(SkPM4f* dst, Sk4f pixel, int index) {
- check_pixel(pixel);
-
+ void SK_VECTORCALL SrcPixel(SkPM4f* dst, Sk4f pixel, int index) {
Sk4f newPixel = pixel;
if (alphaType == kUnpremul_SkAlphaType) {
newPixel = Premultiply(pixel);
@@ -650,8 +797,7 @@
// identity matrix, the matrix stage is skipped, and the tilerStage is the first stage.
auto blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlenderStage);
auto samplerStage = choose_pixel_sampler(
- blenderStage, filterQuality, xTile, yTile,
- srcPixmap, paintColor, &fSampleStage, &fAccessor);
+ blenderStage, filterQuality, srcPixmap, paintColor, &fSampleStage, &fAccessor);
auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile,
filterQuality, dx, &fTileStage);
fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage);
« no previous file with comments | « src/core/SkLinearBitmapPipeline.h ('k') | src/core/SkLinearBitmapPipeline_core.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698