thread an SkArenaAlloc into shaders

We'll need something like this to extend the lifetime of our
SkBitmapController::State (and the bitmap and mipmaps it holds)
to match the lifetime of the blitter.  This is particularly
important particularly for kMedium where we're not sampling off
the original image.

Not sure which other effects will need this sort of thing, if any.
I think gradients would just write the colors directly into uniforms.

Change-Id: Idefe620f88113ed436e04a101195b27aec1230db
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/262522
Auto-Submit: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
This commit is contained in:
Mike Klein 2020-01-06 19:53:39 -06:00 committed by Skia Commit-Bot
parent c21316a73b
commit 3ab7128dfa
10 changed files with 29 additions and 25 deletions

View File

@ -28,7 +28,7 @@ struct Fade : public SkShaderBase {
bool onProgram(skvm::Builder* p,
const SkMatrix&, const SkMatrix*,
SkFilterQuality, SkColorSpace*,
skvm::Uniforms*,
skvm::Uniforms*, SkArenaAlloc*,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override {
// In this GM `y` will range over 0-50 and `x` over 50-100.

View File

@ -127,10 +127,12 @@ namespace {
x = p.add(x, p.splat(0.5f));
y = p.add(y, p.splat(0.5f));
skvm::F32 r,g,b,a;
SkSTArenaAlloc<2*sizeof(void*)> tmp;
if (shader->program(&p,
params.ctm, /*localM=*/nullptr,
params.quality, params.colorSpace.get(),
uniforms,
uniforms,&tmp,
x,y, &r,&g,&b,&a)) {
shaderHash = p.hash();
} else {
@ -159,7 +161,7 @@ namespace {
};
}
Builder(const Params& params, skvm::Uniforms* uniforms) {
Builder(const Params& params, skvm::Uniforms* uniforms, SkArenaAlloc* alloc) {
// First two arguments are always uniforms and the destination buffer.
uniforms->ptr = uniform();
skvm::Arg dst_ptr = arg(SkColorTypeBytesPerPixel(params.colorType));
@ -182,7 +184,7 @@ namespace {
SkAssertResult(as_SB(params.shader)->program(this,
params.ctm, /*localM=*/nullptr,
params.quality, params.colorSpace.get(),
uniforms,
uniforms, alloc,
x,y, &src.r, &src.g, &src.b, &src.a));
// We don't know if the src color is normalized (logical [0,1], premul [0,a]) or not.
bool src_is_normalized = false;
@ -425,7 +427,8 @@ namespace {
private:
SkPixmap fDevice;
skvm::Uniforms fUniforms;
skvm::Uniforms fUniforms; // Most data is copied directly into fUniforms,
SkArenaAlloc fAlloc{2*sizeof(void*)}; // but a few effects need to ref large content.
const Params fParams;
const Key fKey;
skvm::Program fBlitH,
@ -454,7 +457,7 @@ namespace {
// fUniforms should reuse the exact same memory, so this is very cheap.
SkDEBUGCODE(size_t prev = fUniforms.buf.size();)
fUniforms.buf.resize(kBlitterUniformsCount);
Builder builder{fParams.withCoverage(coverage), &fUniforms};
Builder builder{fParams.withCoverage(coverage), &fUniforms, &fAlloc};
SkASSERT(fUniforms.buf.size() == prev);
skvm::Program program = builder.done(debug_name(key).c_str());

View File

@ -63,11 +63,11 @@ bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const {
bool SkColorFilterShader::onProgram(skvm::Builder* p,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
// Run the shader.
if (!as_SB(fShader)->program(p, ctm,localM, quality,dstCS, uniforms, x,y, r,g,b,a)) {
if (!as_SB(fShader)->program(p, ctm,localM, quality,dstCS, uniforms,alloc, x,y, r,g,b,a)) {
return false;
}

View File

@ -29,7 +29,7 @@ private:
bool onProgram(skvm::Builder*,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc*,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;

View File

@ -108,7 +108,7 @@ static bool common_program(SkColor4f color, SkColorSpace* cs,
bool SkColorShader::onProgram(skvm::Builder* p,
const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
SkFilterQuality /*quality*/, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc*,
skvm::F32 /*x*/, skvm::F32 /*y*/,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
return common_program(SkColor4f::FromColor(fColor), sk_srgb_singleton(),
@ -117,7 +117,7 @@ bool SkColorShader::onProgram(skvm::Builder* p,
bool SkColor4Shader::onProgram(skvm::Builder* p,
const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
SkFilterQuality /*quality*/, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc*,
skvm::F32 /*x*/, skvm::F32 /*y*/,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
return common_program(fColor, fColorSpace.get(),

View File

@ -47,7 +47,7 @@ private:
bool onProgram(skvm::Builder*,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc*,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;
@ -74,7 +74,7 @@ private:
bool onProgram(skvm::Builder*,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc*,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;

View File

@ -645,7 +645,7 @@ SkStageUpdater* SkImageShader::onAppendUpdatableStages(const SkStageRec& rec) co
bool SkImageShader::onProgram(skvm::Builder* p,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
SkMatrix inv;
@ -653,14 +653,15 @@ bool SkImageShader::onProgram(skvm::Builder* p,
return false;
}
// TODO: need to extend lifetime of this once we start supporting kMedium_SkFilterQuality.
SkBitmapController::State state{as_IB(fImage.get()), inv, quality};
const SkPixmap& pm = state.pixmap();
if (!pm.addr()) {
// We use RequestBitmap() to make sure our SkBitmapController::State lives in the alloc.
// This lets the SkVMBlitter hang on to this state and keep our image alive.
auto state = SkBitmapController::RequestBitmap(as_IB(fImage.get()), inv, quality, alloc);
if (!state) {
return false;
}
inv = state.invMatrix();
quality = state.quality();
const SkPixmap& pm = state->pixmap();
inv = state->invMatrix();
quality = state->quality();
tweak_quality_and_inv_matrix(&quality, &inv);
if (quality != kNone_SkFilterQuality) { return false; }

View File

@ -50,7 +50,7 @@ private:
bool onProgram(skvm::Builder*,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc*,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;

View File

@ -200,7 +200,7 @@ bool SkShaderBase::onAppendStages(const SkStageRec& rec) const {
bool SkShaderBase::program(skvm::Builder* p,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
// Force opaque alpha for all opaque shaders.
@ -215,7 +215,7 @@ bool SkShaderBase::program(skvm::Builder* p,
// shader program hash and blitter Key. This makes it safe for us to use
// that bit to make decisions when constructing an SkVMBlitter, like doing
// SrcOver -> Src strength reduction.
if (this->onProgram(p, ctm,localM, quality,dstCS, uniforms, x,y, r,g,b,a)) {
if (this->onProgram(p, ctm,localM, quality,dstCS, uniforms,alloc, x,y, r,g,b,a)) {
if (this->isOpaque()) {
*a = p->splat(1.0f);
}

View File

@ -210,14 +210,14 @@ public:
bool program(skvm::Builder*,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const;
virtual bool onProgram(skvm::Builder*,
const SkMatrix& ctm, const SkMatrix* localM,
SkFilterQuality quality, SkColorSpace* dstCS,
skvm::Uniforms* uniforms,
skvm::Uniforms* uniforms, SkArenaAlloc* alloc,
skvm::F32 x, skvm::F32 y,
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
return false;