From: Robert Phillips Date: Tue, 7 Feb 2017 17:28:15 +0000 (+0000) Subject: Revert "Use SkArenaAlloc instead of SkSmallAllocator in the SkAutoBlitterChoose code." X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~55^2~466 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dd8b72ae7319598cfc1024901e860c52f06e6ae1;p=platform%2Fupstream%2FlibSkiaSharp.git 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 > Reviewed-by: Herb Derby > Commit-Queue: Herb Derby > 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 Reviewed-by: Robert Phillips --- diff --git a/bench/SkLinearBitmapPipelineBench.cpp b/bench/SkLinearBitmapPipelineBench.cpp index 0391798..4e892b6 100644 --- a/bench/SkLinearBitmapPipelineBench.cpp +++ b/bench/SkLinearBitmapPipelineBench.cpp @@ -7,8 +7,6 @@ #include #include "Benchmark.h" - -#include "SkArenaAlloc.h" #include "SkBitmapProcShader.h" #include "SkColor.h" #include "SkArenaAlloc.h" @@ -201,11 +199,12 @@ struct SkBitmapFPOrigShader : public CommonBitmapFPBenchmark { SkAutoTMalloc buffer4b(width*height); - SkArenaAlloc alloc{kSkBlitterContextSize * sizeof(uint32_t)}; + uint32_t storage[kSkBlitterContextSize]; const SkShader::ContextRec rec(fPaint, fM, nullptr, SkShader::ContextRec::kPMColor_DstType, nullptr); - SkShader::Context* ctx = fPaint.getShader()->makeContext(rec, &alloc); + SkASSERT(fPaint.getShader()->contextSize(rec) <= sizeof(storage)); + SkShader::Context* ctx = fPaint.getShader()->createContext(rec, storage); int count = 100; diff --git a/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp index 06589f2..401d3c3 100644 --- a/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp +++ b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.cpp @@ -5,10 +5,8 @@ * found in the LICENSE file. */ -#include "SkPerlinNoiseShader2.h" - -#include "SkArenaAlloc.h" #include "SkDither.h" +#include "SkPerlinNoiseShader2.h" #include "SkColorFilter.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" @@ -571,9 +569,13 @@ SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade( return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); } -SkShader::Context* SkPerlinNoiseShader2::onMakeContext(const ContextRec& rec, - SkArenaAlloc* alloc) const { - return alloc->make(*this, rec); +SkShader::Context* SkPerlinNoiseShader2::onCreateContext(const ContextRec& rec, + void* storage) const { + return new (storage) PerlinNoiseShaderContext(*this, rec); +} + +size_t SkPerlinNoiseShader2::onContextSize(const ContextRec&) const { + return sizeof(PerlinNoiseShaderContext); } SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext( diff --git a/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.h b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.h index 1f4839c..f1b94e1 100644 --- a/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.h +++ b/experimental/SkPerlinNoiseShader2/SkPerlinNoiseShader2.h @@ -114,7 +114,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* storage) const override; private: SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type, SkScalar baseFrequencyX, diff --git a/gm/SkLinearBitmapPipelineGM.cpp b/gm/SkLinearBitmapPipelineGM.cpp index 1bf4301..e881645 100644 --- a/gm/SkLinearBitmapPipelineGM.cpp +++ b/gm/SkLinearBitmapPipelineGM.cpp @@ -6,8 +6,6 @@ */ #include "gm.h" - -#include "SkArenaAlloc.h" #include "SkBlitter.h" #include "SkCanvas.h" #include "SkColor.h" @@ -61,7 +59,7 @@ static void draw_rect_orig(SkCanvas* canvas, const SkRect& r, SkColor c, const S sk_sp image(SkImage::MakeRasterCopy(SkPixmap(info, pmsrc.addr32(), pmsrc.rowBytes()))); SkPaint paint; - SkArenaAlloc alloc{kSkBlitterContextSize * sizeof(uint32_t)}; + int32_t storage[kSkBlitterContextSize]; sk_sp shader = image->makeShader(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); @@ -75,8 +73,9 @@ static void draw_rect_orig(SkCanvas* canvas, const SkRect& r, SkColor c, const S const SkShader::ContextRec rec(paint, *mat, nullptr, SkBlitter::PreferredShaderDest(pmsrc.info()), canvas->imageInfo().colorSpace()); + SkASSERT(paint.getShader()->contextSize(rec) <= sizeof(storage)); - SkShader::Context* ctx = paint.getShader()->makeContext(rec, &alloc); + SkShader::Context* ctx = paint.getShader()->createContext(rec, storage); for (int y = 0; y < ir.height(); y++) { ctx->shadeSpan(0, y, pmdst.writable_addr32(0, y), ir.width()); diff --git a/include/core/SkShader.h b/include/core/SkShader.h index 97cad6e..30a10dc 100644 --- a/include/core/SkShader.h +++ b/include/core/SkShader.h @@ -17,9 +17,9 @@ #include "SkPaint.h" #include "../gpu/GrColor.h" -class SkArenaAlloc; class SkColorFilter; class SkColorSpace; +class SkArenaAlloc; class SkImage; class SkPath; class SkPicture; @@ -229,11 +229,15 @@ public: }; /** - * Make a context using the memory provided by the arena. - * - * @return pointer to context or nullptr if can't be created + * Create the actual object that does the shading. + * Size of storage must be >= contextSize. */ - Context* makeContext(const ContextRec&, SkArenaAlloc*) const; + Context* createContext(const ContextRec&, void* storage) const; + + /** + * Return the size of a Context returned by createContext. + */ + size_t contextSize(const ContextRec&) const; #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP /** @@ -472,10 +476,16 @@ protected: bool computeTotalInverse(const ContextRec&, SkMatrix* totalInverse) const; /** - * Specialize creating a SkShader context using the supplied allocator. - * @return pointer to context owned by the arena allocator. + * Your subclass must also override contextSize() if it overrides onCreateContext(). + * Base class impl returns NULL. + */ + virtual Context* onCreateContext(const ContextRec&, void* storage) const; + + /** + * Override this if your subclass overrides createContext, to return the correct size of + * your subclass' context. */ - virtual Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const = 0; + virtual size_t onContextSize(const ContextRec&) const; virtual bool onAsLuminanceColor(SkColor*) const { return false; diff --git a/include/effects/SkPerlinNoiseShader.h b/include/effects/SkPerlinNoiseShader.h index 4e648f3..45d4367 100644 --- a/include/effects/SkPerlinNoiseShader.h +++ b/include/effects/SkPerlinNoiseShader.h @@ -92,7 +92,8 @@ public: protected: 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; private: SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, SkScalar baseFrequencyX, diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index fe43ba2..a409517 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 8c648b6..11deac4 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(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(shader, rec, info); + return new (storage) LinearPipelineContext(shader, rec, info); } else { - SkBitmapProcState* state = alloc->make(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(shader, rec, state); + return new (storage) BitmapProcShaderContext(shader, rec, state); } } diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h index 204b27d..4b7447e 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 a386904..d8e3dfd 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 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(*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(); + return allocator->createT(); } 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(); + return allocator->createT(); } 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(device, *paint); + return allocator->createT(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(); + 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(); + } + SkASSERT(shaderContext); + } else { + return allocator->createT(); } - 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(device, *paint, shaderContext); + blitter = allocator->createT(device, *paint, shaderContext); } else { - blitter = alloc->make(device, *paint); + blitter = allocator->createT(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( + blitter = allocator->createT( device, *paint, shaderContext); } else if (paint->getColor() == SK_ColorBLACK) { - blitter = alloc->make(device, *paint); + blitter = allocator->createT(device, *paint); } else if (paint->getAlpha() == 0xFF) { - blitter = alloc->make(device, *paint); + blitter = allocator->createT(device, *paint); } else { - blitter = alloc->make(device, *paint); + blitter = allocator->createT(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(); + blitter = allocator->createT(); } 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(innerBlitter, shaderContext); + blitter = allocator->createT(innerBlitter, shaderContext); } return blitter; } diff --git a/src/core/SkBlitter.h b/src/core/SkBlitter.h index 4d34ce3..cab2afc 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 61105ce..ce66580 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 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 SkBlitter* create(const SkPixmap& device, const SkPain bstate.fMode = paint.getBlendMode(); (void)shaderContext->chooseBlitProcs(device.info(), &bstate); - return alloc->make>(device, paint, bstate); + return allocator->createT>(device, paint, bstate); } else { SkColor color = paint.getColor(); if (0 == SkColorGetA(color)) { return nullptr; } - return alloc->make>(device, paint); + return allocator->createT>(device, paint); } } SkBlitter* SkBlitter_ARGB32_Create(const SkPixmap& device, const SkPaint& paint, SkShader::Context* shaderContext, - SkArenaAlloc* alloc) { - return create(device, paint, shaderContext, alloc); + SkTBlitterAllocator* allocator) { + return create(device, paint, shaderContext, allocator); } SkBlitter* SkBlitter_F16_Create(const SkPixmap& device, const SkPaint& paint, SkShader::Context* shaderContext, - SkArenaAlloc* alloc) { - return create(device, paint, shaderContext, alloc); + SkTBlitterAllocator* allocator) { + return create(device, paint, shaderContext, allocator); } diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp index e91e23f..afa8cac 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(device, paint, + blitter = allocator->createT(device, paint, shaderContext); } else { - blitter = alloc->make(device, paint, shaderContext); + blitter = allocator->createT(device, paint, shaderContext); } } else { // no shader, no xfermode, (and we always ignore colorfilter) SkColor color = paint.getColor(); if (0 == SkColorGetA(color)) { - blitter = alloc->make(); + blitter = allocator->createT(); #ifdef USE_BLACK_BLITTER } else if (SK_ColorBLACK == color) { - blitter = alloc->make(device, paint); + blitter = allocator->createT(device, paint); #endif } else if (0xFF == SkColorGetA(color)) { - blitter = alloc->make(device, paint); + blitter = allocator->createT(device, paint); } else { - blitter = alloc->make(device, paint); + blitter = allocator->createT(device, paint); } } diff --git a/src/core/SkColorFilterShader.cpp b/src/core/SkColorFilterShader.cpp index 5e96b24..4090a18 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(*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(fShader); diff --git a/src/core/SkColorFilterShader.h b/src/core/SkColorFilterShader.h index e697736..035acd8 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 shader, sk_sp 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 fShader; diff --git a/src/core/SkColorShader.cpp b/src/core/SkColorShader.cpp index 32d9b43..ed2a26b 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(*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(*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 b9db657..813fd3e 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 07bbd9a..5cbd23e 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::MakeComposeShader(sk_sp dst, sk_sp /////////////////////////////////////////////////////////////////////////////// +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 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(*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 be788af..7f9ff69 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 fShaderA; diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h index 63ddda9..62bf73e 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 2891c95..dd39d9e 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(*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(const_cast(&fShader)); TriColorShaderData* set = parent->takeSetupData(); diff --git a/src/core/SkEmptyShader.h b/src/core/SkEmptyShader.h index b2c9b76..528ceea 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 5bdaee5..4ed0057 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 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(*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 9d9e109..7a0a369 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 5c04240..0641abe 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 5ff7d82..5d49253 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(); + 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 1d1983c..d133738 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 73ef549..b4ed977 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(); + 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 4a8f743..e129559 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 2d3d241..3a9f9cf 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 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(*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 f2b07f2..5908369 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 221c09d..32ef08c 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 7102682..bdb6d06 100644 --- a/src/core/SkPictureShader.cpp +++ b/src/core/SkPictureShader.cpp @@ -243,6 +243,19 @@ sk_sp 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 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 bitmapShader(this->refBitmapShader(*rec.fMatrix, rec.fLocalMatrix, - rec.fDstColorSpace)); - if (!bitmapShader) { - return nullptr; - } - PictureShaderContext* ctx = - alloc->make(*this, rec, std::move(bitmapShader), alloc); +SkShader::Context* SkPictureShader::PictureShaderContext::Create(void* storage, + const SkPictureShader& shader, const ContextRec& rec, + sk_sp 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 bitmapShader, - SkArenaAlloc* alloc) + const SkPictureShader& shader, const ContextRec& rec, sk_sp 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 9807cd9..ff83fa3 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, TileMode, TileMode, const SkMatrix*, const SkRect*); @@ -52,14 +52,20 @@ private: class PictureShaderContext : public SkShader::Context { public: - PictureShaderContext( - const SkPictureShader&, const ContextRec&, sk_sp bitmapShader, SkArenaAlloc*); + static Context* Create(void* storage, const SkPictureShader&, const ContextRec&, + sk_sp 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 bitmapShader); + sk_sp fBitmapShader; SkShader::Context* fBitmapShaderContext; void* fBitmapShaderContextStorage; diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp index 1a00009..bb89f76 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( + SkTBlitterAllocator* alloc) { + auto blitter = alloc->createT( 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 9da760f..9f97a7a 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(this->contextSize(rec)))) { + struct ContextDestroyer { + ContextDestroyer(Context* ctx) : fContext(ctx) {} + ~ContextDestroyer() { fContext->~Context(); } + + Context* fContext; + }; + + alloc->make(ctx); p->append(SkRasterPipeline::shader_adapter, ctx); // Legacy shaders aren't aware of color spaces. We can pretty diff --git a/src/effects/SkGaussianEdgeShader.cpp b/src/effects/SkGaussianEdgeShader.cpp index 7bbbb79..be05e54 100644 --- a/src/effects/SkGaussianEdgeShader.cpp +++ b/src/effects/SkGaussianEdgeShader.cpp @@ -9,8 +9,6 @@ #include "SkReadBuffer.h" #include "SkWriteBuffer.h" -class SkArenaAlloc; - /** \class SkGaussianEdgeShaderImpl This subclass of shader applies a Gaussian to shadow edge @@ -36,9 +34,7 @@ public: protected: void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* storage) const override { - return nullptr; - } + private: friend class SkGaussianEdgeShader; diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp index 7582196..92f2946 100644 --- a/src/effects/SkPerlinNoiseShader.cpp +++ b/src/effects/SkPerlinNoiseShader.cpp @@ -6,8 +6,6 @@ */ #include "SkPerlinNoiseShader.h" - -#include "SkArenaAlloc.h" #include "SkColorFilter.h" #include "SkReadBuffer.h" #include "SkWriteBuffer.h" @@ -436,9 +434,13 @@ SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); } -SkShader::Context* SkPerlinNoiseShader::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const { - return alloc->make(*this, rec); +SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec, + void* storage) const { + return new (storage) PerlinNoiseShaderContext(*this, rec); +} + +size_t SkPerlinNoiseShader::onContextSize(const ContextRec&) const { + return sizeof(PerlinNoiseShaderContext); } SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index a9eef7d..75b6595 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -11,7 +11,6 @@ #include "SkGradientBitmapCache.h" #include "SkGradientShader.h" -#include "SkArenaAlloc.h" #include "SkAutoMalloc.h" #include "SkClampRange.h" #include "SkColorPriv.h" @@ -238,9 +237,10 @@ protected: int count); template - static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) { - auto* ctx = alloc->make(std::forward(args)...); + static Context* CheckedCreateContext(void* storage, Args&&... args) { + auto* ctx = new (storage) T(std::forward(args)...); if (!ctx->isValid()) { + ctx->~T(); return nullptr; } return ctx; diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index 73247cb..5a74bfd 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -74,12 +74,16 @@ void SkLinearGradient::flatten(SkWriteBuffer& buffer) const { buffer.writePoint(fEnd); } -SkShader::Context* SkLinearGradient::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ +size_t SkLinearGradient::onContextSize(const ContextRec& rec) const { + return use_4f_context(rec, fGradFlags) + ? sizeof(LinearGradient4fContext) + : sizeof(LinearGradientContext); +} + +SkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void* storage) const { return use_4f_context(rec, fGradFlags) - ? CheckedMakeContext(alloc, *this, rec) - : CheckedMakeContext< LinearGradientContext>(alloc, *this, rec); + ? CheckedCreateContext(storage, *this, rec) + : CheckedCreateContext< LinearGradientContext>(storage, *this, rec); } // For now, only a 2-stop raster pipeline specialization. diff --git a/src/effects/gradients/SkLinearGradient.h b/src/effects/gradients/SkLinearGradient.h index 4118dee..f13599d 100644 --- a/src/effects/gradients/SkLinearGradient.h +++ b/src/effects/gradients/SkLinearGradient.h @@ -66,7 +66,8 @@ public: protected: SkLinearGradient(SkReadBuffer& buffer); void flatten(SkWriteBuffer& buffer) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) 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; diff --git a/src/effects/gradients/SkRadialGradient.cpp b/src/effects/gradients/SkRadialGradient.cpp index 7e56863..a7dca76 100644 --- a/src/effects/gradients/SkRadialGradient.cpp +++ b/src/effects/gradients/SkRadialGradient.cpp @@ -39,10 +39,12 @@ SkRadialGradient::SkRadialGradient(const SkPoint& center, SkScalar radius, const , fRadius(radius) { } -SkShader::Context* SkRadialGradient::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ - return CheckedMakeContext(alloc, *this, rec); +size_t SkRadialGradient::onContextSize(const ContextRec&) const { + return sizeof(RadialGradientContext); +} + +SkShader::Context* SkRadialGradient::onCreateContext(const ContextRec& rec, void* storage) const { + return CheckedCreateContext(storage, *this, rec); } SkRadialGradient::RadialGradientContext::RadialGradientContext( diff --git a/src/effects/gradients/SkRadialGradient.h b/src/effects/gradients/SkRadialGradient.h index f92fbb3..0b23903 100644 --- a/src/effects/gradients/SkRadialGradient.h +++ b/src/effects/gradients/SkRadialGradient.h @@ -35,7 +35,8 @@ public: protected: SkRadialGradient(SkReadBuffer& buffer); void flatten(SkWriteBuffer& buffer) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; private: const SkPoint fCenter; diff --git a/src/effects/gradients/SkSweepGradient.cpp b/src/effects/gradients/SkSweepGradient.cpp index 928de4c..27d5dbe 100644 --- a/src/effects/gradients/SkSweepGradient.cpp +++ b/src/effects/gradients/SkSweepGradient.cpp @@ -45,10 +45,12 @@ void SkSweepGradient::flatten(SkWriteBuffer& buffer) const { buffer.writePoint(fCenter); } -SkShader::Context* SkSweepGradient::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const -{ - return CheckedMakeContext(alloc, *this, rec); +size_t SkSweepGradient::onContextSize(const ContextRec&) const { + return sizeof(SweepGradientContext); +} + +SkShader::Context* SkSweepGradient::onCreateContext(const ContextRec& rec, void* storage) const { + return CheckedCreateContext(storage, *this, rec); } SkSweepGradient::SweepGradientContext::SweepGradientContext( diff --git a/src/effects/gradients/SkSweepGradient.h b/src/effects/gradients/SkSweepGradient.h index 30ebb1a..f132118 100644 --- a/src/effects/gradients/SkSweepGradient.h +++ b/src/effects/gradients/SkSweepGradient.h @@ -35,7 +35,8 @@ public: protected: void flatten(SkWriteBuffer& buffer) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; private: const SkPoint fCenter; diff --git a/src/effects/gradients/SkTwoPointConicalGradient.cpp b/src/effects/gradients/SkTwoPointConicalGradient.cpp index a9740aa..599fd4c 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient.cpp +++ b/src/effects/gradients/SkTwoPointConicalGradient.cpp @@ -210,9 +210,13 @@ bool SkTwoPointConicalGradient::isOpaque() const { return false; } -SkShader::Context* SkTwoPointConicalGradient::onMakeContext( - const ContextRec& rec, SkArenaAlloc* alloc) const { - return CheckedMakeContext(alloc, *this, rec); +size_t SkTwoPointConicalGradient::onContextSize(const ContextRec&) const { + return sizeof(TwoPointConicalGradientContext); +} + +SkShader::Context* SkTwoPointConicalGradient::onCreateContext(const ContextRec& rec, + void* storage) const { + return CheckedCreateContext(storage, *this, rec); } SkTwoPointConicalGradient::TwoPointConicalGradientContext::TwoPointConicalGradientContext( diff --git a/src/effects/gradients/SkTwoPointConicalGradient.h b/src/effects/gradients/SkTwoPointConicalGradient.h index e509f92..d16e4bc 100644 --- a/src/effects/gradients/SkTwoPointConicalGradient.h +++ b/src/effects/gradients/SkTwoPointConicalGradient.h @@ -75,7 +75,8 @@ public: protected: SkTwoPointConicalGradient(SkReadBuffer& buffer); void flatten(SkWriteBuffer& buffer) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; private: SkPoint fCenter1; diff --git a/src/image/SkImageShader.cpp b/src/image/SkImageShader.cpp index 64a09dd..90ae830 100644 --- a/src/image/SkImageShader.cpp +++ b/src/image/SkImageShader.cpp @@ -48,10 +48,14 @@ bool SkImageShader::isOpaque() const { return fImage->isOpaque(); } -SkShader::Context* SkImageShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const { +size_t SkImageShader::onContextSize(const ContextRec& rec) const { + return SkBitmapProcLegacyShader::ContextSize(rec, as_IB(fImage)->onImageInfo()); +} + +SkShader::Context* SkImageShader::onCreateContext(const ContextRec& rec, void* storage) const { return SkBitmapProcLegacyShader::MakeContext(*this, fTileModeX, fTileModeY, SkBitmapProvider(fImage.get(), rec.fDstColorSpace), - rec, alloc); + rec, storage); } SkImage* SkImageShader::onIsAImage(SkMatrix* texM, TileMode xy[]) const { diff --git a/src/image/SkImageShader.h b/src/image/SkImageShader.h index ef5e87c..d065a1e 100644 --- a/src/image/SkImageShader.h +++ b/src/image/SkImageShader.h @@ -30,7 +30,8 @@ public: protected: void flatten(SkWriteBuffer&) const override; - Context* onMakeContext(const ContextRec&, SkArenaAlloc* storage) const override; + size_t onContextSize(const ContextRec&) const override; + Context* onCreateContext(const ContextRec&, void* storage) const override; #ifdef SK_SUPPORT_LEGACY_SHADER_ISABITMAP bool onIsABitmap(SkBitmap*, SkMatrix*, TileMode*) const override; #endif