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:
parent
d2265e537c
commit
dfa492e580
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user