diff options
author | 2017-02-07 17:28:15 +0000 | |
---|---|---|
committer | 2017-02-07 17:28:21 +0000 | |
commit | dd8b72ae7319598cfc1024901e860c52f06e6ae1 (patch) | |
tree | b6e94e11c082c691512f8989ae55794fa2e6b756 /src/core | |
parent | 1f2fff2544a9dc6a0f169a017d374eca9f04c6b5 (diff) |
Revert "Use SkArenaAlloc instead of SkSmallAllocator in the SkAutoBlitterChoose code."
This reverts commit 2b57b7f7a7fc97db57f190b5a8ebcf68e177ee2d.
Reason for revert: Android compile failing
Original change's description:
> Use SkArenaAlloc instead of SkSmallAllocator in the SkAutoBlitterChoose code.
>
>
> TBR=reed@google.com
> Change-Id: Iefb044bf7657fbf982f23aa91a3f4d013ce2c626
> Reviewed-on: https://skia-review.googlesource.com/7786
> Reviewed-by: Mike Klein <mtklein@chromium.org>
> Reviewed-by: Herb Derby <herb@google.com>
> Commit-Queue: Herb Derby <herb@google.com>
>
TBR=mtklein@chromium.org,mtklein@google.com,herb@google.com,reed@google.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Change-Id: Id09c35377dddae0811d998b7d0c34c422325a5bc
Reviewed-on: https://skia-review.googlesource.com/8129
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/core')
30 files changed, 314 insertions, 162 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index fe43ba24b6..a409517090 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -326,7 +326,6 @@ void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, USE_SHADER: - // TODO(herb): Move this over to SkArenaAlloc when arena alloc has a facility to return sk_sps. // Since the shader need only live for our stack-frame, pass in a custom allocator. This // can save malloc calls, and signals to SkMakeBitmapShader to not try to copy the bitmap // if its mutable, since that precaution is not needed (give the short lifetime of the shader). diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp index 8c648b6051..11deac4aed 100644 --- a/src/core/SkBitmapProcShader.cpp +++ b/src/core/SkBitmapProcShader.cpp @@ -6,8 +6,6 @@ */ #include "SkBitmapProcShader.h" - -#include "SkArenaAlloc.h" #include "SkBitmapProcState.h" #include "SkBitmapProvider.h" #include "SkXfermodePriv.h" @@ -35,6 +33,10 @@ public: } } + ~BitmapProcInfoContext() override { + fInfo->~SkBitmapProcInfo(); + } + uint32_t getFlags() const override { return fFlags; } private: @@ -199,10 +201,10 @@ size_t SkBitmapProcLegacyShader::ContextSize(const ContextRec& rec, const SkImag return s; } -SkShader::Context* SkBitmapProcLegacyShader::MakeContext( - const SkShader& shader, TileMode tmx, TileMode tmy, - const SkBitmapProvider& provider, const ContextRec& rec, SkArenaAlloc* alloc) -{ +SkShader::Context* SkBitmapProcLegacyShader::MakeContext(const SkShader& shader, + TileMode tmx, TileMode tmy, + const SkBitmapProvider& provider, + const ContextRec& rec, void* storage) { SkMatrix totalInverse; // Do this first, so we know the matrix can be inverted. if (!shader.computeTotalInverse(rec, &totalInverse)) { @@ -213,17 +215,21 @@ SkShader::Context* SkBitmapProcLegacyShader::MakeContext( bool useLinearPipeline = choose_linear_pipeline(rec, provider.info()); if (useLinearPipeline) { - SkBitmapProcInfo* info = alloc->make<SkBitmapProcInfo>(provider, tmx, tmy); + void* infoStorage = (char*)storage + sizeof(LinearPipelineContext); + SkBitmapProcInfo* info = new (infoStorage) SkBitmapProcInfo(provider, tmx, tmy); if (!info->init(totalInverse, *rec.fPaint)) { + info->~SkBitmapProcInfo(); return nullptr; } - return alloc->make<LinearPipelineContext>(shader, rec, info); + return new (storage) LinearPipelineContext(shader, rec, info); } else { - SkBitmapProcState* state = alloc->make<SkBitmapProcState>(provider, tmx, tmy); + void* stateStorage = (char*)storage + sizeof(BitmapProcShaderContext); + SkBitmapProcState* state = new (stateStorage) SkBitmapProcState(provider, tmx, tmy); if (!state->setup(totalInverse, *rec.fPaint)) { + state->~SkBitmapProcState(); return nullptr; } - return alloc->make<BitmapProcShaderContext>(shader, rec, state); + return new (storage) BitmapProcShaderContext(shader, rec, state); } } diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h index 204b27dd4c..4b7447e52e 100644 --- a/src/core/SkBitmapProcShader.h +++ b/src/core/SkBitmapProcShader.h @@ -18,7 +18,7 @@ private: static size_t ContextSize(const ContextRec&, const SkImageInfo& srcInfo); static Context* MakeContext(const SkShader&, TileMode tmx, TileMode tmy, - const SkBitmapProvider&, const ContextRec&, SkArenaAlloc* alloc); + const SkBitmapProvider&, const ContextRec&, void* storage); typedef SkShader INHERITED; }; diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index a386904dcd..d8e3dfd664 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkArenaAlloc.h" #include "SkBlitter.h" #include "SkAntiRun.h" #include "SkColor.h" @@ -586,15 +585,24 @@ class Sk3DShader : public SkShader { public: Sk3DShader(sk_sp<SkShader> proxy) : fProxy(std::move(proxy)) {} - Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override { + size_t onContextSize(const ContextRec& rec) const override { + size_t size = sizeof(Sk3DShaderContext); + if (fProxy) { + size += fProxy->contextSize(rec); + } + return size; + } + + Context* onCreateContext(const ContextRec& rec, void* storage) const override { SkShader::Context* proxyContext = nullptr; if (fProxy) { - proxyContext = fProxy->makeContext(rec, alloc); + char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext); + proxyContext = fProxy->createContext(rec, proxyContextStorage); if (!proxyContext) { return nullptr; } } - return alloc->make<Sk3DShaderContext>(*this, rec, proxyContext); + return new (storage) Sk3DShaderContext(*this, rec, proxyContext); } class Sk3DShaderContext : public SkShader::Context { @@ -785,15 +793,15 @@ SkShader::ContextRec::DstType SkBlitter::PreferredShaderDest(const SkImageInfo& SkBlitter* SkBlitter::Choose(const SkPixmap& device, const SkMatrix& matrix, const SkPaint& origPaint, - SkArenaAlloc* alloc, + SkTBlitterAllocator* allocator, bool drawCoverage) { - SkASSERT(alloc != nullptr); + SkASSERT(allocator != nullptr); // which check, in case we're being called by a client with a dummy device // (e.g. they have a bounder that always aborts the draw) if (kUnknown_SkColorType == device.colorType() || (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) { - return alloc->make<SkNullBlitter>(); + return allocator->createT<SkNullBlitter>(); } SkShader* shader = origPaint.getShader(); @@ -819,7 +827,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, paint.writable()->setBlendMode(mode); break; case kSkipDrawing_SkXfermodeInterpretation:{ - return alloc->make<SkNullBlitter>(); + return allocator->createT<SkNullBlitter>(); } default: break; @@ -844,10 +852,10 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, if (kAlpha_8_SkColorType == device.colorType() && drawCoverage) { SkASSERT(nullptr == shader); SkASSERT(paint->isSrcOver()); - return alloc->make<SkA8_Coverage_Blitter>(device, *paint); + return allocator->createT<SkA8_Coverage_Blitter>(device, *paint); } - if (SkBlitter* blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc)) { + if (SkBlitter* blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, allocator)) { return blitter; } @@ -883,12 +891,21 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, const SkShader::ContextRec rec(*paint, matrix, nullptr, PreferredShaderDest(device.info()), device.colorSpace()); - // Try to create the ShaderContext - shaderContext = shader->makeContext(rec, alloc); - if (!shaderContext) { - return alloc->make<SkNullBlitter>(); + size_t contextSize = shader->contextSize(rec); + if (contextSize) { + // Try to create the ShaderContext + shaderContext = allocator->createWithIniter( + contextSize, + [&rec, shader](void* storage) { + return shader->createContext(rec, storage); + }); + if (!shaderContext) { + return allocator->createT<SkNullBlitter>(); + } + SkASSERT(shaderContext); + } else { + return allocator->createT<SkNullBlitter>(); } - SkASSERT(shaderContext); } SkBlitter* blitter = nullptr; @@ -896,14 +913,14 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, case kAlpha_8_SkColorType: SkASSERT(!drawCoverage); // Handled above. if (shader) { - blitter = alloc->make<SkA8_Shader_Blitter>(device, *paint, shaderContext); + blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext); } else { - blitter = alloc->make<SkA8_Blitter>(device, *paint); + blitter = allocator->createT<SkA8_Blitter>(device, *paint); } break; case kRGB_565_SkColorType: - blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, alloc); + blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator); break; case kN32_SkColorType: @@ -913,23 +930,23 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, if (device.info().gammaCloseToSRGB()) #endif { - blitter = SkBlitter_ARGB32_Create(device, *paint, shaderContext, alloc); + blitter = SkBlitter_ARGB32_Create(device, *paint, shaderContext, allocator); } else { if (shader) { - blitter = alloc->make<SkARGB32_Shader_Blitter>( + blitter = allocator->createT<SkARGB32_Shader_Blitter>( device, *paint, shaderContext); } else if (paint->getColor() == SK_ColorBLACK) { - blitter = alloc->make<SkARGB32_Black_Blitter>(device, *paint); + blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint); } else if (paint->getAlpha() == 0xFF) { - blitter = alloc->make<SkARGB32_Opaque_Blitter>(device, *paint); + blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint); } else { - blitter = alloc->make<SkARGB32_Blitter>(device, *paint); + blitter = allocator->createT<SkARGB32_Blitter>(device, *paint); } } break; case kRGBA_F16_SkColorType: - blitter = SkBlitter_F16_Create(device, *paint, shaderContext, alloc); + blitter = SkBlitter_F16_Create(device, *paint, shaderContext, allocator); break; default: @@ -937,16 +954,15 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, } if (!blitter) { - blitter = alloc->make<SkNullBlitter>(); + blitter = allocator->createT<SkNullBlitter>(); } if (shader3D) { SkBlitter* innerBlitter = blitter; - // FIXME - comment about allocator // innerBlitter was allocated by allocator, which will delete it. // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to // wrapper the blitter to notify it when we see an emboss mask. - blitter = alloc->make<Sk3DBlitter>(innerBlitter, shaderContext); + blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext); } return blitter; } diff --git a/src/core/SkBlitter.h b/src/core/SkBlitter.h index 4d34ce3e91..cab2afc974 100644 --- a/src/core/SkBlitter.h +++ b/src/core/SkBlitter.h @@ -137,7 +137,7 @@ public: static SkBlitter* Choose(const SkPixmap& dst, const SkMatrix& matrix, const SkPaint& paint, - SkArenaAlloc*, + SkTBlitterAllocator*, bool drawCoverage = false); static SkBlitter* ChooseSprite(const SkPixmap& dst, diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp index 61105ce2db..ce66580659 100644 --- a/src/core/SkBlitter_PM4f.cpp +++ b/src/core/SkBlitter_PM4f.cpp @@ -6,8 +6,6 @@ */ #include "SkCoreBlitters.h" - -#include "SkArenaAlloc.h" #include "SkColorPriv.h" #include "SkShader.h" #include "SkUtils.h" @@ -405,8 +403,8 @@ struct StateF16 : State4f { template <typename State> SkBlitter* create(const SkPixmap& device, const SkPaint& paint, SkShader::Context* shaderContext, - SkArenaAlloc* alloc) { - SkASSERT(alloc != nullptr); + SkTBlitterAllocator* allocator) { + SkASSERT(allocator != nullptr); if (shaderContext) { SkShader::Context::BlitState bstate; @@ -415,24 +413,24 @@ template <typename State> SkBlitter* create(const SkPixmap& device, const SkPain bstate.fMode = paint.getBlendMode(); (void)shaderContext->chooseBlitProcs(device.info(), &bstate); - return alloc->make<SkState_Shader_Blitter<State>>(device, paint, bstate); + return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, bstate); } else { SkColor color = paint.getColor(); if (0 == SkColorGetA(color)) { return nullptr; } - return alloc->make<SkState_Blitter<State>>(device, paint); + return allocator->createT<SkState_Blitter<State>>(device, paint); } } SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint, SkShader::Context* shaderContext, - SkArenaAlloc* alloc) { - return create<State32>(device, paint, shaderContext, alloc); + SkTBlitterAllocator* allocator) { + return create<State32>(device, paint, shaderContext, allocator); } SkBlitter* SkBlitter_F16_Create(const SkPixmap& device, const SkPaint& paint, SkShader::Context* shaderContext, - SkArenaAlloc* alloc) { - return create<StateF16>(device, paint, shaderContext, alloc); + SkTBlitterAllocator* allocator) { + return create<StateF16>(device, paint, shaderContext, allocator); } diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp index e91e23fd69..afa8cac184 100644 --- a/src/core/SkBlitter_RGB16.cpp +++ b/src/core/SkBlitter_RGB16.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkArenaAlloc.h" #include "SkBlitRow.h" #include "SkCoreBlitters.h" #include "SkColorPriv.h" @@ -881,8 +880,8 @@ void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, SkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint, SkShader::Context* shaderContext, - SkArenaAlloc* alloc) { - SkASSERT(alloc != nullptr); + SkTBlitterAllocator* allocator) { + SkASSERT(allocator != nullptr); SkBlitter* blitter; SkShader* shader = paint.getShader(); @@ -894,24 +893,24 @@ SkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint, if (shader) { SkASSERT(shaderContext != nullptr); if (!is_srcover) { - blitter = alloc->make<SkRGB16_Shader_Xfermode_Blitter>(device, paint, + blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint, shaderContext); } else { - blitter = alloc->make<SkRGB16_Shader_Blitter>(device, paint, shaderContext); + blitter = allocator->createT<SkRGB16_Shader_Blitter>(device, paint, shaderContext); } } else { // no shader, no xfermode, (and we always ignore colorfilter) SkColor color = paint.getColor(); if (0 == SkColorGetA(color)) { - blitter = alloc->make<SkNullBlitter>(); + blitter = allocator->createT<SkNullBlitter>(); #ifdef USE_BLACK_BLITTER } else if (SK_ColorBLACK == color) { - blitter = alloc->make<SkRGB16_Black_Blitter>(device, paint); + blitter = allocator->createT<SkRGB16_Black_Blitter>(device, paint); #endif } else if (0xFF == SkColorGetA(color)) { - blitter = alloc->make<SkRGB16_Opaque_Blitter>(device, paint); + blitter = allocator->createT<SkRGB16_Opaque_Blitter>(device, paint); } else { - blitter = alloc->make<SkRGB16_Blitter>(device, paint); + blitter = allocator->createT<SkRGB16_Blitter>(device, paint); } } diff --git a/src/core/SkColorFilterShader.cpp b/src/core/SkColorFilterShader.cpp index 5e96b24b41..4090a18b45 100644 --- a/src/core/SkColorFilterShader.cpp +++ b/src/core/SkColorFilterShader.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkArenaAlloc.h" #include "SkColorFilterShader.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" @@ -53,15 +52,19 @@ uint32_t SkColorFilterShader::FilterShaderContext::getFlags() const { return shaderF; } -SkShader::Context* SkColorFilterShader::onMakeContext(const ContextRec& rec, - SkArenaAlloc* alloc) const { - SkShader::Context* shaderContext = fShader->makeContext(rec, alloc); +SkShader::Context* SkColorFilterShader::onCreateContext(const ContextRec& rec, + void* storage) const { + char* shaderContextStorage = (char*)storage + sizeof(FilterShaderContext); + SkShader::Context* shaderContext = fShader->createContext(rec, shaderContextStorage); if (nullptr == shaderContext) { return nullptr; } - return alloc->make<FilterShaderContext>(*this, shaderContext, rec); + return new (storage) FilterShaderContext(*this, shaderContext, rec); } +size_t SkColorFilterShader::onContextSize(const ContextRec& rec) const { + return sizeof(FilterShaderContext) + fShader->contextSize(rec); +} SkColorFilterShader::FilterShaderContext::FilterShaderContext( const SkColorFilterShader& filterShader, @@ -71,6 +74,10 @@ SkColorFilterShader::FilterShaderContext::FilterShaderContext( , fShaderContext(shaderContext) {} +SkColorFilterShader::FilterShaderContext::~FilterShaderContext() { + fShaderContext->~Context(); +} + void SkColorFilterShader::FilterShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { const SkColorFilterShader& filterShader = static_cast<const SkColorFilterShader&>(fShader); diff --git a/src/core/SkColorFilterShader.h b/src/core/SkColorFilterShader.h index e697736ae8..035acd8397 100644 --- a/src/core/SkColorFilterShader.h +++ b/src/core/SkColorFilterShader.h @@ -11,8 +11,6 @@ #include "SkColorFilter.h" #include "SkShader.h" -class SkArenaAlloc; - class SkColorFilterShader : public SkShader { public: SkColorFilterShader(sk_sp<SkShader> shader, sk_sp<SkColorFilter> filter); @@ -25,6 +23,7 @@ public: public: // Takes ownership of shaderContext and calls its destructor. FilterShaderContext(const SkColorFilterShader&, SkShader::Context*, const ContextRec&); + virtual ~FilterShaderContext(); uint32_t getFlags() const override; @@ -47,7 +46,8 @@ public: protected: void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc* alloc) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; private: sk_sp<SkShader> fShader; diff --git a/src/core/SkColorShader.cpp b/src/core/SkColorShader.cpp index 32d9b430c7..ed2a26b931 100644 --- a/src/core/SkColorShader.cpp +++ b/src/core/SkColorShader.cpp @@ -31,8 +31,8 @@ uint32_t SkColorShader::ColorShaderContext::getFlags() const { return fFlags; } -SkShader::Context* SkColorShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { - return alloc->make<ColorShaderContext>(*this, rec); +SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const { + return new (storage) ColorShaderContext(*this, rec); } SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, @@ -149,8 +149,8 @@ uint32_t SkColor4Shader::Color4Context::getFlags() const { return fFlags; } -SkShader::Context* SkColor4Shader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { - return alloc->make<Color4Context>(*this, rec); +SkShader::Context* SkColor4Shader::onCreateContext(const ContextRec& rec, void* storage) const { + return new (storage) Color4Context(*this, rec); } SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader, diff --git a/src/core/SkColorShader.h b/src/core/SkColorShader.h index b9db657b2b..813fd3e892 100644 --- a/src/core/SkColorShader.h +++ b/src/core/SkColorShader.h @@ -59,13 +59,12 @@ public: protected: SkColorShader(SkReadBuffer&); void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc* storage) const override; - + Context* onCreateContext(const ContextRec&, void* storage) const override; + size_t onContextSize(const ContextRec&) const override { return sizeof(ColorShaderContext); } bool onAsLuminanceColor(SkColor* lum) const override { *lum = fColor; return true; } - bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, const SkMatrix& ctm, const SkPaint&, const SkMatrix*) const override; @@ -116,7 +115,8 @@ public: protected: SkColor4Shader(SkReadBuffer&); void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; + size_t onContextSize(const ContextRec&) const override { return sizeof(Color4Context); } bool onAsLuminanceColor(SkColor* lum) const override { *lum = fCachedByteColor; return true; diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp index 07bbd9a092..5cbd23eb08 100644 --- a/src/core/SkComposeShader.cpp +++ b/src/core/SkComposeShader.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkArenaAlloc.h" #include "SkComposeShader.h" #include "SkColorFilter.h" #include "SkColorPriv.h" @@ -30,6 +29,12 @@ sk_sp<SkShader> SkShader::MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> /////////////////////////////////////////////////////////////////////////////// +size_t SkComposeShader::onContextSize(const ContextRec& rec) const { + return sizeof(ComposeShaderContext) + + fShaderA->contextSize(rec) + + fShaderB->contextSize(rec); +} + class SkAutoAlphaRestore { public: SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) { @@ -75,9 +80,10 @@ template <typename T> void safe_call_destructor(T* obj) { } } -SkShader::Context* SkComposeShader::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ +SkShader::Context* SkComposeShader::onCreateContext(const ContextRec& rec, void* storage) const { + char* aStorage = (char*) storage + sizeof(ComposeShaderContext); + char* bStorage = aStorage + fShaderA->contextSize(rec); + // we preconcat our localMatrix (if any) with the device matrix // before calling our sub-shaders SkMatrix tmpM; @@ -93,15 +99,15 @@ SkShader::Context* SkComposeShader::onMakeContext( newRec.fMatrix = &tmpM; newRec.fPaint = &opaquePaint; - SkShader::Context* contextA = fShaderA->makeContext(newRec, alloc); - SkShader::Context* contextB = fShaderB->makeContext(newRec, alloc); + SkShader::Context* contextA = fShaderA->createContext(newRec, aStorage); + SkShader::Context* contextB = fShaderB->createContext(newRec, bStorage); if (!contextA || !contextB) { safe_call_destructor(contextA); safe_call_destructor(contextB); return nullptr; } - return alloc->make<ComposeShaderContext>(*this, rec, contextA, contextB); + return new (storage) ComposeShaderContext(*this, rec, contextA, contextB); } SkComposeShader::ComposeShaderContext::ComposeShaderContext( @@ -111,6 +117,11 @@ SkComposeShader::ComposeShaderContext::ComposeShaderContext( , fShaderContextA(contextA) , fShaderContextB(contextB) {} +SkComposeShader::ComposeShaderContext::~ComposeShaderContext() { + fShaderContextA->~Context(); + fShaderContextB->~Context(); +} + bool SkComposeShader::asACompose(ComposeRec* rec) const { if (rec) { rec->fShaderA = fShaderA.get(); diff --git a/src/core/SkComposeShader.h b/src/core/SkComposeShader.h index be788af2af..7f9ff69ca8 100644 --- a/src/core/SkComposeShader.h +++ b/src/core/SkComposeShader.h @@ -45,6 +45,8 @@ public: ComposeShaderContext(const SkComposeShader&, const ContextRec&, SkShader::Context* contextA, SkShader::Context* contextB); + virtual ~ComposeShaderContext(); + void shadeSpan(int x, int y, SkPMColor[], int count) override; private: @@ -67,7 +69,8 @@ public: protected: SkComposeShader(SkReadBuffer&); void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void*) const override; private: sk_sp<SkShader> fShaderA; diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h index 63ddda9b13..62bf73e6a2 100644 --- a/src/core/SkCoreBlitters.h +++ b/src/core/SkCoreBlitters.h @@ -178,10 +178,10 @@ private: }; SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint&, SkShader::Context*, - SkArenaAlloc*); + SkTBlitterAllocator*); SkBlitter* SkBlitter_F16_Create(const SkPixmap& device, const SkPaint&, SkShader::Context*, - SkArenaAlloc*); + SkTBlitterAllocator*); /////////////////////////////////////////////////////////////////////////////// @@ -200,11 +200,11 @@ SkBlitter* SkBlitter_F16_Create(const SkPixmap& device, const SkPaint&, SkShader SkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint, SkShader::Context* shaderContext, - SkArenaAlloc* allocator); + SkTBlitterAllocator* allocator); // Returns nullptr if no SkRasterPipeline blitter can be constructed for this paint. SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap&, const SkPaint&, const SkMatrix& ctm, - SkArenaAlloc*); + SkTBlitterAllocator*); #endif diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 2891c95fdd..dd39d9eb97 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -7,8 +7,6 @@ #define __STDC_LIMIT_MACROS #include "SkDraw.h" - -#include "SkArenaAlloc.h" #include "SkBlendModePriv.h" #include "SkBlitter.h" #include "SkCanvas.h" @@ -55,7 +53,7 @@ public: } SkAutoBlitterChoose(const SkPixmap& dst, const SkMatrix& matrix, const SkPaint& paint, bool drawCoverage = false) { - fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAlloc, drawCoverage); + fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAllocator, drawCoverage); } SkBlitter* operator->() { return fBlitter; } @@ -64,16 +62,13 @@ public: void choose(const SkPixmap& dst, const SkMatrix& matrix, const SkPaint& paint, bool drawCoverage = false) { SkASSERT(!fBlitter); - fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAlloc, drawCoverage); + fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAllocator, drawCoverage); } private: // Owned by fAllocator, which will handle the delete. SkBlitter* fBlitter; SkTBlitterAllocator fAllocator; - - // FIXME - pick a good inline and number. - SkArenaAlloc fAlloc{1024}; }; #define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose) @@ -87,8 +82,6 @@ public: SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint, const SkMatrix* localMatrix = nullptr) : fPaint(paint) /* makes a copy of the paint */ { - // TODO(herb): Move this over to SkArenaAlloc when arena alloc has a - // facility to return sk_sps. fPaint.setShader(SkMakeBitmapShader(src, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, localMatrix, kNever_SkCopyPixelsMode, @@ -1776,8 +1769,9 @@ public: } protected: - Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override { - return alloc->make<TriColorShaderContext>(*this, rec); + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec& rec, void* storage) const override { + return new (storage) TriColorShaderContext(*this, rec); } private: @@ -1833,6 +1827,10 @@ SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorS SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} +size_t SkTriColorShader::onContextSize(const ContextRec&) const { + return sizeof(TriColorShaderContext); +} + void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { SkTriColorShader* parent = static_cast<SkTriColorShader*>(const_cast<SkShader*>(&fShader)); TriColorShaderData* set = parent->takeSetupData(); diff --git a/src/core/SkEmptyShader.h b/src/core/SkEmptyShader.h index b2c9b76792..528ceeabee 100644 --- a/src/core/SkEmptyShader.h +++ b/src/core/SkEmptyShader.h @@ -24,7 +24,13 @@ public: SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkEmptyShader) protected: - SkShader::Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override { + size_t onContextSize(const ContextRec&) const override { + // Even though createContext returns nullptr we have to return a value of at least + // sizeof(SkShader::Context) to satisfy SkSmallAllocator. + return sizeof(SkShader::Context); + } + + SkShader::Context* onCreateContext(const ContextRec&, void*) const override { return nullptr; } diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp index 5bdaee5594..4ed0057682 100644 --- a/src/core/SkLightingShader.cpp +++ b/src/core/SkLightingShader.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkArenaAlloc.h" #include "SkBitmapProcShader.h" #include "SkBitmapProcState.h" #include "SkColor.h" @@ -64,6 +63,8 @@ public: SkShader::Context* diffuseContext, SkNormalSource::Provider*, void* heapAllocated); + ~LightingShaderContext() override; + void shadeSpan(int x, int y, SkPMColor[], int count) override; uint32_t getFlags() const override { return fFlags; } @@ -74,6 +75,8 @@ public: SkColor fPaintColor; uint32_t fFlags; + void* fHeapAllocated; + typedef SkShader::Context INHERITED; }; @@ -82,7 +85,8 @@ public: protected: void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void*) const override; private: sk_sp<SkShader> fDiffuseShader; @@ -305,7 +309,8 @@ SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( void* heapAllocated) : INHERITED(shader, rec) , fDiffuseContext(diffuseContext) - , fNormalProvider(normalProvider) { + , fNormalProvider(normalProvider) + , fHeapAllocated(heapAllocated) { bool isOpaque = shader.isOpaque(); // update fFlags @@ -318,6 +323,17 @@ SkLightingShaderImpl::LightingShaderContext::LightingShaderContext( fFlags = flags; } +SkLightingShaderImpl::LightingShaderContext::~LightingShaderContext() { + // The dependencies have been created outside of the context on memory that was allocated by + // the onCreateContext() method. Call the destructors and free the memory. + if (fDiffuseContext) { + fDiffuseContext->~Context(); + } + fNormalProvider->~Provider(); + + sk_free(fHeapAllocated); +} + static inline SkPMColor convert(SkColor3f color, U8CPU a) { if (color.fX <= 0.0f) { color.fX = 0.0f; @@ -441,23 +457,39 @@ void SkLightingShaderImpl::flatten(SkWriteBuffer& buf) const { } } -SkShader::Context* SkLightingShaderImpl::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ +size_t SkLightingShaderImpl::onContextSize(const ContextRec& rec) const { + return sizeof(LightingShaderContext); +} + +SkShader::Context* SkLightingShaderImpl::onCreateContext(const ContextRec& rec, + void* storage) const { + size_t heapRequired = (fDiffuseShader ? fDiffuseShader->contextSize(rec) : 0) + + fNormalSource->providerSize(rec); + void* heapAllocated = sk_malloc_throw(heapRequired); + + void* diffuseContextStorage = heapAllocated; + void* normalProviderStorage = (char*) diffuseContextStorage + + (fDiffuseShader ? fDiffuseShader->contextSize(rec) : 0); + SkShader::Context *diffuseContext = nullptr; if (fDiffuseShader) { - diffuseContext = fDiffuseShader->makeContext(rec, alloc); + diffuseContext = fDiffuseShader->createContext(rec, diffuseContextStorage); if (!diffuseContext) { + sk_free(heapAllocated); return nullptr; } } - SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec, alloc); + SkNormalSource::Provider* normalProvider = fNormalSource->asProvider(rec, + normalProviderStorage); if (!normalProvider) { + diffuseContext->~Context(); + sk_free(heapAllocated); return nullptr; } - return alloc->make<LightingShaderContext>(*this, rec, diffuseContext, normalProvider, nullptr); + return new (storage) LightingShaderContext(*this, rec, diffuseContext, normalProvider, + heapAllocated); } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkLocalMatrixShader.cpp b/src/core/SkLocalMatrixShader.cpp index 9d9e109fcb..7a0a3697bd 100644 --- a/src/core/SkLocalMatrixShader.cpp +++ b/src/core/SkLocalMatrixShader.cpp @@ -37,9 +37,8 @@ void SkLocalMatrixShader::flatten(SkWriteBuffer& buffer) const { buffer.writeFlattenable(fProxyShader.get()); } -SkShader::Context* SkLocalMatrixShader::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ +SkShader::Context* SkLocalMatrixShader::onCreateContext(const ContextRec& rec, + void* storage) const { ContextRec newRec(rec); SkMatrix tmp; if (rec.fLocalMatrix) { @@ -48,7 +47,7 @@ SkShader::Context* SkLocalMatrixShader::onMakeContext( } else { newRec.fLocalMatrix = &this->getLocalMatrix(); } - return fProxyShader->makeContext(newRec, alloc); + return fProxyShader->createContext(newRec, storage); } bool SkLocalMatrixShader::onAppendStages(SkRasterPipeline* p, diff --git a/src/core/SkLocalMatrixShader.h b/src/core/SkLocalMatrixShader.h index 5c0424053b..0641abe461 100644 --- a/src/core/SkLocalMatrixShader.h +++ b/src/core/SkLocalMatrixShader.h @@ -13,7 +13,6 @@ #include "SkWriteBuffer.h" class GrFragmentProcessor; -class SkArenaAlloc; class SkLocalMatrixShader : public SkShader { public: @@ -42,8 +41,11 @@ public: protected: void flatten(SkWriteBuffer&) const override; + Context* onCreateContext(const ContextRec&, void*) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + size_t onContextSize(const ContextRec& rec) const override { + return fProxyShader->contextSize(rec); + } SkImage* onIsAImage(SkMatrix* matrix, TileMode* mode) const override { return fProxyShader->isAImage(matrix, mode); diff --git a/src/core/SkNormalBevelSource.cpp b/src/core/SkNormalBevelSource.cpp index 5ff7d8231f..5d49253b01 100644 --- a/src/core/SkNormalBevelSource.cpp +++ b/src/core/SkNormalBevelSource.cpp @@ -7,7 +7,6 @@ #include "SkNormalBevelSource.h" -#include "SkArenaAlloc.h" #include "SkNormalSource.h" #include "SkNormalSourcePriv.h" #include "SkPoint3.h" @@ -264,8 +263,12 @@ SkNormalBevelSourceImpl::Provider::Provider() {} SkNormalBevelSourceImpl::Provider::~Provider() {} SkNormalSource::Provider* SkNormalBevelSourceImpl::asProvider(const SkShader::ContextRec &rec, - SkArenaAlloc* alloc) const { - return alloc->make<Provider>(); + void *storage) const { + return new (storage) Provider(); +} + +size_t SkNormalBevelSourceImpl::providerSize(const SkShader::ContextRec&) const { + return sizeof(Provider); } // TODO Implement feature for the CPU pipeline diff --git a/src/core/SkNormalBevelSource.h b/src/core/SkNormalBevelSource.h index 1d1983c66a..d133738bce 100644 --- a/src/core/SkNormalBevelSource.h +++ b/src/core/SkNormalBevelSource.h @@ -22,7 +22,8 @@ public: #endif SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec, - SkArenaAlloc*) const override; + void* storage) const override; + size_t providerSize(const SkShader::ContextRec& rec) const override; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkNormalBevelSourceImpl) diff --git a/src/core/SkNormalFlatSource.cpp b/src/core/SkNormalFlatSource.cpp index 73ef549747..b4ed977285 100644 --- a/src/core/SkNormalFlatSource.cpp +++ b/src/core/SkNormalFlatSource.cpp @@ -7,7 +7,6 @@ #include "SkNormalFlatSource.h" -#include "SkArenaAlloc.h" #include "SkNormalSource.h" #include "SkNormalSourcePriv.h" #include "SkPoint3.h" @@ -78,8 +77,12 @@ SkNormalFlatSourceImpl::Provider::Provider() {} SkNormalFlatSourceImpl::Provider::~Provider() {} SkNormalSource::Provider* SkNormalFlatSourceImpl::asProvider(const SkShader::ContextRec &rec, - SkArenaAlloc *alloc) const { - return alloc->make<Provider>(); + void *storage) const { + return new (storage) Provider(); +} + +size_t SkNormalFlatSourceImpl::providerSize(const SkShader::ContextRec&) const { + return sizeof(Provider); } void SkNormalFlatSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[], diff --git a/src/core/SkNormalFlatSource.h b/src/core/SkNormalFlatSource.h index 4a8f74304b..e1295596b9 100644 --- a/src/core/SkNormalFlatSource.h +++ b/src/core/SkNormalFlatSource.h @@ -19,7 +19,8 @@ public: #endif SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec, - SkArenaAlloc* alloc) const override; + void* storage) const override; + size_t providerSize(const SkShader::ContextRec& rec) const override; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkNormalFlatSourceImpl) diff --git a/src/core/SkNormalMapSource.cpp b/src/core/SkNormalMapSource.cpp index 2d3d24181d..3a9f9cf76f 100644 --- a/src/core/SkNormalMapSource.cpp +++ b/src/core/SkNormalMapSource.cpp @@ -7,7 +7,6 @@ #include "SkNormalMapSource.h" -#include "SkArenaAlloc.h" #include "SkLightingShader.h" #include "SkMatrix.h" #include "SkNormalSource.h" @@ -137,29 +136,42 @@ sk_sp<GrFragmentProcessor> SkNormalMapSourceImpl::asFragmentProcessor( //////////////////////////////////////////////////////////////////////////// SkNormalMapSourceImpl::Provider::Provider(const SkNormalMapSourceImpl& source, - SkShader::Context* mapContext) + SkShader::Context* mapContext, + SkPaint* overridePaint) : fSource(source) - , fMapContext(mapContext) {} + , fMapContext(mapContext) + , fOverridePaint(overridePaint) {} + +SkNormalMapSourceImpl::Provider::~Provider() { + fMapContext->~Context(); + fOverridePaint->~SkPaint(); +} SkNormalSource::Provider* SkNormalMapSourceImpl::asProvider(const SkShader::ContextRec &rec, - SkArenaAlloc* alloc) const { + void *storage) const { SkMatrix normTotalInv; if (!this->computeNormTotalInverse(rec, &normTotalInv)) { return nullptr; } // Overriding paint's alpha because we need the normal map's RGB channels to be unpremul'd - SkPaint overridePaint {*(rec.fPaint)}; - overridePaint.setAlpha(0xFF); - SkShader::ContextRec overrideRec(overridePaint, *(rec.fMatrix), rec.fLocalMatrix, + void* paintStorage = (char*)storage + sizeof(Provider); + SkPaint* overridePaint = new (paintStorage) SkPaint(*(rec.fPaint)); + overridePaint->setAlpha(0xFF); + SkShader::ContextRec overrideRec(*overridePaint, *(rec.fMatrix), rec.fLocalMatrix, rec.fPreferredDstType, rec.fDstColorSpace); - SkShader::Context* context = fMapShader->makeContext(overrideRec, alloc); + void* mapContextStorage = (char*) paintStorage + sizeof(SkPaint); + SkShader::Context* context = fMapShader->createContext(overrideRec, mapContextStorage); if (!context) { return nullptr; } - return alloc->make<Provider>(*this, context); + return new (storage) Provider(*this, context, overridePaint); +} + +size_t SkNormalMapSourceImpl::providerSize(const SkShader::ContextRec& rec) const { + return sizeof(Provider) + sizeof(SkPaint) + fMapShader->contextSize(rec); } bool SkNormalMapSourceImpl::computeNormTotalInverse(const SkShader::ContextRec& rec, diff --git a/src/core/SkNormalMapSource.h b/src/core/SkNormalMapSource.h index f2b07f21e9..5908369fc7 100644 --- a/src/core/SkNormalMapSource.h +++ b/src/core/SkNormalMapSource.h @@ -21,7 +21,8 @@ public: #endif SkNormalSource::Provider* asProvider(const SkShader::ContextRec& rec, - SkArenaAlloc* alloc) const override; + void* storage) const override; + size_t providerSize(const SkShader::ContextRec& rec) const override; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkNormalMapSourceImpl) @@ -33,7 +34,10 @@ protected: private: class Provider : public SkNormalSource::Provider { public: - Provider(const SkNormalMapSourceImpl& source, SkShader::Context* mapContext); + Provider(const SkNormalMapSourceImpl& source, SkShader::Context* mapContext, + SkPaint* overridePaint); + + virtual ~Provider() override; void fillScanLine(int x, int y, SkPoint3 output[], int count) const override; @@ -41,6 +45,8 @@ private: const SkNormalMapSourceImpl& fSource; SkShader::Context* fMapContext; + SkPaint* fOverridePaint; + typedef SkNormalSource::Provider INHERITED; }; diff --git a/src/core/SkNormalSource.h b/src/core/SkNormalSource.h index 221c09db99..32ef08ce52 100644 --- a/src/core/SkNormalSource.h +++ b/src/core/SkNormalSource.h @@ -44,7 +44,11 @@ public: /** Returns an instance of 'Provider' that provides normals for the CPU pipeline. The necessary data will be initialized in place at 'storage'. */ - virtual Provider* asProvider(const SkShader::ContextRec&, SkArenaAlloc*) const = 0; + virtual Provider* asProvider(const SkShader::ContextRec&, void* storage) const = 0; + + /** Amount of memory needed to store a provider object and its dependencies. + */ + virtual size_t providerSize(const SkShader::ContextRec&) const = 0; /** Returns a normal source that provides normals sourced from the the normal map argument. diff --git a/src/core/SkPictureShader.cpp b/src/core/SkPictureShader.cpp index 71026824cd..bdb6d060a7 100644 --- a/src/core/SkPictureShader.cpp +++ b/src/core/SkPictureShader.cpp @@ -243,6 +243,19 @@ sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, con return tileShader; } +size_t SkPictureShader::onContextSize(const ContextRec&) const { + return sizeof(PictureShaderContext); +} + +SkShader::Context* SkPictureShader::onCreateContext(const ContextRec& rec, void* storage) const { + sk_sp<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix, + rec.fDstColorSpace)); + if (!bitmapShader) { + return nullptr; + } + return PictureShaderContext::Create(storage, *this, rec, bitmapShader); +} + bool SkPictureShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc, const SkMatrix& ctm, const SkPaint& paint, const SkMatrix* localMatrix) const { @@ -253,34 +266,36 @@ bool SkPictureShader::onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkAr } ///////////////////////////////////////////////////////////////////////////////////////// -SkShader::Context* SkPictureShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) -const { - sk_sp<SkShader> bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix, - rec.fDstColorSpace)); - if (!bitmapShader) { - return nullptr; - } - PictureShaderContext* ctx = - alloc->make<PictureShaderContext>(*this, rec, std::move(bitmapShader), alloc); +SkShader::Context* SkPictureShader::PictureShaderContext::Create(void* storage, + const SkPictureShader& shader, const ContextRec& rec, + sk_sp<SkShader> bitmapShader) { + PictureShaderContext* ctx = new (storage) PictureShaderContext(shader, rec, + std::move(bitmapShader)); if (nullptr == ctx->fBitmapShaderContext) { + ctx->~PictureShaderContext(); ctx = nullptr; } return ctx; } -///////////////////////////////////////////////////////////////////////////////////////// - SkPictureShader::PictureShaderContext::PictureShaderContext( - const SkPictureShader& shader, const ContextRec& rec, sk_sp<SkShader> bitmapShader, - SkArenaAlloc* alloc) + const SkPictureShader& shader, const ContextRec& rec, sk_sp<SkShader> bitmapShader) : INHERITED(shader, rec) , fBitmapShader(std::move(bitmapShader)) { - fBitmapShaderContext = fBitmapShader->makeContext(rec, alloc); + fBitmapShaderContextStorage = sk_malloc_throw(fBitmapShader->contextSize(rec)); + fBitmapShaderContext = fBitmapShader->createContext(rec, fBitmapShaderContextStorage); //if fBitmapShaderContext is null, we are invalid } +SkPictureShader::PictureShaderContext::~PictureShaderContext() { + if (fBitmapShaderContext) { + fBitmapShaderContext->~Context(); + } + sk_free(fBitmapShaderContextStorage); +} + uint32_t SkPictureShader::PictureShaderContext::getFlags() const { SkASSERT(fBitmapShaderContext); return fBitmapShaderContext->getFlags(); diff --git a/src/core/SkPictureShader.h b/src/core/SkPictureShader.h index 9807cd9482..ff83fa3bb8 100644 --- a/src/core/SkPictureShader.h +++ b/src/core/SkPictureShader.h @@ -10,7 +10,6 @@ #include "SkShader.h" -class SkArenaAlloc; class SkBitmap; class SkPicture; @@ -35,9 +34,10 @@ public: protected: SkPictureShader(SkReadBuffer&); void flatten(SkWriteBuffer&) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; bool onAppendStages(SkRasterPipeline*, SkColorSpace*, SkArenaAlloc*, const SkMatrix&, const SkPaint&, const SkMatrix*) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; private: SkPictureShader(sk_sp<SkPicture>, TileMode, TileMode, const SkMatrix*, const SkRect*); @@ -52,14 +52,20 @@ private: class PictureShaderContext : public SkShader::Context { public: - PictureShaderContext( - const SkPictureShader&, const ContextRec&, sk_sp<SkShader> bitmapShader, SkArenaAlloc*); + static Context* Create(void* storage, const SkPictureShader&, const ContextRec&, + sk_sp<SkShader> bitmapShader); + + virtual ~PictureShaderContext(); uint32_t getFlags() const override; ShadeProc asAShadeProc(void** ctx) override; void shadeSpan(int x, int y, SkPMColor dstC[], int count) override; + private: + PictureShaderContext(const SkPictureShader&, const ContextRec&, + sk_sp<SkShader> bitmapShader); + sk_sp<SkShader> fBitmapShader; SkShader::Context* fBitmapShaderContext; void* fBitmapShaderContextStorage; diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp index 1a00009734..bb89f76b8f 100644 --- a/src/core/SkRasterPipelineBlitter.cpp +++ b/src/core/SkRasterPipelineBlitter.cpp @@ -21,7 +21,7 @@ class SkRasterPipelineBlitter : public SkBlitter { public: static SkBlitter* Create(const SkPixmap&, const SkPaint&, const SkMatrix& ctm, - SkArenaAlloc*); + SkTBlitterAllocator*); SkRasterPipelineBlitter(SkPixmap dst, SkBlendMode blend, SkPM4f paintColor) : fDst(dst) @@ -71,7 +71,7 @@ private: SkBlitter* SkCreateRasterPipelineBlitter(const SkPixmap& dst, const SkPaint& paint, const SkMatrix& ctm, - SkArenaAlloc* alloc) { + SkTBlitterAllocator* alloc) { return SkRasterPipelineBlitter::Create(dst, paint, ctm, alloc); } @@ -88,12 +88,16 @@ static bool supported(const SkImageInfo& info) { SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, const SkPaint& paint, const SkMatrix& ctm, - SkArenaAlloc* alloc) { - auto blitter = alloc->make<SkRasterPipelineBlitter>( + SkTBlitterAllocator* alloc) { + auto blitter = alloc->createT<SkRasterPipelineBlitter>( dst, paint.getBlendMode(), SkPM4f_from_SkColor(paint.getColor(), dst.colorSpace())); + auto earlyOut = [&] { + alloc->deleteLast(); + return nullptr; + }; SkBlendMode* blend = &blitter->fBlend; SkPM4f* paintColor = &blitter->fPaintColor; @@ -104,7 +108,7 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, // TODO: all temporary if (!supported(dst.info()) || !SkBlendMode_AppendStages(*blend)) { - return nullptr; + return earlyOut(); } bool is_opaque = paintColor->a() == 1.0f, @@ -113,7 +117,7 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, pipeline->append(SkRasterPipeline::seed_shader, &blitter->fCurrentY); if (!shader->appendStages(pipeline, dst.colorSpace(), &blitter->fArena, ctm, paint)) { - return nullptr; + return earlyOut(); } if (!is_opaque) { pipeline->append(SkRasterPipeline::scale_1_float, @@ -129,7 +133,7 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, if (colorFilter) { if (!colorFilter->appendStages(pipeline, dst.colorSpace(), &blitter->fArena, is_opaque)) { - return nullptr; + return earlyOut(); } is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag); } diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp index 9da760f843..9f97a7a74a 100644 --- a/src/core/SkShader.cpp +++ b/src/core/SkShader.cpp @@ -90,11 +90,23 @@ bool SkShader::asLuminanceColor(SkColor* colorPtr) const { return false; } -SkShader::Context* SkShader::makeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { +SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const { if (!this->computeTotalInverse(rec, nullptr)) { return nullptr; } - return this->onMakeContext(rec, alloc); + return this->onCreateContext(rec, storage); +} + +SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const { + return nullptr; +} + +size_t SkShader::contextSize(const ContextRec& rec) const { + return this->onContextSize(rec); +} + +size_t SkShader::onContextSize(const ContextRec&) const { + return 0; } SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) @@ -274,7 +286,16 @@ bool SkShader::onAppendStages(SkRasterPipeline* p, } ContextRec rec(*opaquePaint, ctm, localM, ContextRec::kPM4f_DstType, cs); - if (auto* ctx = this->makeContext(rec, alloc)) { + if (auto* ctx = this->createContext(rec, + alloc->makeArrayDefault<char>(this->contextSize(rec)))) { + struct ContextDestroyer { + ContextDestroyer(Context* ctx) : fContext(ctx) {} + ~ContextDestroyer() { fContext->~Context(); } + + Context* fContext; + }; + + alloc->make<ContextDestroyer>(ctx); p->append(SkRasterPipeline::shader_adapter, ctx); // Legacy shaders aren't aware of color spaces. We can pretty |