From f9d5d4fb8cf370e60e1856320e8fa9eb70f3d5c4 Mon Sep 17 00:00:00 2001 From: Herb Derby Date: Wed, 16 Nov 2016 16:23:24 -0500 Subject: [PATCH] Use SkSmallAllocator for SamplerStage and Accessor. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4917 Change-Id: Id67d7c1cefa2aadfc706c56dd02d086120f99be3 Reviewed-on: https://skia-review.googlesource.com/4917 Commit-Queue: Herb Derby Reviewed-by: Mike Klein --- src/core/SkLinearBitmapPipeline.cpp | 274 ++++++++++++---------------- src/core/SkLinearBitmapPipeline.h | 62 ++----- 2 files changed, 134 insertions(+), 202 deletions(-) diff --git a/src/core/SkLinearBitmapPipeline.cpp b/src/core/SkLinearBitmapPipeline.cpp index dae6985ecc..c9b71b987e 100644 --- a/src/core/SkLinearBitmapPipeline.cpp +++ b/src/core/SkLinearBitmapPipeline.cpp @@ -36,9 +36,6 @@ void SkLinearBitmapPipeline::Stage::initStage(Next* next, Arg "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace)); new (&fSpace) Variant(next, std::forward(args)...); - fStageCloner = [this](Next* nextClone, void* addr) { - new (addr) Variant(nextClone, (const Variant&)*this->get()); - }; fIsInitialized = true; }; @@ -51,22 +48,6 @@ void SkLinearBitmapPipeline::Stage::initSink(Args&& ... args) fIsInitialized = true; }; -template -template -To* SkLinearBitmapPipeline::Stage::getInterface() { - From* down = static_cast(this->get()); - return static_cast(down); -} - -template -Base* SkLinearBitmapPipeline::Stage::cloneStageTo( - Next* next, Stage* cloneToStage) const -{ - if (!fIsInitialized) return nullptr; - fStageCloner(next, &cloneToStage->fSpace); - return cloneToStage->get(); -} - namespace { //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -336,138 +317,10 @@ private: using Blender = SkLinearBitmapPipeline::BlendProcessorInterface; -template -static SkLinearBitmapPipeline::PixelAccessorInterface* choose_specific_accessor( - const SkPixmap& srcPixmap, SkLinearBitmapPipeline::Accessor* accessor) -{ - if (srcPixmap.info().gammaCloseToSRGB()) { - using PA = PixelAccessor; - accessor->init(srcPixmap); - return accessor->get(); - } else { - using PA = PixelAccessor; - accessor->init(srcPixmap); - return accessor->get(); - } -} - -static SkLinearBitmapPipeline::PixelAccessorInterface* choose_pixel_accessor( - const SkPixmap& srcPixmap, - const SkColor A8TintColor, - SkLinearBitmapPipeline::Accessor* accessor) -{ - const SkImageInfo& imageInfo = srcPixmap.info(); - - SkLinearBitmapPipeline::PixelAccessorInterface* pixelAccessor = nullptr; - switch (imageInfo.colorType()) { - case kAlpha_8_SkColorType: { - using PA = PixelAccessor; - accessor->init(srcPixmap, A8TintColor); - pixelAccessor = accessor->get(); - } - break; - case kARGB_4444_SkColorType: - pixelAccessor = choose_specific_accessor(srcPixmap, accessor); - break; - case kRGB_565_SkColorType: - pixelAccessor = choose_specific_accessor(srcPixmap, accessor); - break; - case kRGBA_8888_SkColorType: - pixelAccessor = choose_specific_accessor(srcPixmap, accessor); - break; - case kBGRA_8888_SkColorType: - pixelAccessor = choose_specific_accessor(srcPixmap, accessor); - break; - case kIndex_8_SkColorType: - pixelAccessor = choose_specific_accessor(srcPixmap, accessor); - break; - case kGray_8_SkColorType: - pixelAccessor = choose_specific_accessor(srcPixmap, accessor); - break; - case kRGBA_F16_SkColorType: { - using PA = PixelAccessor; - accessor->init(srcPixmap); - pixelAccessor = accessor->get(); - } - break; - default: - SkFAIL("Not implemented. Unsupported src"); - break; - } - - return pixelAccessor; -} - -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()) { - if (filterQuality == kNone_SkFilterQuality) { - switch (imageInfo.colorType()) { - case kN32_SkColorType: { - using S = - NearestNeighborSampler< - PixelAccessor, Blender>; - sampleStage->initStage(next, srcPixmap); - return sampleStage->get(); - } - case kIndex_8_SkColorType: { - using S = - NearestNeighborSampler< - PixelAccessor, Blender>; - sampleStage->initStage(next, srcPixmap); - return sampleStage->get(); - } - default: - break; - } - } else { - switch (imageInfo.colorType()) { - case kN32_SkColorType: { - using S = - BilerpSampler< - PixelAccessor, Blender>; - sampleStage->initStage(next, dimensions, xTile, yTile, srcPixmap); - return sampleStage->get(); - } - case kIndex_8_SkColorType: { - using S = - BilerpSampler< - PixelAccessor, Blender>; - sampleStage->initStage(next, dimensions, xTile, yTile, srcPixmap); - return sampleStage->get(); - } - default: - break; - } - } - } - - auto pixelAccessor = choose_pixel_accessor(srcPixmap, A8TintColor, accessor); - // General cases. - if (filterQuality == kNone_SkFilterQuality) { - using S = NearestNeighborSampler; - sampleStage->initStage(next, pixelAccessor); - } else { - using S = BilerpSampler; - sampleStage->initStage(next, dimensions, xTile, yTile, pixelAccessor); - } - return sampleStage->get(); -} - //////////////////////////////////////////////////////////////////////////////////////////////////// // Pixel Blender Stage template -class SrcFPPixel final : public SkLinearBitmapPipeline::BlendProcessorInterface { +class SrcFPPixel final : public Blender { public: SrcFPPixel(float postAlpha) : fPostAlpha{postAlpha} { } SrcFPPixel(const SrcFPPixel& Blender) : fPostAlpha(Blender.fPostAlpha) {} @@ -566,9 +419,8 @@ 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 blenderStage = choose_blender_for_shading(alphaType, postAlpha, &fBlenderStage); - auto samplerStage = choose_pixel_sampler( - blenderStage, filterQuality, xTile, yTile, - srcPixmap, paintColor, &fSampleStage, &fAccessor); + auto samplerStage = this->chooseSampler( + blenderStage, filterQuality, xTile, yTile, srcPixmap, paintColor); auto tilerStage = this->chooseTiler( samplerStage, dimensions, xTile, yTile, filterQuality, dx); fFirstStage = this->chooseMatrix(tilerStage, adjustedInverse); @@ -620,17 +472,19 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline( SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType() && srcPixmap.info().colorType() == kRGBA_8888_SkColorType); + SampleProcessorInterface* sampleStage; if (mode == SkBlendMode::kSrc) { - fSampleStage.initSink( + auto sampler = fMemory.createT( srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4); - fLastStage = fSampleStage.getInterface(); + sampleStage = sampler; + fLastStage = sampler; } else { - fSampleStage.initSink( + auto sampler = fMemory.createT( srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4); - fLastStage = fSampleStage.getInterface(); + sampleStage = sampler; + fLastStage = sampler; } - auto sampleStage = fSampleStage.get(); auto tilerStage = pipeline.fTileStageCloner(sampleStage, &fMemory); auto matrixStage = pipeline.fMatrixStageCloner(tilerStage, &fMemory); fFirstStage = matrixStage; @@ -765,3 +619,111 @@ SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::chooseT SkFAIL("Not all X tile cases covered."); return nullptr; } + +template +SkLinearBitmapPipeline::PixelAccessorInterface* + SkLinearBitmapPipeline::chooseSpecificAccessor( + const SkPixmap& srcPixmap) +{ + if (srcPixmap.info().gammaCloseToSRGB()) { + using Accessor = PixelAccessor; + return fMemory.createT(srcPixmap); + } else { + using Accessor = PixelAccessor; + return fMemory.createT(srcPixmap); + } +} + +SkLinearBitmapPipeline::PixelAccessorInterface* SkLinearBitmapPipeline::choosePixelAccessor( + const SkPixmap& srcPixmap, + const SkColor A8TintColor) +{ + const SkImageInfo& imageInfo = srcPixmap.info(); + + switch (imageInfo.colorType()) { + case kAlpha_8_SkColorType: { + using Accessor = PixelAccessor; + return fMemory.createT(srcPixmap, A8TintColor); + } + case kARGB_4444_SkColorType: + return this->chooseSpecificAccessor(srcPixmap); + case kRGB_565_SkColorType: + return this->chooseSpecificAccessor(srcPixmap); + case kRGBA_8888_SkColorType: + return this->chooseSpecificAccessor(srcPixmap); + case kBGRA_8888_SkColorType: + return this->chooseSpecificAccessor(srcPixmap); + case kIndex_8_SkColorType: + return this->chooseSpecificAccessor(srcPixmap); + case kGray_8_SkColorType: + return this->chooseSpecificAccessor(srcPixmap); + case kRGBA_F16_SkColorType: { + using Accessor = PixelAccessor; + return fMemory.createT(srcPixmap); + } + default: + // Should never get here. + SkFAIL("Pixel source not supported."); + return nullptr; + } +} + +SkLinearBitmapPipeline::SampleProcessorInterface* SkLinearBitmapPipeline::chooseSampler( + Blender* next, + SkFilterQuality filterQuality, + SkShader::TileMode xTile, SkShader::TileMode yTile, + const SkPixmap& srcPixmap, + const SkColor A8TintColor) +{ + const SkImageInfo& imageInfo = srcPixmap.info(); + SkISize dimensions = imageInfo.dimensions(); + + // Special case samplers with fully expanded templates + if (imageInfo.gammaCloseToSRGB()) { + if (filterQuality == kNone_SkFilterQuality) { + switch (imageInfo.colorType()) { + case kN32_SkColorType: { + using Sampler = + NearestNeighborSampler< + PixelAccessor, Blender>; + return fMemory.createT(next, srcPixmap); + } + case kIndex_8_SkColorType: { + using Sampler = + NearestNeighborSampler< + PixelAccessor, Blender>; + return fMemory.createT(next, srcPixmap); + } + default: + break; + } + } else { + switch (imageInfo.colorType()) { + case kN32_SkColorType: { + using Sampler = + BilerpSampler< + PixelAccessor, Blender>; + return fMemory.createT(next, dimensions, xTile, yTile, srcPixmap); + } + case kIndex_8_SkColorType: { + using Sampler = + BilerpSampler< + PixelAccessor, Blender>; + return fMemory.createT(next, dimensions, xTile, yTile, srcPixmap); + } + default: + break; + } + } + } + + auto pixelAccessor = this->choosePixelAccessor(srcPixmap, A8TintColor); + // General cases. + if (filterQuality == kNone_SkFilterQuality) { + using Sampler = NearestNeighborSampler; + return fMemory.createT(next, pixelAccessor); + } else { + using Sampler = BilerpSampler; + return fMemory.createT(next, dimensions, xTile, yTile, pixelAccessor); + } +} diff --git a/src/core/SkLinearBitmapPipeline.h b/src/core/SkLinearBitmapPipeline.h index d5c43d91b8..f936ffd7f9 100644 --- a/src/core/SkLinearBitmapPipeline.h +++ b/src/core/SkLinearBitmapPipeline.h @@ -70,55 +70,15 @@ public: template void initSink(Args&& ... args); - template - To* getInterface(); - - // Copy this stage to `cloneToStage` with `next` as its next stage - // (not necessarily the same as our next, you see), returning `cloneToStage`. - // Note: There is no cloneSinkTo method because the code usually places the top part of - // the pipeline on a new sampler. - Base* cloneStageTo(Next* next, Stage* cloneToStage) const; - Base* get() const { return reinterpret_cast(fSpace); } Base* operator->() const { return this->get(); } Base& operator*() const { return *(this->get()); } private: - std::function fStageCloner; mutable char fSpace[kSize]; bool fIsInitialized; }; -/////////////////////////////////////////////////////////////////////////////////////////////////// -// PolyMemory - template - class PolyMemory { - public: - PolyMemory() : fIsInitialized{false} { } - ~PolyMemory() { - if (fIsInitialized) { - this->get()->~Base(); - } - } - template - void init(Args&& ... args) { - SkASSERTF(sizeof(Variant) <= sizeof(fSpace), - "Size Variant: %d, Space: %d", sizeof(Variant), sizeof(fSpace)); - - new (&fSpace) Variant(std::forward(args)...); - fIsInitialized = true; - } - - Base* get() const { return reinterpret_cast(fSpace); } - Base* operator->() const { return this->get(); } - Base& operator*() const { return *(this->get()); } - - private: - mutable char fSpace[kSize]; - bool fIsInitialized; - - }; - class PointProcessorInterface; class SampleProcessorInterface; class BlendProcessorInterface; @@ -128,10 +88,9 @@ public: // These values were generated by the assert above in Stage::init{Sink|Stage}. using SampleStage = Stage; using BlenderStage = Stage; - using Accessor = PolyMemory; private: - using MemoryAllocator = SkSmallAllocator<128, 2>; + using MemoryAllocator = SkSmallAllocator<128, 4>; using MatrixCloner = std::function; using TilerCloner = @@ -151,19 +110,30 @@ private: PointProcessorInterface* chooseTiler( SampleProcessorInterface* next, SkISize dimensions, - SkShader::TileMode xMode, - SkShader::TileMode yMode, + SkShader::TileMode xMode, SkShader::TileMode yMode, SkFilterQuality filterQuality, SkScalar dx); + template + PixelAccessorInterface* chooseSpecificAccessor(const SkPixmap& srcPixmap); + + PixelAccessorInterface* choosePixelAccessor( + const SkPixmap& srcPixmap, + const SkColor A8TintColor); + + SampleProcessorInterface* chooseSampler( + BlendProcessorInterface* next, + SkFilterQuality filterQuality, + SkShader::TileMode xTile, SkShader::TileMode yTile, + const SkPixmap& srcPixmap, + const SkColor A8TintColor); + MemoryAllocator fMemory; PointProcessorInterface* fFirstStage; MatrixCloner fMatrixStageCloner; TilerCloner fTileStageCloner; - SampleStage fSampleStage; BlenderStage fBlenderStage; DestinationInterface* fLastStage; - Accessor fAccessor; }; ////////////////////////////////////////////////////////////////////////////////////////////////////