pass more information to shaders
If we're going to write an image shader, we're going to need to know the matrix and some bits of the paint. Instead of all possible information, I decided to pass just what the image shader needs for now, and will pass along more as I go. I've added a stub implementation of SkImageFilter as a way to make sure I'm threading everything it'll need through. Change-Id: I98de1724056dbc0902a34fc31da8ec6bdf38dc34 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/261801 Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
parent
107c66669d
commit
4f275cfe0e
@ -21,6 +21,8 @@
|
||||
// Just a tiny example that the (x,y) coordinate parameters are vaguely working.
|
||||
// In this case we'll fade the red channel over its span vertically using `y`,
|
||||
// and green horizontally using `x`.
|
||||
//
|
||||
// TODO: this doesn't really need to wrap another shader.
|
||||
struct Fade : public SkShaderBase {
|
||||
explicit Fade(sk_sp<SkShader> shader) : fShader(std::move(shader)) {}
|
||||
|
||||
@ -29,11 +31,14 @@ struct Fade : public SkShaderBase {
|
||||
bool isOpaque() const override { return fShader->isOpaque(); }
|
||||
|
||||
bool onProgram(skvm::Builder* p,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override {
|
||||
if (as_SB(fShader)->program(p, dstCS,
|
||||
if (as_SB(fShader)->program(p,
|
||||
ctm, localM,
|
||||
quality, dstCS,
|
||||
uniforms,
|
||||
x,y, r,g,b,a)) {
|
||||
// In this GM `y` will range over 0-50 and `x` over 50-100.
|
||||
|
@ -36,6 +36,8 @@ namespace {
|
||||
SkAlphaType alphaType;
|
||||
SkBlendMode blendMode;
|
||||
Coverage coverage;
|
||||
SkFilterQuality quality;
|
||||
SkMatrix ctm;
|
||||
|
||||
Params withCoverage(Coverage c) const {
|
||||
Params p = *this;
|
||||
@ -52,6 +54,9 @@ namespace {
|
||||
alphaType,
|
||||
blendMode,
|
||||
coverage;
|
||||
// Params::quality and Params::ctm are only passed to shader->program(),
|
||||
// not used here by the blitter itself. No need to include them in the key;
|
||||
// they'll be folded into the shader key if used.
|
||||
|
||||
bool operator==(const Key& that) const {
|
||||
return this->colorSpace == that.colorSpace
|
||||
@ -148,7 +153,8 @@ namespace {
|
||||
offsetof(BlitterUniforms, y)));
|
||||
skvm::F32 r,g,b,a;
|
||||
if (shader->program(&p,
|
||||
params.colorSpace.get(),
|
||||
params.ctm, /*localM=*/nullptr,
|
||||
params.quality, params.colorSpace.get(),
|
||||
uniforms,
|
||||
x,y, &r,&g,&b,&a)) {
|
||||
shaderHash = p.hash();
|
||||
@ -200,7 +206,8 @@ namespace {
|
||||
y = to_f32(uniform32(uniforms->ptr,
|
||||
offsetof(BlitterUniforms, y)));
|
||||
SkAssertResult(as_SB(params.shader)->program(this,
|
||||
params.colorSpace.get(),
|
||||
params.ctm, /*localM=*/nullptr,
|
||||
params.quality, params.colorSpace.get(),
|
||||
uniforms,
|
||||
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.
|
||||
@ -346,6 +353,7 @@ namespace {
|
||||
};
|
||||
|
||||
// Scale the output of another shader by alpha.
|
||||
// TODO: this would make more sense as a color filter
|
||||
struct AlphaShader : public SkShaderBase {
|
||||
AlphaShader(sk_sp<SkShader> shader, float alpha)
|
||||
: fShader(std::move(shader))
|
||||
@ -355,11 +363,14 @@ namespace {
|
||||
float fAlpha;
|
||||
|
||||
bool onProgram(skvm::Builder* p,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override {
|
||||
if (as_SB(fShader)->program(p, dstCS,
|
||||
if (as_SB(fShader)->program(p,
|
||||
ctm, localM,
|
||||
quality, dstCS,
|
||||
uniforms,
|
||||
x,y, r,g,b,a)) {
|
||||
skvm::F32 A = p->uniformF(uniforms->pushF(fAlpha));
|
||||
@ -377,7 +388,9 @@ namespace {
|
||||
const char* getTypeName() const override { return "AlphaShader"; }
|
||||
};
|
||||
|
||||
static Params effective_params(const SkPixmap& device, const SkPaint& paint) {
|
||||
static Params effective_params(const SkPixmap& device,
|
||||
const SkPaint& paint,
|
||||
const SkMatrix& ctm) {
|
||||
// Color filters have been handled for us by SkBlitter::Choose().
|
||||
SkASSERT(!paint.getColorFilter());
|
||||
|
||||
@ -415,15 +428,17 @@ namespace {
|
||||
device.alphaType(),
|
||||
blendMode,
|
||||
Coverage::Full, // Placeholder... withCoverage() will change as needed.
|
||||
paint.getFilterQuality(),
|
||||
ctm,
|
||||
};
|
||||
}
|
||||
|
||||
class Blitter final : public SkBlitter {
|
||||
public:
|
||||
Blitter(const SkPixmap& device, const SkPaint& paint, bool* ok)
|
||||
Blitter(const SkPixmap& device, const SkPaint& paint, const SkMatrix& ctm, bool* ok)
|
||||
: fDevice(device)
|
||||
, fUniforms(kBlitterUniformsCount)
|
||||
, fParams(effective_params(device, paint))
|
||||
, fParams(effective_params(device, paint, ctm))
|
||||
, fKey(Builder::CacheKey(fParams, &fUniforms, ok))
|
||||
{}
|
||||
|
||||
@ -676,6 +691,6 @@ SkBlitter* SkCreateSkVMBlitter(const SkPixmap& device,
|
||||
const SkMatrix& ctm,
|
||||
SkArenaAlloc* alloc) {
|
||||
bool ok = true;
|
||||
auto blitter = alloc->make<Blitter>(device, paint, &ok);
|
||||
auto blitter = alloc->make<Blitter>(device, paint, ctm, &ok);
|
||||
return ok ? blitter : nullptr;
|
||||
}
|
||||
|
@ -61,12 +61,13 @@ bool SkColorFilterShader::onAppendStages(const SkStageRec& rec) const {
|
||||
}
|
||||
|
||||
bool SkColorFilterShader::onProgram(skvm::Builder* p,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
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, dstCS, uniforms, x,y, r,g,b,a)) {
|
||||
if (!as_SB(fShader)->program(p, ctm,localM, quality,dstCS, uniforms, x,y, r,g,b,a)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,8 @@ private:
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
bool onProgram(skvm::Builder*,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;
|
||||
|
@ -106,7 +106,8 @@ static bool common_program(SkColor4f color, SkColorSpace* cs,
|
||||
}
|
||||
|
||||
bool SkColorShader::onProgram(skvm::Builder* p,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
|
||||
SkFilterQuality /*quality*/, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 /*x*/, skvm::F32 /*y*/,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
|
||||
@ -114,7 +115,8 @@ bool SkColorShader::onProgram(skvm::Builder* p,
|
||||
p, dstCS, uniforms, r,g,b,a);
|
||||
}
|
||||
bool SkColor4Shader::onProgram(skvm::Builder* p,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& /*ctm*/, const SkMatrix* /*localM*/,
|
||||
SkFilterQuality /*quality*/, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 /*x*/, skvm::F32 /*y*/,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
|
||||
|
@ -45,7 +45,8 @@ private:
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
bool onProgram(skvm::Builder*,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;
|
||||
@ -71,7 +72,8 @@ private:
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
bool onProgram(skvm::Builder*,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;
|
||||
|
@ -636,3 +636,25 @@ SkStageUpdater* SkImageShader::onAppendUpdatableStages(const SkStageRec& rec) co
|
||||
return this->doStages(rec, updater) ? updater : nullptr;
|
||||
}
|
||||
|
||||
bool SkImageShader::onProgram(skvm::Builder* p,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
|
||||
SkMatrix inv;
|
||||
if (!this->computeTotalInverse(ctm, localM, &inv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkBitmapController::State state{as_IB(fImage.get()), inv, quality};
|
||||
const SkPixmap& pm = state.pixmap();
|
||||
if (!pm.addr()) {
|
||||
return false;
|
||||
}
|
||||
inv = state.invMatrix();
|
||||
quality = state.quality();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,13 @@ private:
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
SkStageUpdater* onAppendUpdatableStages(const SkStageRec&) const override;
|
||||
|
||||
bool onProgram(skvm::Builder*,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const override;
|
||||
|
||||
bool doStages(const SkStageRec&, SkImageStageUpdater* = nullptr) const;
|
||||
|
||||
sk_sp<SkImage> fImage;
|
||||
|
@ -198,7 +198,8 @@ bool SkShaderBase::onAppendStages(const SkStageRec& rec) const {
|
||||
}
|
||||
|
||||
bool SkShaderBase::program(skvm::Builder* p,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
|
||||
@ -214,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, dstCS, uniforms, x,y, r,g,b,a)) {
|
||||
if (this->onProgram(p, ctm,localM, quality,dstCS, uniforms, x,y, r,g,b,a)) {
|
||||
if (this->isOpaque()) {
|
||||
*a = p->splat(1.0f);
|
||||
}
|
||||
|
@ -208,13 +208,15 @@ public:
|
||||
}
|
||||
|
||||
bool program(skvm::Builder*,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const;
|
||||
|
||||
virtual bool onProgram(skvm::Builder*,
|
||||
SkColorSpace* dstCS,
|
||||
const SkMatrix& ctm, const SkMatrix* localM,
|
||||
SkFilterQuality quality, SkColorSpace* dstCS,
|
||||
skvm::Uniforms* uniforms,
|
||||
skvm::F32 x, skvm::F32 y,
|
||||
skvm::F32* r, skvm::F32* g, skvm::F32* b, skvm::F32* a) const {
|
||||
|
Loading…
Reference in New Issue
Block a user