Index: src/core/SkLinearBitmapPipeline.cpp |
diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp |
index dc2ee513ca259b00ac577190c4b1c38f51744fbf..539547af9a903288f63a772e9a7be08b9666a614 100644 |
--- a/src/core/SkLinearBitmapPipeline.cpp |
+++ b/src/core/SkLinearBitmapPipeline.cpp |
@@ -65,21 +65,66 @@ public: |
class SkLinearBitmapPipeline::DestinationInterface { |
public: |
virtual ~DestinationInterface() { } |
+ // Count is normally not needed, but in these early stages of development it is useful to |
+ // check bounds. |
+ // TODO(herb): 4/6/2016 - remove count when code is stable. |
virtual void setDestination(void* dst, int count) = 0; |
}; |
-class SkLinearBitmapPipeline::PixelPlacerInterface |
+class SkLinearBitmapPipeline::BlendProcessorInterface |
: public SkLinearBitmapPipeline::DestinationInterface { |
public: |
- virtual ~PixelPlacerInterface() { } |
- // Count is normally not needed, but in these early stages of development it is useful to |
- // check bounds. |
- // TODO(herb): 4/6/2016 - remove count when code is stable. |
- virtual void setDestination(void* dst, int count) = 0; |
- virtual void VECTORCALL placePixel(Sk4f pixel0) = 0; |
- virtual void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0; |
+ virtual void VECTORCALL blendPixel(Sk4f pixel0) = 0; |
+ virtual void VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) = 0; |
}; |
+//////////////////////////////////////////////////////////////////////////////////////////////////// |
+// SkLinearBitmapPipeline::Stage |
+template<typename Base, size_t kSize, typename Next> |
+SkLinearBitmapPipeline::Stage<Base, kSize, Next>::~Stage() { |
+ if (fIsInitialized) { |
+ this->get()->~Base(); |
+ } |
+} |
+ |
+template<typename Base, size_t kSize, typename Next> |
+template<typename Variant, typename... Args> |
+void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initStage(Next* next, Args&& ... args) { |
+ SkASSERTF(sizeof(Variant) <= sizeof(fSpace), |
+ "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace)); |
+ |
+ new (&fSpace) Variant(next, std::forward<Args>(args)...); |
+ fStageCloner = [this](Next* nextClone, void* addr) { |
+ new (addr) Variant(nextClone, (const Variant&)*this->get()); |
+ }; |
+ fIsInitialized = true; |
+}; |
+ |
+template<typename Base, size_t kSize, typename Next> |
+template<typename Variant, typename... Args> |
+void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initSink(Args&& ... args) { |
+ SkASSERTF(sizeof(Variant) <= sizeof(fSpace), |
+ "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace)); |
+ new (&fSpace) Variant(std::forward<Args>(args)...); |
+ fIsInitialized = true; |
+}; |
+ |
+template<typename Base, size_t kSize, typename Next> |
+template <typename To, typename From> |
+To* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::getInterface() { |
+ From* down = static_cast<From*>(this->get()); |
+ return static_cast<To*>(down); |
+} |
+ |
+template<typename Base, size_t kSize, typename Next> |
+Base* SkLinearBitmapPipeline::Stage<Base, kSize, Next>::cloneStageTo( |
+ Next* next, Stage* cloneToStage) const |
+{ |
+ if (!fIsInitialized) return nullptr; |
+ fStageCloner(next, &cloneToStage->fSpace); |
+ return cloneToStage->get(); |
+} |
+ |
namespace { |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
@@ -101,6 +146,10 @@ public: |
: fNext{next} |
, fStrategy{std::forward<Args>(args)...}{ } |
+ MatrixStage(Next* next, const MatrixStage& stage) |
+ : fNext{next} |
+ , fStrategy{stage.fStrategy} { } |
+ |
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
fStrategy.processPoints(&xs, &ys); |
fNext->pointListFew(n, xs, ys); |
@@ -142,7 +191,7 @@ static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( |
const SkMatrix& inverse, |
SkLinearBitmapPipeline::MatrixStage* matrixProc) { |
if (inverse.hasPerspective()) { |
- matrixProc->Initialize<PerspectiveMatrix<>>( |
+ matrixProc->initStage<PerspectiveMatrix<>>( |
next, |
SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
SkVector{inverse.getScaleX(), inverse.getScaleY()}, |
@@ -150,18 +199,18 @@ static SkLinearBitmapPipeline::PointProcessorInterface* choose_matrix( |
SkVector{inverse.getPerspX(), inverse.getPerspY()}, |
inverse.get(SkMatrix::kMPersp2)); |
} else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) { |
- matrixProc->Initialize<AffineMatrix<>>( |
+ matrixProc->initStage<AffineMatrix<>>( |
next, |
SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
SkVector{inverse.getScaleX(), inverse.getScaleY()}, |
SkVector{inverse.getSkewX(), inverse.getSkewY()}); |
} else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) { |
- matrixProc->Initialize<ScaleMatrix<>>( |
+ matrixProc->initStage<ScaleMatrix<>>( |
next, |
SkVector{inverse.getTranslateX(), inverse.getTranslateY()}, |
SkVector{inverse.getScaleX(), inverse.getScaleY()}); |
} else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0f) { |
- matrixProc->Initialize<TranslateMatrix<>>( |
+ matrixProc->initStage<TranslateMatrix<>>( |
next, |
SkVector{inverse.getTranslateX(), inverse.getTranslateY()}); |
} else { |
@@ -182,6 +231,11 @@ public: |
, fXStrategy{dimensions.width()} |
, fYStrategy{dimensions.height()}{ } |
+ NearestTileStage(Next* next, const NearestTileStage& stage) |
+ : fNext{next} |
+ , fXStrategy{stage.fXStrategy} |
+ , fYStrategy{stage.fYStrategy} { } |
+ |
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
fXStrategy.tileXPoints(&xs); |
fYStrategy.tileYPoints(&ys); |
@@ -218,11 +272,18 @@ class BilerpTileStage final : public SkLinearBitmapPipeline::PointProcessorInter |
public: |
template <typename... Args> |
BilerpTileStage(Next* next, SkISize dimensions) |
- : fXMax(dimensions.width()) |
+ : fNext{next} |
+ , fXMax(dimensions.width()) |
, fYMax(dimensions.height()) |
- , fNext{next} |
, fXStrategy{dimensions.width()} |
- , fYStrategy{dimensions.height()}{ } |
+ , fYStrategy{dimensions.height()} { } |
+ |
+ BilerpTileStage(Next* next, const BilerpTileStage& stage) |
+ : fNext{next} |
+ , fXMax{stage.fXMax} |
+ , fYMax{stage.fYMax} |
+ , fXStrategy{stage.fXStrategy} |
+ , fYStrategy{stage.fYStrategy} { } |
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
fXStrategy.tileXPoints(&xs); |
@@ -339,9 +400,9 @@ private: |
} |
} |
+ Next* const fNext; |
SkScalar fXMax; |
SkScalar fYMax; |
- Next* const fNext; |
XStrategy fXStrategy; |
YStrategy fYStrategy; |
}; |
@@ -351,9 +412,9 @@ void make_tile_stage( |
SkFilterQuality filterQuality, SkISize dimensions, |
Next* next, SkLinearBitmapPipeline::TileStage* tileStage) { |
if (filterQuality == kNone_SkFilterQuality) { |
- tileStage->Initialize<NearestTileStage<XStrategy, YStrategy, Next>>(next, dimensions); |
+ tileStage->initStage<NearestTileStage<XStrategy, YStrategy, Next>>(next, dimensions); |
} else { |
- tileStage->Initialize<BilerpTileStage<XStrategy, YStrategy, Next>>(next, dimensions); |
+ tileStage->initStage<BilerpTileStage<XStrategy, YStrategy, Next>>(next, dimensions); |
} |
} |
template <typename XStrategy> |
@@ -413,6 +474,9 @@ public: |
NearestNeighborSampler(Next* next, Args&&... args) |
: fSampler{next, std::forward<Args>(args)...} { } |
+ NearestNeighborSampler(Next* next, const NearestNeighborSampler& sampler) |
+ : fSampler{next, sampler.fSampler} { } |
+ |
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
fSampler.nearestListFew(n, xs, ys); |
} |
@@ -451,6 +515,9 @@ public: |
BilerpSampler(Next* next, Args&&... args) |
: fSampler{next, std::forward<Args>(args)...} { } |
+ BilerpSampler(Next* next, const BilerpSampler& sampler) |
+ : fSampler{next, sampler.fSampler} { } |
+ |
void VECTORCALL pointListFew(int n, Sk4s xs, Sk4s ys) override { |
fSampler.bilerpListFew(n, xs, ys); |
} |
@@ -554,34 +621,34 @@ private: |
uint32_t* fEnd; |
}; |
-using Placer = SkLinearBitmapPipeline::PixelPlacerInterface; |
+using Blender = SkLinearBitmapPipeline::BlendProcessorInterface; |
template<template <typename, typename> class Sampler> |
static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_base( |
- Placer* next, |
+ Blender* next, |
const SkPixmap& srcPixmap, |
SkLinearBitmapPipeline::SampleStage* sampleStage) { |
const SkImageInfo& imageInfo = srcPixmap.info(); |
switch (imageInfo.colorType()) { |
case kRGBA_8888_SkColorType: |
if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
- sampleStage->Initialize<Sampler<Pixel8888SRGB, Placer>>(next, srcPixmap); |
+ sampleStage->initStage<Sampler<Pixel8888SRGB, Blender>>(next, srcPixmap); |
} else { |
- sampleStage->Initialize<Sampler<Pixel8888LRGB, Placer>>(next, srcPixmap); |
+ sampleStage->initStage<Sampler<Pixel8888LRGB, Blender>>(next, srcPixmap); |
} |
break; |
case kBGRA_8888_SkColorType: |
if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
- sampleStage->Initialize<Sampler<Pixel8888SBGR, Placer>>(next, srcPixmap); |
+ sampleStage->initStage<Sampler<Pixel8888SBGR, Blender>>(next, srcPixmap); |
} else { |
- sampleStage->Initialize<Sampler<Pixel8888LBGR, Placer>>(next, srcPixmap); |
+ sampleStage->initStage<Sampler<Pixel8888LBGR, Blender>>(next, srcPixmap); |
} |
break; |
case kIndex_8_SkColorType: |
if (imageInfo.profileType() == kSRGB_SkColorProfileType) { |
- sampleStage->Initialize<Sampler<PixelIndex8SRGB, Placer>>(next, srcPixmap); |
+ sampleStage->initStage<Sampler<PixelIndex8SRGB, Blender>>(next, srcPixmap); |
} else { |
- sampleStage->Initialize<Sampler<PixelIndex8LRGB, Placer>>(next, srcPixmap); |
+ sampleStage->initStage<Sampler<PixelIndex8LRGB, Blender>>(next, srcPixmap); |
} |
break; |
default: |
@@ -592,10 +659,11 @@ static SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler_ba |
} |
SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( |
- Placer* next, |
+ Blender* next, |
SkFilterQuality filterQuality, |
const SkPixmap& srcPixmap, |
- SkLinearBitmapPipeline::SampleStage* sampleStage) { |
+ SkLinearBitmapPipeline::SampleStage* sampleStage) |
+{ |
if (filterQuality == kNone_SkFilterQuality) { |
return choose_pixel_sampler_base<NearestNeighborSampler>(next, srcPixmap, sampleStage); |
} else { |
@@ -604,25 +672,25 @@ SkLinearBitmapPipeline::SampleProcessorInterface* choose_pixel_sampler( |
} |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
-// Pixel Placement Stage |
+// Pixel Blender Stage |
template <SkAlphaType alphaType> |
-class PlaceFPPixel final : public SkLinearBitmapPipeline::PixelPlacerInterface { |
+class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface { |
public: |
- PlaceFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } |
- |
- void VECTORCALL placePixel(Sk4f pixel) override { |
+ SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } |
+ SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} |
+ void VECTORCALL blendPixel(Sk4f pixel) override { |
SkASSERT(fDst + 1 <= fEnd ); |
- PlacePixel(fDst, pixel, 0); |
+ SrcPixel(fDst, pixel, 0); |
fDst += 1; |
} |
- void VECTORCALL place4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { |
+ void VECTORCALL blend4Pixels(Sk4f p0, Sk4f p1, Sk4f p2, Sk4f p3) override { |
SkASSERT(fDst + 4 <= fEnd); |
SkPM4f* dst = fDst; |
- PlacePixel(dst, p0, 0); |
- PlacePixel(dst, p1, 1); |
- PlacePixel(dst, p2, 2); |
- PlacePixel(dst, p3, 3); |
+ SrcPixel(dst, p0, 0); |
+ SrcPixel(dst, p1, 1); |
+ SrcPixel(dst, p2, 2); |
+ SrcPixel(dst, p3, 3); |
fDst += 4; |
} |
@@ -632,7 +700,7 @@ public: |
} |
private: |
- void VECTORCALL PlacePixel(SkPM4f* dst, Sk4f pixel, int index) { |
+ void VECTORCALL SrcPixel(SkPM4f* dst, Sk4f pixel, int index) { |
Sk4f newPixel = pixel; |
if (alphaType == kUnpremul_SkAlphaType) { |
newPixel = Premultiply(pixel); |
@@ -650,21 +718,22 @@ private: |
Sk4f fPostAlpha; |
}; |
-static SkLinearBitmapPipeline::PixelPlacerInterface* choose_pixel_placer( |
+static SkLinearBitmapPipeline::BlendProcessorInterface* choose_blender( |
SkAlphaType alphaType, |
float postAlpha, |
- SkLinearBitmapPipeline::PixelStage* placerStage) { |
+ SkLinearBitmapPipeline::BlenderStage* blenderStage) { |
if (alphaType == kUnpremul_SkAlphaType) { |
- placerStage->Initialize<PlaceFPPixel<kUnpremul_SkAlphaType>>(postAlpha); |
+ blenderStage->initSink<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha); |
} else { |
// kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType |
- placerStage->Initialize<PlaceFPPixel<kPremul_SkAlphaType>>(postAlpha); |
+ blenderStage->initSink<SrcFPPixel<kPremul_SkAlphaType>>(postAlpha); |
} |
- return placerStage->get(); |
+ return blenderStage->get(); |
} |
} // namespace |
//////////////////////////////////////////////////////////////////////////////////////////////////// |
+// SkLinearBitmapPipeline |
SkLinearBitmapPipeline::~SkLinearBitmapPipeline() {} |
SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
@@ -699,14 +768,12 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( |
// As the stages are built, the chooser function may skip a stage. For example, with the |
// identity matrix, the matrix stage is skipped, and the tilerStage is the first stage. |
- auto placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage); |
- auto samplerStage = choose_pixel_sampler(placementStage, |
- filterQuality, srcPixmap, &fSampleStage); |
- auto tilerStage = choose_tiler(samplerStage, |
- dimensions, xTile, yTile, filterQuality, dx, &fTiler); |
- fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage); |
- fLastStage = placementStage; |
- |
+ auto blenderStage = choose_blender(alphaType, postAlpha, &fBlenderStage); |
+ auto samplerStage = choose_pixel_sampler(blenderStage, filterQuality, srcPixmap, &fSampleStage); |
+ auto tilerStage = choose_tiler(samplerStage, dimensions, xTile, yTile, |
+ filterQuality, dx, &fTileStage); |
+ fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixStage); |
+ fLastStage = blenderStage; |
} |
void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |