Use SkFixedAllocator in SkLinearPipeline and remove the embedding of

the entire pipeline.

Adjust SkFixedAlloc to allow nesting of allocation.

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4987

Change-Id: Ieeb1b5deaae004b67cee933af9bc19bbfd5a7687
Reviewed-on: https://skia-review.googlesource.com/4987
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
Herb Derby 2016-11-17 21:12:36 -05:00 committed by Skia Commit-Bot
parent d2265e537c
commit dfa492e580
6 changed files with 182 additions and 177 deletions

View File

@ -6,13 +6,14 @@
*/
#include <memory>
#include "SkColor.h"
#include "SkLinearBitmapPipeline.h"
#include "SkBitmapProcShader.h"
#include "SkPM4f.h"
#include "Benchmark.h"
#include "SkShader.h"
#include "SkBitmapProcShader.h"
#include "SkColor.h"
#include "SkFixedAlloc.h"
#include "SkImage.h"
#include "SkLinearBitmapPipeline.h"
#include "SkPM4f.h"
#include "SkShader.h"
struct CommonBitmapFPBenchmark : public Benchmark {
CommonBitmapFPBenchmark(
@ -146,8 +147,12 @@ struct SkBitmapFPGeneral final : public CommonBitmapFPBenchmark {
SkPixmap srcPixmap{fInfo, fBitmap.get(), static_cast<size_t>(4 * width)};
char storage[600];
SkFixedAlloc fixedAlloc{storage, sizeof(storage)};
SkFallbackAlloc allocator{&fixedAlloc};
SkLinearBitmapPipeline pipeline{
fInvert, filterQuality, fXTile, fYTile, SK_ColorBLACK, srcPixmap};
fInvert, filterQuality, fXTile, fYTile, SK_ColorBLACK, srcPixmap, &allocator};
int count = 100;

View File

@ -115,9 +115,13 @@ static void draw_rect_fp(SkCanvas* canvas, const SkRect& r, SkColor c, const SkM
uint32_t flags = 0;
auto procN = SkXfermode::GetD32Proc(SkBlendMode::kSrcOver, flags);
char storage[512];
SkFixedAlloc fixedAlloc{storage, sizeof(storage)};
SkFallbackAlloc allocator{&fixedAlloc};
SkLinearBitmapPipeline pipeline{
inv, filterQuality,
SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, SK_ColorBLACK, pmsrc};
SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
SK_ColorBLACK, pmsrc, &allocator};
for (int y = 0; y < ir.height(); y++) {
pipeline.shadeSpan4f(0, y, dstBits, ir.width());

View File

@ -113,16 +113,15 @@ public:
// Save things off in case we need to build a blitter pipeline.
fSrcPixmap = info->fPixmap;
fAlpha = SkColorGetA(info->fPaintColor) / 255.0f;
fXMode = info->fTileModeX;
fYMode = info->fTileModeY;
fFilterQuality = info->fFilterQuality;
fMatrixTypeMask = info->fRealInvMatrix.getType();
fShaderPipeline.init(
fShaderPipeline = fAllocator.make<SkLinearBitmapPipeline>(
info->fRealInvMatrix, info->fFilterQuality,
info->fTileModeX, info->fTileModeY,
info->fPaintColor,
info->fPixmap);
info->fPixmap,
&fAllocator);
// To implement the old shadeSpan entry-point, we need to efficiently convert our native
// floats into SkPMColor. The SkXfermode::D32Procs do exactly that.
@ -149,14 +148,13 @@ public:
}
bool onChooseBlitProcs(const SkImageInfo& dstInfo, BlitState* state) override {
if (SkLinearBitmapPipeline::ClonePipelineForBlitting(
&fBlitterPipeline, *fShaderPipeline,
if ((fBlitterPipeline = SkLinearBitmapPipeline::ClonePipelineForBlitting(
*fShaderPipeline,
fMatrixTypeMask,
fXMode, fYMode,
fFilterQuality, fSrcPixmap,
fAlpha, state->fMode, dstInfo))
fAlpha, state->fMode, dstInfo, &fAllocator)))
{
state->fStorage[0] = fBlitterPipeline.get();
state->fStorage[0] = fBlitterPipeline;
state->fBlitBW = &LinearPipelineContext::ForwardToPipeline;
return true;
@ -172,15 +170,16 @@ public:
}
private:
SkEmbeddableLinearPipeline fShaderPipeline;
SkEmbeddableLinearPipeline fBlitterPipeline;
SkXfermode::D32Proc fSrcModeProc;
SkPixmap fSrcPixmap;
float fAlpha;
SkShader::TileMode fXMode;
SkShader::TileMode fYMode;
SkMatrix::TypeMask fMatrixTypeMask;
SkFilterQuality fFilterQuality;
char fStorage[512 + 96];
SkFixedAlloc fFixedAlloc {fStorage, sizeof(fStorage)};
SkFallbackAlloc fAllocator {&fFixedAlloc};
SkLinearBitmapPipeline* fShaderPipeline;
SkLinearBitmapPipeline* fBlitterPipeline;
SkXfermode::D32Proc fSrcModeProc;
SkPixmap fSrcPixmap;
float fAlpha;
SkMatrix::TypeMask fMatrixTypeMask;
SkFilterQuality fFilterQuality;
typedef BitmapProcInfoContext INHERITED;
};

View File

@ -35,9 +35,8 @@ public:
// Skip ahead until our buffer is aligned for T.
fUsed += skip;
// Create the T.
// Make space for T.
auto ptr = (T*)(fBuffer+fUsed);
new (ptr) T(std::forward<Args>(args)...);
fUsed += sizeof(T);
// Stamp a footer after the T that we can use to clean it up.
@ -45,7 +44,8 @@ public:
memcpy(fBuffer+fUsed, &footer, sizeof(Footer));
fUsed += sizeof(Footer);
return ptr;
// Creating a T must be last for nesting to work.
return new (ptr) T(std::forward<Args>(args)...);
}
// Destroys the last object allocated and frees its space in the buffer.
@ -78,9 +78,10 @@ public:
return ptr;
}
}
auto ptr = new T(std::forward<Args>(args)...);
fHeapAllocs.push_back({[](void* ptr) { delete (T*)ptr; }, ptr});
return ptr;
char* ptr = new char[sizeof(T)];
fHeapAllocs.push_back({[](char* ptr) { ((T*)ptr)->~T(); delete [] ptr; }, ptr});
return new (ptr) T(std::forward<Args>(args)...);
}
// Destroys the last object allocated and frees any space it used in the SkFixedAlloc.
@ -91,8 +92,8 @@ public:
private:
struct HeapAlloc {
void (*deleter)(void*);
void* ptr;
void (*deleter)(char*);
char* ptr;
};
SkFixedAlloc* fFixedAlloc;

View File

@ -12,6 +12,7 @@
#include <limits>
#include <tuple>
#include "SkFixedAlloc.h"
#include "SkLinearBitmapPipeline_core.h"
#include "SkLinearBitmapPipeline_matrix.h"
#include "SkLinearBitmapPipeline_tile.h"
@ -349,7 +350,8 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline(
SkFilterQuality filterQuality,
SkShader::TileMode xTile, SkShader::TileMode yTile,
SkColor paintColor,
const SkPixmap& srcPixmap)
const SkPixmap& srcPixmap,
SkFallbackAlloc* allocator)
{
SkISize dimensions = srcPixmap.info().dimensions();
const SkImageInfo& srcImageInfo = srcPixmap.info();
@ -377,55 +379,21 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline(
float postAlpha = SkColorGetA(paintColor) * (1.0f / 255.0f);
// 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 = this->chooseBlenderForShading(alphaType, postAlpha);
auto blenderStage = this->chooseBlenderForShading(alphaType, postAlpha, allocator);
auto samplerStage = this->chooseSampler(
blenderStage, filterQuality, xTile, yTile, srcPixmap, paintColor);
blenderStage, filterQuality, xTile, yTile, srcPixmap, paintColor, allocator);
auto tilerStage = this->chooseTiler(
samplerStage, dimensions, xTile, yTile, filterQuality, dx);
fFirstStage = this->chooseMatrix(tilerStage, adjustedInverse);
samplerStage, dimensions, xTile, yTile, filterQuality, dx, allocator);
fFirstStage = this->chooseMatrix(tilerStage, adjustedInverse, allocator);
fLastStage = blenderStage;
}
bool SkLinearBitmapPipeline::ClonePipelineForBlitting(
SkEmbeddableLinearPipeline* pipelineStorage,
const SkLinearBitmapPipeline& pipeline,
SkMatrix::TypeMask matrixMask,
SkShader::TileMode xTileMode,
SkShader::TileMode yTileMode,
SkFilterQuality filterQuality,
const SkPixmap& srcPixmap,
float finalAlpha,
SkBlendMode blendMode,
const SkImageInfo& dstInfo)
{
if (blendMode == SkBlendMode::kSrcOver && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
blendMode = SkBlendMode::kSrc;
}
if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return false; }
if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return false; }
if (finalAlpha != 1.0f) { return false; }
if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType
|| dstInfo.colorType() != kRGBA_8888_SkColorType) { return false; }
if (!srcPixmap.info().gammaCloseToSRGB() || !dstInfo.gammaCloseToSRGB()) {
return false;
}
if (blendMode != SkBlendMode::kSrc && blendMode != SkBlendMode::kSrcOver) {
return false;
}
pipelineStorage->init(pipeline, srcPixmap, blendMode, dstInfo);
return true;
}
SkLinearBitmapPipeline::SkLinearBitmapPipeline(
const SkLinearBitmapPipeline& pipeline,
const SkPixmap& srcPixmap,
SkBlendMode mode,
const SkImageInfo& dstInfo)
const SkImageInfo& dstInfo,
SkFallbackAlloc* allocator)
{
SkASSERT(mode == SkBlendMode::kSrc || mode == SkBlendMode::kSrcOver);
SkASSERT(srcPixmap.info().colorType() == dstInfo.colorType()
@ -433,22 +401,54 @@ SkLinearBitmapPipeline::SkLinearBitmapPipeline(
SampleProcessorInterface* sampleStage;
if (mode == SkBlendMode::kSrc) {
auto sampler = fMemory.createT<RGBA8888UnitRepeatSrc>(
auto sampler = allocator->make<RGBA8888UnitRepeatSrc>(
srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
sampleStage = sampler;
fLastStage = sampler;
} else {
auto sampler = fMemory.createT<RGBA8888UnitRepeatSrcOver>(
auto sampler = allocator->make<RGBA8888UnitRepeatSrcOver>(
srcPixmap.writable_addr32(0, 0), srcPixmap.rowBytes() / 4);
sampleStage = sampler;
fLastStage = sampler;
}
auto tilerStage = pipeline.fTileStageCloner(sampleStage, &fMemory);
auto matrixStage = pipeline.fMatrixStageCloner(tilerStage, &fMemory);
auto tilerStage = pipeline.fTileStageCloner(sampleStage, allocator);
auto matrixStage = pipeline.fMatrixStageCloner(tilerStage, allocator);
fFirstStage = matrixStage;
}
SkLinearBitmapPipeline* SkLinearBitmapPipeline::ClonePipelineForBlitting(
const SkLinearBitmapPipeline& pipeline,
SkMatrix::TypeMask matrixMask,
SkFilterQuality filterQuality,
const SkPixmap& srcPixmap,
float finalAlpha,
SkBlendMode blendMode,
const SkImageInfo& dstInfo,
SkFallbackAlloc* allocator)
{
if (blendMode == SkBlendMode::kSrcOver && srcPixmap.info().alphaType() == kOpaque_SkAlphaType) {
blendMode = SkBlendMode::kSrc;
}
if (matrixMask & ~SkMatrix::kTranslate_Mask ) { return nullptr; }
if (filterQuality != SkFilterQuality::kNone_SkFilterQuality) { return nullptr; }
if (finalAlpha != 1.0f) { return nullptr; }
if (srcPixmap.info().colorType() != kRGBA_8888_SkColorType
|| dstInfo.colorType() != kRGBA_8888_SkColorType) { return nullptr; }
if (!srcPixmap.info().gammaCloseToSRGB() || !dstInfo.gammaCloseToSRGB()) {
return nullptr;
}
if (blendMode != SkBlendMode::kSrc && blendMode != SkBlendMode::kSrcOver) {
return nullptr;
}
return allocator->make<SkLinearBitmapPipeline>(
pipeline, srcPixmap, blendMode, dstInfo, allocator);
}
void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) {
SkASSERT(count > 0);
this->blitSpan(x, y, dst, count);
@ -466,9 +466,13 @@ void SkLinearBitmapPipeline::blitSpan(int x, int y, void* dst, int count) {
}
SkLinearBitmapPipeline::PointProcessorInterface*
SkLinearBitmapPipeline::chooseMatrix(PointProcessorInterface* next, const SkMatrix& inverse) {
SkLinearBitmapPipeline::chooseMatrix(
PointProcessorInterface* next,
const SkMatrix& inverse,
SkFallbackAlloc* allocator)
{
if (inverse.hasPerspective()) {
auto matrixStage = fMemory.createT<PerspectiveMatrix<>>(
auto matrixStage = allocator->make<PerspectiveMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
SkVector{inverse.getScaleX(), inverse.getScaleY()},
@ -476,42 +480,42 @@ SkLinearBitmapPipeline::chooseMatrix(PointProcessorInterface* next, const SkMatr
SkVector{inverse.getPerspX(), inverse.getPerspY()},
inverse.get(SkMatrix::kMPersp2));
fMatrixStageCloner =
[matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
return memory->createT<PerspectiveMatrix<>>(cloneNext, matrixStage);
[matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<PerspectiveMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
} else if (inverse.getSkewX() != 0.0f || inverse.getSkewY() != 0.0f) {
auto matrixStage = fMemory.createT<AffineMatrix<>>(
auto matrixStage = allocator->make<AffineMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
SkVector{inverse.getScaleX(), inverse.getScaleY()},
SkVector{inverse.getSkewX(), inverse.getSkewY()});
fMatrixStageCloner =
[matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
return memory->createT<AffineMatrix<>>(cloneNext, matrixStage);
[matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<AffineMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
} else if (inverse.getScaleX() != 1.0f || inverse.getScaleY() != 1.0f) {
auto matrixStage = fMemory.createT<ScaleMatrix<>>(
auto matrixStage = allocator->make<ScaleMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()},
SkVector{inverse.getScaleX(), inverse.getScaleY()});
fMatrixStageCloner =
[matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
return memory->createT<ScaleMatrix<>>(cloneNext, matrixStage);
[matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<ScaleMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
} else if (inverse.getTranslateX() != 0.0f || inverse.getTranslateY() != 0.0f) {
auto matrixStage = fMemory.createT<TranslateMatrix<>>(
auto matrixStage = allocator->make<TranslateMatrix<>>(
next,
SkVector{inverse.getTranslateX(), inverse.getTranslateY()});
fMatrixStageCloner =
[matrixStage](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
return memory->createT<TranslateMatrix<>>(cloneNext, matrixStage);
[matrixStage](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return memory->make<TranslateMatrix<>>(cloneNext, matrixStage);
};
return matrixStage;
} else {
fMatrixStageCloner = [](PointProcessorInterface* cloneNext, MemoryAllocator* memory) {
fMatrixStageCloner = [](PointProcessorInterface* cloneNext, SkFallbackAlloc* memory) {
return cloneNext;
};
return next;
@ -520,31 +524,38 @@ SkLinearBitmapPipeline::chooseMatrix(PointProcessorInterface* next, const SkMatr
template <typename Tiler>
SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::createTiler(
SampleProcessorInterface* next, SkISize dimensions) {
auto tilerStage = fMemory.createT<Tiler>(next, dimensions);
SampleProcessorInterface* next,
SkISize dimensions,
SkFallbackAlloc* allocator)
{
auto tilerStage = allocator->make<Tiler>(next, dimensions);
fTileStageCloner =
[tilerStage](SampleProcessorInterface* cloneNext,
MemoryAllocator* memory) -> PointProcessorInterface* {
return memory->createT<Tiler>(cloneNext, tilerStage);
SkFallbackAlloc* memory) -> PointProcessorInterface* {
return memory->make<Tiler>(cloneNext, tilerStage);
};
return tilerStage;
}
template <typename XStrategy>
SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::chooseTilerYMode(
SampleProcessorInterface* next, SkShader::TileMode yMode, SkISize dimensions) {
SampleProcessorInterface* next,
SkShader::TileMode yMode,
SkISize dimensions,
SkFallbackAlloc* allocator)
{
switch (yMode) {
case SkShader::kClamp_TileMode: {
using Tiler = CombinedTileStage<XStrategy, YClampStrategy, SampleProcessorInterface>;
return this->createTiler<Tiler>(next, dimensions);
return this->createTiler<Tiler>(next, dimensions, allocator);
}
case SkShader::kRepeat_TileMode: {
using Tiler = CombinedTileStage<XStrategy, YRepeatStrategy, SampleProcessorInterface>;
return this->createTiler<Tiler>(next, dimensions);
return this->createTiler<Tiler>(next, dimensions, allocator);
}
case SkShader::kMirror_TileMode: {
using Tiler = CombinedTileStage<XStrategy, YMirrorStrategy, SampleProcessorInterface>;
return this->createTiler<Tiler>(next, dimensions);
return this->createTiler<Tiler>(next, dimensions, allocator);
}
}
@ -559,19 +570,22 @@ SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::chooseT
SkShader::TileMode xMode,
SkShader::TileMode yMode,
SkFilterQuality filterQuality,
SkScalar dx)
SkScalar dx,
SkFallbackAlloc* allocator)
{
switch (xMode) {
case SkShader::kClamp_TileMode:
return this->chooseTilerYMode<XClampStrategy>(next, yMode, dimensions);
return this->chooseTilerYMode<XClampStrategy>(next, yMode, dimensions, allocator);
case SkShader::kRepeat_TileMode:
if (dx == 1.0f && filterQuality == kNone_SkFilterQuality) {
return this->chooseTilerYMode<XRepeatUnitScaleStrategy>(next, yMode, dimensions);
return this->chooseTilerYMode<XRepeatUnitScaleStrategy>(
next, yMode, dimensions, allocator);
} else {
return this->chooseTilerYMode<XRepeatStrategy>(next, yMode, dimensions);
return this->chooseTilerYMode<XRepeatStrategy>(
next, yMode, dimensions, allocator);
}
case SkShader::kMirror_TileMode:
return this->chooseTilerYMode<XMirrorStrategy>(next, yMode, dimensions);
return this->chooseTilerYMode<XMirrorStrategy>(next, yMode, dimensions, allocator);
}
// Should never get here.
@ -582,43 +596,45 @@ SkLinearBitmapPipeline::PointProcessorInterface* SkLinearBitmapPipeline::chooseT
template <SkColorType colorType>
SkLinearBitmapPipeline::PixelAccessorInterface*
SkLinearBitmapPipeline::chooseSpecificAccessor(
const SkPixmap& srcPixmap)
const SkPixmap& srcPixmap,
SkFallbackAlloc* allocator)
{
if (srcPixmap.info().gammaCloseToSRGB()) {
using Accessor = PixelAccessor<colorType, kSRGB_SkGammaType>;
return fMemory.createT<Accessor>(srcPixmap);
return allocator->make<Accessor>(srcPixmap);
} else {
using Accessor = PixelAccessor<colorType, kLinear_SkGammaType>;
return fMemory.createT<Accessor>(srcPixmap);
return allocator->make<Accessor>(srcPixmap);
}
}
SkLinearBitmapPipeline::PixelAccessorInterface* SkLinearBitmapPipeline::choosePixelAccessor(
const SkPixmap& srcPixmap,
const SkColor A8TintColor)
const SkColor A8TintColor,
SkFallbackAlloc* allocator)
{
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);
return allocator->make<Accessor>(srcPixmap, A8TintColor);
}
case kARGB_4444_SkColorType:
return this->chooseSpecificAccessor<kARGB_4444_SkColorType>(srcPixmap);
return this->chooseSpecificAccessor<kARGB_4444_SkColorType>(srcPixmap, allocator);
case kRGB_565_SkColorType:
return this->chooseSpecificAccessor<kRGB_565_SkColorType>(srcPixmap);
return this->chooseSpecificAccessor<kRGB_565_SkColorType>(srcPixmap, allocator);
case kRGBA_8888_SkColorType:
return this->chooseSpecificAccessor<kRGBA_8888_SkColorType>(srcPixmap);
return this->chooseSpecificAccessor<kRGBA_8888_SkColorType>(srcPixmap, allocator);
case kBGRA_8888_SkColorType:
return this->chooseSpecificAccessor<kBGRA_8888_SkColorType>(srcPixmap);
return this->chooseSpecificAccessor<kBGRA_8888_SkColorType>(srcPixmap, allocator);
case kIndex_8_SkColorType:
return this->chooseSpecificAccessor<kIndex_8_SkColorType>(srcPixmap);
return this->chooseSpecificAccessor<kIndex_8_SkColorType>(srcPixmap, allocator);
case kGray_8_SkColorType:
return this->chooseSpecificAccessor<kGray_8_SkColorType>(srcPixmap);
return this->chooseSpecificAccessor<kGray_8_SkColorType>(srcPixmap, allocator);
case kRGBA_F16_SkColorType: {
using Accessor = PixelAccessor<kRGBA_F16_SkColorType, kLinear_SkGammaType>;
return fMemory.createT<Accessor>(srcPixmap);
return allocator->make<Accessor>(srcPixmap);
}
default:
// Should never get here.
@ -632,7 +648,8 @@ SkLinearBitmapPipeline::SampleProcessorInterface* SkLinearBitmapPipeline::choose
SkFilterQuality filterQuality,
SkShader::TileMode xTile, SkShader::TileMode yTile,
const SkPixmap& srcPixmap,
const SkColor A8TintColor)
const SkColor A8TintColor,
SkFallbackAlloc* allocator)
{
const SkImageInfo& imageInfo = srcPixmap.info();
SkISize dimensions = imageInfo.dimensions();
@ -645,13 +662,13 @@ SkLinearBitmapPipeline::SampleProcessorInterface* SkLinearBitmapPipeline::choose
using Sampler =
NearestNeighborSampler<
PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
return fMemory.createT<Sampler>(next, srcPixmap);
return allocator->make<Sampler>(next, srcPixmap);
}
case kIndex_8_SkColorType: {
using Sampler =
NearestNeighborSampler<
PixelAccessor<kIndex_8_SkColorType, kSRGB_SkGammaType>, Blender>;
return fMemory.createT<Sampler>(next, srcPixmap);
return allocator->make<Sampler>(next, srcPixmap);
}
default:
break;
@ -662,13 +679,13 @@ SkLinearBitmapPipeline::SampleProcessorInterface* SkLinearBitmapPipeline::choose
using Sampler =
BilerpSampler<
PixelAccessor<kN32_SkColorType, kSRGB_SkGammaType>, Blender>;
return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, srcPixmap);
return allocator->make<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);
return allocator->make<Sampler>(next, dimensions, xTile, yTile, srcPixmap);
}
default:
break;
@ -676,24 +693,26 @@ SkLinearBitmapPipeline::SampleProcessorInterface* SkLinearBitmapPipeline::choose
}
}
auto pixelAccessor = this->choosePixelAccessor(srcPixmap, A8TintColor);
auto pixelAccessor = this->choosePixelAccessor(srcPixmap, A8TintColor, allocator);
// General cases.
if (filterQuality == kNone_SkFilterQuality) {
using Sampler = NearestNeighborSampler<PixelAccessorShim, Blender>;
return fMemory.createT<Sampler>(next, pixelAccessor);
return allocator->make<Sampler>(next, pixelAccessor);
} else {
using Sampler = BilerpSampler<PixelAccessorShim, Blender>;
return fMemory.createT<Sampler>(next, dimensions, xTile, yTile, pixelAccessor);
return allocator->make<Sampler>(next, dimensions, xTile, yTile, pixelAccessor);
}
}
Blender* SkLinearBitmapPipeline::chooseBlenderForShading(
SkAlphaType alphaType,
float postAlpha) {
float postAlpha,
SkFallbackAlloc* allocator)
{
if (alphaType == kUnpremul_SkAlphaType) {
return fMemory.createT<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
return allocator->make<SrcFPPixel<kUnpremul_SkAlphaType>>(postAlpha);
} else {
// kOpaque_SkAlphaType is treated the same as kPremul_SkAlphaType
return fMemory.createT<SrcFPPixel<kPremul_SkAlphaType>>(postAlpha);
return allocator->make<SrcFPPixel<kPremul_SkAlphaType>>(postAlpha);
}
}

View File

@ -9,10 +9,10 @@
#define SkLinearBitmapPipeline_DEFINED
#include "SkColor.h"
#include "SkFixedAlloc.h"
#include "SkImageInfo.h"
#include "SkMatrix.h"
#include "SkShader.h"
#include "SkSmallAllocator.h"
class SkEmbeddableLinearPipeline;
@ -33,25 +33,25 @@ public:
SkFilterQuality filterQuality,
SkShader::TileMode xTile, SkShader::TileMode yTile,
SkColor paintColor,
const SkPixmap& srcPixmap);
const SkPixmap& srcPixmap,
SkFallbackAlloc* allocator);
SkLinearBitmapPipeline(
const SkLinearBitmapPipeline& pipeline,
const SkPixmap& srcPixmap,
SkBlendMode,
const SkImageInfo& dstInfo);
const SkImageInfo& dstInfo,
SkFallbackAlloc* allocator);
static bool ClonePipelineForBlitting(
SkEmbeddableLinearPipeline* pipelineStorage,
static SkLinearBitmapPipeline* ClonePipelineForBlitting(
const SkLinearBitmapPipeline& pipeline,
SkMatrix::TypeMask matrixMask,
SkShader::TileMode xTileMode,
SkShader::TileMode yTileMode,
SkFilterQuality filterQuality,
const SkPixmap& srcPixmap,
float finalAlpha,
SkBlendMode,
const SkImageInfo& dstInfo);
const SkImageInfo& dstInfo,
SkFallbackAlloc* allocator);
~SkLinearBitmapPipeline();
@ -64,82 +64,59 @@ public:
class DestinationInterface;
class PixelAccessorInterface;
private:
using MemoryAllocator = SkSmallAllocator<5, 256>;
using MatrixCloner =
std::function<PointProcessorInterface* (PointProcessorInterface*, MemoryAllocator*)>;
std::function<PointProcessorInterface* (PointProcessorInterface*, SkFallbackAlloc*)>;
using TilerCloner =
std::function<PointProcessorInterface* (SampleProcessorInterface*, MemoryAllocator*)>;
std::function<PointProcessorInterface* (SampleProcessorInterface*, SkFallbackAlloc*)>;
PointProcessorInterface* chooseMatrix(
PointProcessorInterface* next,
const SkMatrix& inverse);
const SkMatrix& inverse,
SkFallbackAlloc* allocator);
template <typename Tiler>
PointProcessorInterface* createTiler(SampleProcessorInterface* next, SkISize dimensions);
PointProcessorInterface* createTiler(SampleProcessorInterface* next, SkISize dimensions,
SkFallbackAlloc* allocator);
template <typename XStrategy>
PointProcessorInterface* chooseTilerYMode(
SampleProcessorInterface* next, SkShader::TileMode yMode, SkISize dimensions);
SampleProcessorInterface* next, SkShader::TileMode yMode, SkISize dimensions,
SkFallbackAlloc* allocator);
PointProcessorInterface* chooseTiler(
SampleProcessorInterface* next,
SkISize dimensions,
SkShader::TileMode xMode, SkShader::TileMode yMode,
SkFilterQuality filterQuality,
SkScalar dx);
SkScalar dx,
SkFallbackAlloc* allocator);
template <SkColorType colorType>
PixelAccessorInterface* chooseSpecificAccessor(const SkPixmap& srcPixmap);
PixelAccessorInterface* chooseSpecificAccessor(const SkPixmap& srcPixmap,
SkFallbackAlloc* allocator);
PixelAccessorInterface* choosePixelAccessor(
const SkPixmap& srcPixmap,
const SkColor A8TintColor);
const SkColor A8TintColor,
SkFallbackAlloc* allocator);
SampleProcessorInterface* chooseSampler(
BlendProcessorInterface* next,
SkFilterQuality filterQuality,
SkShader::TileMode xTile, SkShader::TileMode yTile,
const SkPixmap& srcPixmap,
const SkColor A8TintColor);
const SkColor A8TintColor,
SkFallbackAlloc* allocator);
BlendProcessorInterface* chooseBlenderForShading(
SkAlphaType alphaType,
float postAlpha);
float postAlpha,
SkFallbackAlloc* allocator);
MemoryAllocator fMemory;
PointProcessorInterface* fFirstStage;
MatrixCloner fMatrixStageCloner;
TilerCloner fTileStageCloner;
DestinationInterface* fLastStage;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
// SkEmbeddableLinearPipeline - manage stricter alignment needs for SkLinearBitmapPipeline.
class SkEmbeddableLinearPipeline {
public:
SkEmbeddableLinearPipeline() { }
~SkEmbeddableLinearPipeline() {
if (fInitialized) {
get()->~SkLinearBitmapPipeline();
}
}
template <typename... Args>
void init(Args&&... args) {
new (fPipelineStorage) SkLinearBitmapPipeline{std::forward<Args>(args)...};
fInitialized = true;
}
SkLinearBitmapPipeline* get() const {
return reinterpret_cast<SkLinearBitmapPipeline*>(fPipelineStorage);
}
SkLinearBitmapPipeline& operator*() const { return *this->get(); }
SkLinearBitmapPipeline* operator->() const { return this->get(); }
private:
alignas(SkLinearBitmapPipeline) mutable char fPipelineStorage[sizeof(SkLinearBitmapPipeline)];
bool fInitialized {false};
};
#endif // SkLinearBitmapPipeline_DEFINED