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 <herb@google.com> Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
parent
db4d406e7e
commit
f9d5d4fb8c
@ -36,9 +36,6 @@ void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initStage(Next* next, Arg
|
||||
"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;
|
||||
};
|
||||
|
||||
@ -51,22 +48,6 @@ void SkLinearBitmapPipeline::Stage<Base, kSize, Next>::initSink(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 {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -336,138 +317,10 @@ private:
|
||||
|
||||
using Blender = SkLinearBitmapPipeline::BlendProcessorInterface;
|
||||
|
||||
template <SkColorType colorType>
|
||||
static SkLinearBitmapPipeline::PixelAccessorInterface* choose_specific_accessor(
|
||||
const SkPixmap& srcPixmap, SkLinearBitmapPipeline::Accessor* accessor)
|
||||
{
|
||||
if (srcPixmap.info().gammaCloseToSRGB()) {
|
||||
using PA = PixelAccessor<colorType, kSRGB_SkGammaType>;
|
||||
accessor->init<PA>(srcPixmap);
|
||||
return accessor->get();
|
||||
} else {
|
||||
using PA = PixelAccessor<colorType, kLinear_SkGammaType>;
|
||||
accessor->init<PA>(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<kAlpha_8_SkColorType, kLinear_SkGammaType>;
|
||||
accessor->init<PA>(srcPixmap, A8TintColor);
|
||||
pixelAccessor = accessor->get();
|
||||
}
|
||||
break;
|
||||
case kARGB_4444_SkColorType:
|
||||
pixelAccessor = choose_specific_accessor<kARGB_4444_SkColorType>(srcPixmap, accessor);
|
||||
break;
|
||||
case kRGB_565_SkColorType:
|
||||
pixelAccessor = choose_specific_accessor<kRGB_565_SkColorType>(srcPixmap, accessor);
|
||||
break;
|
||||
case kRGBA_8888_SkColorType:
|
||||
pixelAccessor = choose_specific_accessor<kRGBA_8888_SkColorType>(srcPixmap, accessor);
|
||||
break;
|
||||
case kBGRA_8888_SkColorType:
|
||||
pixelAccessor = choose_specific_accessor<kBGRA_8888_SkColorType>(srcPixmap, accessor);
|
||||
break;
|
||||
case kIndex_8_SkColorType:
|
||||
pixelAccessor = choose_specific_accessor<kIndex_8_SkColorType>(srcPixmap, accessor);
|
||||
break;
|
||||
case kGray_8_SkColorType:
|
||||
pixelAccessor = choose_specific_accessor<kGray_8_SkColorType>(srcPixmap, accessor);
|
||||
break;
|
||||
case kRGBA_F16_SkColorType: {
|
||||
using PA = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaType>;
|
||||
accessor->init<PA>(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<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
|
||||
sampleStage->initStage<S>(next, srcPixmap);
|
||||
return sampleStage->get();
|
||||
}
|
||||
case kIndex_8_SkColorType: {
|
||||
using S =
|
||||
NearestNeighborSampler<
|
||||
PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
|
||||
sampleStage->initStage<S>(next, srcPixmap);
|
||||
return sampleStage->get();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (imageInfo.colorType()) {
|
||||
case kN32_SkColorType: {
|
||||
using S =
|
||||
BilerpSampler<
|
||||
PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
|
||||
sampleStage->initStage<S>(next, dimensions, xTile, yTile, 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);
|
||||
return sampleStage->get();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pixelAccessor = choose_pixel_accessor(srcPixmap, A8TintColor, accessor);
|
||||
// General cases.
|
||||
if (filterQuality == kNone_SkFilterQuality) {
|
||||
using S = NearestNeighborSampler<PixelAccessorShim, Blender>;
|
||||
sampleStage->initStage<S>(next, pixelAccessor);
|
||||
} else {
|
||||
using S = BilerpSampler<PixelAccessorShim, Blender>;
|
||||
sampleStage->initStage<S>(next, dimensions, xTile, yTile, pixelAccessor);
|
||||
}
|
||||
return sampleStage->get();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Pixel Blender Stage
|
||||
template <SkAlphaType alphaType>
|
||||
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<RGBA8888UnitRepeatSrc>(
|
||||
auto sampler = fMemory.createT<RGBA8888UnitRepeatSrc>(
|
||||
srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
|
||||
fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888UnitRepeatSrc>();
|
||||
sampleStage = sampler;
|
||||
fLastStage = sampler;
|
||||
} else {
|
||||
fSampleStage.initSink<RGBA8888UnitRepeatSrcOver>(
|
||||
auto sampler = fMemory.createT<RGBA8888UnitRepeatSrcOver>(
|
||||
srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
|
||||
fLastStage = fSampleStage.getInterface<DestinationInterface, RGBA8888UnitRepeatSrcOver>();
|
||||
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 <SkColorType colorType>
|
||||
SkLinearBitmapPipeline::PixelAccessorInterface*
|
||||
SkLinearBitmapPipeline::chooseSpecificAccessor(
|
||||
const SkPixmap& srcPixmap)
|
||||
{
|
||||
if (srcPixmap.info().gammaCloseToSRGB()) {
|
||||
using Accessor = PixelAccessor<colorType, kSRGB_SkGammaType>;
|
||||
return fMemory.createT<Accessor>(srcPixmap);
|
||||
} else {
|
||||
using Accessor = PixelAccessor<colorType, kLinear_SkGammaType>;
|
||||
return fMemory.createT<Accessor>(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<kAlpha_8_SkColorType, kLinear_SkGammaType>;
|
||||
return fMemory.createT<Accessor>(srcPixmap, A8TintColor);
|
||||
}
|
||||
case kARGB_4444_SkColorType:
|
||||
return this->chooseSpecificAccessor<kARGB_4444_SkColorType>(srcPixmap);
|
||||
case kRGB_565_SkColorType:
|
||||
return this->chooseSpecificAccessor<kRGB_565_SkColorType>(srcPixmap);
|
||||
case kRGBA_8888_SkColorType:
|
||||
return this->chooseSpecificAccessor<kRGBA_8888_SkColorType>(srcPixmap);
|
||||
case kBGRA_8888_SkColorType:
|
||||
return this->chooseSpecificAccessor<kBGRA_8888_SkColorType>(srcPixmap);
|
||||
case kIndex_8_SkColorType:
|
||||
return this->chooseSpecificAccessor<kIndex_8_SkColorType>(srcPixmap);
|
||||
case kGray_8_SkColorType:
|
||||
return this->chooseSpecificAccessor<kGray_8_SkColorType>(srcPixmap);
|
||||
case kRGBA_F16_SkColorType: {
|
||||
using Accessor = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaType>;
|
||||
return fMemory.createT<Accessor>(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<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
|
||||
return fMemory.createT<Sampler>(next, srcPixmap);
|
||||
}
|
||||
case kIndex_8_SkColorType: {
|
||||
using Sampler =
|
||||
NearestNeighborSampler<
|
||||
PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
|
||||
return fMemory.createT<Sampler>(next, srcPixmap);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (imageInfo.colorType()) {
|
||||
case kN32_SkColorType: {
|
||||
using Sampler =
|
||||
BilerpSampler<
|
||||
PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
|
||||
return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, srcPixmap);
|
||||
}
|
||||
case kIndex_8_SkColorType: {
|
||||
using Sampler =
|
||||
BilerpSampler<
|
||||
PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
|
||||
return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, srcPixmap);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto pixelAccessor = this->choosePixelAccessor(srcPixmap, A8TintColor);
|
||||
// General cases.
|
||||
if (filterQuality == kNone_SkFilterQuality) {
|
||||
using Sampler = NearestNeighborSampler<PixelAccessorShim, Blender>;
|
||||
return fMemory.createT<Sampler>(next, pixelAccessor);
|
||||
} else {
|
||||
using Sampler = BilerpSampler<PixelAccessorShim, Blender>;
|
||||
return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, pixelAccessor);
|
||||
}
|
||||
}
|
||||
|
@ -70,55 +70,15 @@ public:
|
||||
template<typename Variant, typename... Args>
|
||||
void initSink(Args&& ... args);
|
||||
|
||||
template <typename To, typename From>
|
||||
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<Base*>(fSpace); }
|
||||
Base* operator->() const { return this->get(); }
|
||||
Base& operator*() const { return *(this->get()); }
|
||||
|
||||
private:
|
||||
std::function<void (Next*, void*)> fStageCloner;
|
||||
mutable char fSpace[kSize];
|
||||
bool fIsInitialized;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PolyMemory
|
||||
template <typename Base, size_t kSize>
|
||||
class PolyMemory {
|
||||
public:
|
||||
PolyMemory() : fIsInitialized{false} { }
|
||||
~PolyMemory() {
|
||||
if (fIsInitialized) {
|
||||
this->get()->~Base();
|
||||
}
|
||||
}
|
||||
template<typename Variant, typename... Args>
|
||||
void init(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;
|
||||
}
|
||||
|
||||
Base* get() const { return reinterpret_cast<Base*>(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<SampleProcessorInterface, 160, BlendProcessorInterface>;
|
||||
using BlenderStage = Stage<BlendProcessorInterface, 48>;
|
||||
using Accessor = PolyMemory<PixelAccessorInterface, 64>;
|
||||
|
||||
private:
|
||||
using MemoryAllocator = SkSmallAllocator<128, 2>;
|
||||
using MemoryAllocator = SkSmallAllocator<128, 4>;
|
||||
using MatrixCloner =
|
||||
std::function<PointProcessorInterface* (PointProcessorInterface*, MemoryAllocator*)>;
|
||||
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 <SkColorType colorType>
|
||||
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;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user