Index: src/core/SkLinearBitmapPipeline.cpp |
diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp |
index 5a4f86daa7a2e83e6f10d53e8f38d41cb1e84a0e..f3b281aac77b4e126e0d887b6ab13fd6594d951d 100644 |
--- a/src/core/SkLinearBitmapPipeline.cpp |
+++ b/src/core/SkLinearBitmapPipeline.cpp |
@@ -14,6 +14,63 @@ |
#include "SkColor.h" |
#include "SkSize.h" |
+// 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 |
+ #elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON) |
+ #define VECTORCALL __attribute__((pcs("aapcs-vfp"))) |
+ #else |
+ #define VECTORCALL |
+ #endif |
+ |
+class SkLinearBitmapPipeline::PointProcessorInterface { |
+public: |
+ virtual ~PointProcessorInterface() { } |
+ virtual void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) = 0; |
+ virtual void VECTORCALL pointList4(Sk4f xs, Sk4f ys) = 0; |
+ |
+ // The pointSpan method efficiently process horizontal spans of pixels. |
+ // * start - the point where to start the span. |
+ // * length - the number of pixels to traverse in source space. |
+ // * count - the number of pixels to produce in destination space. |
+ // Both start and length are mapped through the inversion matrix to produce values in source |
+ // space. After the matrix operation, the tilers may break the spans up into smaller spans. |
+ // The tilers can produce spans that seem nonsensical. |
+ // * The clamp tiler can create spans with length of 0. This indicates to copy an edge pixel out |
+ // to the edge of the destination scan. |
+ // * The mirror tiler can produce spans with negative length. This indicates that the source |
+ // should be traversed in the opposite direction to the destination pixels. |
+ virtual void pointSpan(SkPoint start, SkScalar length, int count) = 0; |
+}; |
+ |
+class SkLinearBitmapPipeline::BilerpProcessorInterface |
+ : public SkLinearBitmapPipeline::PointProcessorInterface { |
+public: |
+ // The x's and y's are setup in the following order: |
+ // +--------+--------+ |
+ // | | | |
+ // | px00 | px10 | |
+ // | 0 | 1 | |
+ // +--------+--------+ |
+ // | | | |
+ // | px01 | px11 | |
+ // | 2 | 3 | |
+ // +--------+--------+ |
+ // These pixels coordinates are arranged in the following order in xs and ys: |
+ // px00 px10 px01 px11 |
+ virtual void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) = 0; |
+}; |
+ |
+class SkLinearBitmapPipeline::PixelPlacerInterface { |
+public: |
+ virtual ~PixelPlacerInterface() { } |
+ virtual void setDestination(SkPM4f* dst) = 0; |
+ virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; |
+ virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0; |
+}; |
+ |
+namespace { |
+ |
struct X { |
explicit X(SkScalar val) : fVal{val} { } |
explicit X(SkPoint pt) : fVal{pt.fX} { } |
@@ -68,21 +125,21 @@ void span_fallback(SkPoint start, SkScalar length, int count, Stage* stage) { |
// maybeProcessSpan - returns false if it can not process the span and needs to fallback to |
// point lists for processing. |
template<typename Strategy, typename Next> |
-class PointProcessor final : public PointProcessorInterface { |
+class PointProcessor final : public SkLinearBitmapPipeline::PointProcessorInterface { |
public: |
template <typename... Args> |
PointProcessor(Next* next, Args&&... args) |
: fNext{next} |
, fStrategy{std::forward<Args>(args)...}{ } |
- void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
Sk4f newXs = xs; |
Sk4f newYs = ys; |
f(malita)
2016/02/22 22:48:08
Are the locals still needed?
mtklein
2016/02/22 23:00:55
Nope.
|
fStrategy.processPoints(&newXs, &newYs); |
fNext->pointListFew(n, newXs, newYs); |
} |
- void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
Sk4f newXs = xs; |
Sk4f newYs = ys; |
fStrategy.processPoints(&newXs, &newYs); |
@@ -102,28 +159,28 @@ private: |
// See PointProcessor for responsibilities of Strategy. |
template<typename Strategy, typename Next> |
-class BilerpProcessor final : public BilerpProcessorInterface { |
+class BilerpProcessor final : public SkLinearBitmapPipeline::BilerpProcessorInterface { |
public: |
template <typename... Args> |
BilerpProcessor(Next* next, Args&&... args) |
: fNext{next} |
, fStrategy{std::forward<Args>(args)...}{ } |
- void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
Sk4f newXs = xs; |
Sk4f newYs = ys; |
fStrategy.processPoints(&newXs, &newYs); |
fNext->pointListFew(n, newXs, newYs); |
} |
- void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
Sk4f newXs = xs; |
Sk4f newYs = ys; |
fStrategy.processPoints(&newXs, &newYs); |
fNext->pointList4(newXs, newYs); |
} |
- void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { |
Sk4f newXs = xs; |
Sk4f newYs = ys; |
fStrategy.processPoints(&newXs, &newYs); |
@@ -141,14 +198,14 @@ private: |
Strategy fStrategy; |
}; |
-class SkippedStage final : public BilerpProcessorInterface { |
- void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
+class SkippedStage final : public SkLinearBitmapPipeline::BilerpProcessorInterface { |
+ void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
SkFAIL("Skipped stage."); |
} |
- void pointList4(Sk4fArg Xs, Sk4fArg Ys) override { |
+ void VECTORCALL pointList4(Sk4f Xs, Sk4f Ys) override { |
SkFAIL("Skipped stage."); |
} |
- void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { |
SkFAIL("Skipped stage."); |
} |
void pointSpan(SkPoint start, SkScalar length, int count) override { |
@@ -176,7 +233,7 @@ public: |
private: |
const Sk4f fXOffset, fYOffset; |
}; |
-template <typename Next = PointProcessorInterface> |
+template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> |
using TranslateMatrix = PointProcessor<TranslateMatrixStrategy, Next>; |
class ScaleMatrixStrategy { |
@@ -202,7 +259,7 @@ private: |
const Sk4f fXOffset, fYOffset; |
const Sk4f fXScale, fYScale; |
}; |
-template <typename Next = PointProcessorInterface> |
+template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> |
using ScaleMatrix = PointProcessor<ScaleMatrixStrategy, Next>; |
class AffineMatrixStrategy { |
@@ -229,11 +286,11 @@ private: |
const Sk4f fXScale, fYScale; |
const Sk4f fXSkew, fYSkew; |
}; |
-template <typename Next = PointProcessorInterface> |
+template <typename Next = SkLinearBitmapPipeline::PointProcessorInterface> |
using AffineMatrix = PointProcessor<AffineMatrixStrategy, Next>; |
-static PointProcessorInterface* choose_matrix( |
- PointProcessorInterface* next, |
+static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( |
+ SkLinearBitmapPipeline::PointProcessorInterface* next, |
const SkMatrix& inverse, |
SkLinearBitmapPipeline::MatrixStage* matrixProc) { |
if (inverse.hasPerspective()) { |
@@ -260,12 +317,12 @@ static PointProcessorInterface* choose_matrix( |
return matrixProc->get(); |
} |
-template <typename Next = BilerpProcessorInterface> |
-class ExpandBilerp final : public PointProcessorInterface { |
+template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
+class ExpandBilerp final : public SkLinearBitmapPipeline::PointProcessorInterface { |
public: |
ExpandBilerp(Next* next) : fNext{next} { } |
- void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
SkASSERT(0 < n && n < 4); |
// px00 px10 px01 px11 |
const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, |
@@ -275,7 +332,7 @@ public: |
if (n >= 3) fNext->bilerpList(Sk4f{xs[2]} + kXOffsets, Sk4f{ys[2]} + kYOffsets); |
} |
- void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
// px00 px10 px01 px11 |
const Sk4f kXOffsets{-0.5f, 0.5f, -0.5f, 0.5f}, |
kYOffsets{-0.5f, -0.5f, 0.5f, 0.5f}; |
@@ -293,8 +350,8 @@ private: |
Next* const fNext; |
}; |
-static PointProcessorInterface* choose_filter( |
- BilerpProcessorInterface* next, |
+static SkLinearBitmapPipeline::PointProcessorInterface* choose_filter( |
+ SkLinearBitmapPipeline::BilerpProcessorInterface* next, |
SkFilterQuality filterQuailty, |
SkLinearBitmapPipeline::FilterStage* filterProc) { |
if (SkFilterQuality::kNone_SkFilterQuality == filterQuailty) { |
@@ -336,7 +393,7 @@ private: |
const Sk4f fXMax{SK_FloatInfinity}; |
const Sk4f fYMax{SK_FloatInfinity}; |
}; |
-template <typename Next = BilerpProcessorInterface> |
+template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
using Clamp = BilerpProcessor<ClampStrategy, Next>; |
class RepeatStrategy { |
@@ -370,11 +427,11 @@ private: |
const Sk4f fYInvMax{0.0f}; |
}; |
-template <typename Next = BilerpProcessorInterface> |
+template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
using Repeat = BilerpProcessor<RepeatStrategy, Next>; |
-static BilerpProcessorInterface* choose_tiler( |
- BilerpProcessorInterface* next, |
+static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_tiler( |
+ SkLinearBitmapPipeline::BilerpProcessorInterface* next, |
SkSize dimensions, |
SkShader::TileMode xMode, |
SkShader::TileMode yMode, |
@@ -422,7 +479,7 @@ static BilerpProcessorInterface* choose_tiler( |
class sRGBFast { |
public: |
- static Sk4f sRGBToLinear(Sk4fArg pixel) { |
+ static Sk4f VECTORCALL sRGBToLinear(Sk4f pixel) { |
Sk4f l = pixel * pixel; |
return Sk4f{l[0], l[1], l[2], pixel[3]}; |
} |
@@ -434,7 +491,7 @@ public: |
Passthrough8888(int width, const uint32_t* src) |
: fSrc{src}, fWidth{width}{ } |
- void getFewPixels(int n, Sk4fArg xs, Sk4fArg ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { |
+ void VECTORCALL getFewPixels(int n, Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2) { |
Sk4i XIs = SkNx_cast<int, float>(xs); |
Sk4i YIs = SkNx_cast<int, float>(ys); |
Sk4i bufferLoc = YIs * fWidth + XIs; |
@@ -450,7 +507,7 @@ public: |
} |
} |
- void get4Pixels(Sk4fArg xs, Sk4fArg ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3) { |
+ void VECTORCALL get4Pixels(Sk4f xs, Sk4f ys, Sk4f* px0, Sk4f* px1, Sk4f* px2, Sk4f* px3) { |
Sk4i XIs = SkNx_cast<int, float>(xs); |
Sk4i YIs = SkNx_cast<int, float>(ys); |
Sk4i bufferLoc = YIs * fWidth + XIs; |
@@ -496,8 +553,8 @@ private: |
// * px01 -> (1 - x)y = y - xy |
// * px11 -> xy |
// So x * y is calculated first and then used to calculate all the other factors. |
-static Sk4f bilerp4(Sk4fArg xs, Sk4fArg ys, Sk4fArg px00, Sk4fArg px10, |
- Sk4fArg px01, Sk4fArg px11) { |
+static Sk4f VECTORCALL bilerp4(Sk4f xs, Sk4f ys, Sk4f px00, Sk4f px10, |
+ Sk4f px01, Sk4f px11) { |
// Calculate fractional xs and ys. |
Sk4f fxs = xs - xs.floor(); |
Sk4f fys = ys - ys.floor(); |
@@ -510,14 +567,14 @@ static Sk4f bilerp4(Sk4fArg xs, Sk4fArg ys, Sk4fArg px00, Sk4fArg px10, |
} |
template <typename SourceStrategy> |
-class Sampler final : public BilerpProcessorInterface { |
+class Sampler final : public SkLinearBitmapPipeline::BilerpProcessorInterface { |
public: |
template <typename... Args> |
- Sampler(PixelPlacerInterface* next, Args&&... args) |
+ Sampler(SkLinearBitmapPipeline::PixelPlacerInterface* next, Args&&... args) |
: fNext{next} |
, fStrategy{std::forward<Args>(args)...} { } |
- void pointListFew(int n, Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointListFew(int n, Sk4f xs, Sk4f ys) override { |
SkASSERT(0 < n && n < 4); |
Sk4f px0, px1, px2; |
fStrategy.getFewPixels(n, xs, ys, &px0, &px1, &px2); |
@@ -526,13 +583,13 @@ public: |
if (n >= 3) fNext->placePixel(px2); |
} |
- void pointList4(Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL pointList4(Sk4f xs, Sk4f ys) override { |
Sk4f px0, px1, px2, px3; |
fStrategy.get4Pixels(xs, ys, &px0, &px1, &px2, &px3); |
fNext->place4Pixels(px0, px1, px2, px3); |
} |
- void bilerpList(Sk4fArg xs, Sk4fArg ys) override { |
+ void VECTORCALL bilerpList(Sk4f xs, Sk4f ys) override { |
Sk4f px00, px10, px01, px11; |
fStrategy.get4Pixels(xs, ys, &px00, &px10, &px01, &px11); |
Sk4f pixel = bilerp4(xs, ys, px00, px10, px01, px11); |
@@ -544,12 +601,12 @@ public: |
} |
private: |
- PixelPlacerInterface* const fNext; |
+ SkLinearBitmapPipeline::PixelPlacerInterface* const fNext; |
SourceStrategy fStrategy; |
}; |
-static BilerpProcessorInterface* choose_pixel_sampler( |
- PixelPlacerInterface* next, |
+static SkLinearBitmapPipeline::BilerpProcessorInterface* choose_pixel_sampler( |
+ SkLinearBitmapPipeline::PixelPlacerInterface* next, |
const SkPixmap& srcPixmap, |
SkLinearBitmapPipeline::SampleStage* sampleStage) { |
const SkImageInfo& imageInfo = srcPixmap.info(); |
@@ -578,14 +635,14 @@ static BilerpProcessorInterface* choose_pixel_sampler( |
} |
template <SkAlphaType alphaType> |
-class PlaceFPPixel final : public PixelPlacerInterface { |
+class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface { |
public: |
- void placePixel(Sk4fArg pixel) override { |
+ void VECTORCALL placePixel(Sk4f pixel) override { |
PlacePixel(fDst, pixel, 0); |
fDst += 1; |
} |
- void place4Pixels(Sk4fArg p0, Sk4fArg p1, Sk4fArg p2, Sk4fArg p3) override { |
+ void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { |
SkPM4f* dst = fDst; |
PlacePixel(dst, p0, 0); |
PlacePixel(dst, p1, 1); |
@@ -599,14 +656,14 @@ public: |
} |
private: |
- static void PlacePixel(SkPM4f* dst, Sk4fArg pixel, int index) { |
+ static void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) { |
Sk4f newPixel = pixel; |
if (alphaType == kUnpremul_SkAlphaType) { |
newPixel = Premultiply(pixel); |
} |
newPixel.store(dst + index); |
} |
- static Sk4f Premultiply(Sk4fArg pixel) { |
+ static Sk4f VECTORCALL Premultiply(Sk4f pixel) { |
float alpha = pixel[3]; |
return pixel * Sk4f{alpha, alpha, alpha, 1.0f}; |
} |
@@ -614,7 +671,7 @@ private: |
SkPM4f* fDst; |
}; |
-static PixelPlacerInterface* choose_pixel_placer( |
+static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer( |
SkAlphaType alphaType, |
SkLinearBitmapPipeline::PixelStage* placerStage) { |
if (alphaType == kUnpremul_SkAlphaType) { |
@@ -625,6 +682,9 @@ static PixelPlacerInterface* choose_pixel_placer( |
} |
return placerStage->get(); |
} |
+} // namespace |
+ |
+SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {} |
SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
const SkMatrix& inverse, |