remove double compose: lerp and mode
Bug: skia:8937 Change-Id: I5b890c03b0451afe4cbeb6a264798ebbb09b9888 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/205346 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com> Auto-Submit: Mike Reed <reed@google.com>
This commit is contained in:
parent
3bdb69c55f
commit
9b2c4e94e2
@ -259,7 +259,8 @@ template <typename Maker> void do_mixershader(SkCanvas* canvas, Maker&& maker) {
|
||||
|
||||
DEF_SIMPLE_GM(mixershader, canvas, 800, 700) {
|
||||
do_mixershader(canvas, [](sk_sp<SkShader> a, sk_sp<SkShader> b, SkBlendMode mode, float t) {
|
||||
return SkShader::MakeCompose(a, b, mode, t);
|
||||
auto sh = SkShader::MakeBlend(mode, a, b);
|
||||
return SkShader::MakeLerp(t, a, sh);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -297,7 +297,7 @@ static void draw_composed(SkCanvas* canvas, sk_sp<SkShader> src, sk_sp<SkShader>
|
||||
SkBlendMode mode, SkAlpha alpha) {
|
||||
SkPaint p;
|
||||
p.setAlpha(alpha);
|
||||
p.setShader(SkShader::MakeCompose(dst, src, mode));
|
||||
p.setShader(SkShader::MakeBlend(mode, dst, src));
|
||||
canvas->drawRect(SkRect::MakeWH(gCellSize, gCellSize), p);
|
||||
}
|
||||
|
||||
|
@ -49,17 +49,17 @@ DEF_SIMPLE_GM(localmatrixshader_nested, canvas, 450, 1200) {
|
||||
|
||||
// SkLocalMatrixShader(SkComposeShader(SkImageShader(inner)), outer)
|
||||
[](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
|
||||
return SkShader::MakeCompose(SkShader::MakeColorShader(SK_ColorTRANSPARENT),
|
||||
img->makeShader(&inner),
|
||||
SkBlendMode::kSrcOver)
|
||||
return SkShader::MakeBlend(SkBlendMode::kSrcOver,
|
||||
SkShader::MakeColorShader(SK_ColorTRANSPARENT),
|
||||
img->makeShader(&inner))
|
||||
->makeWithLocalMatrix(outer);
|
||||
},
|
||||
|
||||
// SkLocalMatrixShader(SkComposeShader(SkLocalMatrixShader(SkImageShader(I), inner)), outer)
|
||||
[](const sk_sp<SkImage>& img, const SkMatrix& inner, const SkMatrix& outer) {
|
||||
return SkShader::MakeCompose(SkShader::MakeColorShader(SK_ColorTRANSPARENT),
|
||||
img->makeShader()->makeWithLocalMatrix(inner),
|
||||
SkBlendMode::kSrcOver)
|
||||
return SkShader::MakeBlend(SkBlendMode::kSrcOver,
|
||||
SkShader::MakeColorShader(SK_ColorTRANSPARENT),
|
||||
img->makeShader()->makeWithLocalMatrix(inner))
|
||||
->makeWithLocalMatrix(outer);
|
||||
},
|
||||
};
|
||||
|
@ -185,38 +185,25 @@ public:
|
||||
*/
|
||||
static sk_sp<SkShader> MakeColorShader(const SkColor4f&, sk_sp<SkColorSpace>);
|
||||
|
||||
/**
|
||||
* Compose two shaders together, using two operators: mode and lerp. The resulting colors
|
||||
* are computed by first combining the src and dst shaders using mode, and then linearly
|
||||
* interpolating between the dst and result colors using lerp.
|
||||
*
|
||||
* result = dst * (1 - lerp) + (src (mode) dst) * lerp
|
||||
*
|
||||
* If either shader is nullptr, then this returns nullptr.
|
||||
* If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1].
|
||||
*/
|
||||
static sk_sp<SkShader> MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src,
|
||||
SkBlendMode mode, float lerp = 1);
|
||||
static sk_sp<SkShader> MakeBlend(SkBlendMode mode, sk_sp<SkShader> dst, sk_sp<SkShader> src);
|
||||
|
||||
/*
|
||||
* DEPRECATED: call MakeCompose.
|
||||
* DEPRECATED: call MakeBlend.
|
||||
*/
|
||||
static sk_sp<SkShader> MakeComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src,
|
||||
SkBlendMode mode) {
|
||||
return MakeCompose(std::move(dst), std::move(src), mode, 1);
|
||||
return MakeBlend(mode, std::move(dst), std::move(src));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compose two shaders together using a weighted average.
|
||||
*
|
||||
* result = dst * (1 - lerp) + src * lerp
|
||||
* result = dst * (1 - weight) + src * weight
|
||||
*
|
||||
* If either shader is nullptr, then this returns nullptr.
|
||||
* If lerp is NaN then this returns nullptr, otherwise lerp is clamped to [0..1].
|
||||
* If weight is NaN then this returns nullptr, otherwise lerp is clamped to [0..1].
|
||||
*/
|
||||
static sk_sp<SkShader> MakeLerp(sk_sp<SkShader> dst, sk_sp<SkShader> src, float lerp) {
|
||||
return MakeCompose(std::move(dst), std::move(src), SkBlendMode::kSrc, lerp);
|
||||
}
|
||||
static sk_sp<SkShader> MakeLerp(float weight, sk_sp<SkShader> dst, sk_sp<SkShader> src);
|
||||
|
||||
static sk_sp<SkShader> MakeMixer(sk_sp<SkShader> dst, sk_sp<SkShader> src, sk_sp<SkMixer>);
|
||||
|
||||
|
@ -204,7 +204,7 @@ void SkDraw::drawVertices(SkVertices::VertexMode vmode, int vertexCount,
|
||||
|
||||
constexpr size_t kDefVertexCount = 16;
|
||||
constexpr size_t kOuterSize = sizeof(SkTriColorShader) +
|
||||
sizeof(SkComposeShader) +
|
||||
sizeof(SkShader_Blend) +
|
||||
(2 * sizeof(SkPoint) + sizeof(SkColor4f)) * kDefVertexCount;
|
||||
SkSTArenaAlloc<kOuterSize> outerAlloc;
|
||||
|
||||
@ -277,8 +277,8 @@ void SkDraw::drawVertices(SkVertices::VertexMode vmode, int vertexCount,
|
||||
vertexCount));
|
||||
matrix43 = triShader->getMatrix43();
|
||||
if (shader) {
|
||||
shader = outerAlloc.make<SkComposeShader>(sk_ref_sp(triShader), sk_ref_sp(shader),
|
||||
bmode, 1);
|
||||
shader = outerAlloc.make<SkShader_Blend>(bmode,
|
||||
sk_ref_sp(triShader), sk_ref_sp(shader));
|
||||
} else {
|
||||
shader = triShader;
|
||||
}
|
||||
|
@ -80,7 +80,8 @@
|
||||
SK_REGISTER_FLATTENABLE(SkColor4Shader);
|
||||
SK_REGISTER_FLATTENABLE(SkColorFilterShader);
|
||||
SK_REGISTER_FLATTENABLE(SkColorShader);
|
||||
SK_REGISTER_FLATTENABLE(SkComposeShader);
|
||||
SK_REGISTER_FLATTENABLE(SkShader_Blend);
|
||||
SK_REGISTER_FLATTENABLE(SkShader_Lerp);
|
||||
SK_REGISTER_FLATTENABLE(SkEmptyShader);
|
||||
SK_REGISTER_FLATTENABLE(SkLocalMatrixShader);
|
||||
SK_REGISTER_FLATTENABLE(SkPictureShader);
|
||||
|
@ -16,74 +16,114 @@
|
||||
#include "SkWriteBuffer.h"
|
||||
#include "SkString.h"
|
||||
|
||||
sk_sp<SkShader> SkShader::MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode mode,
|
||||
float lerpT) {
|
||||
if (!src || !dst || SkScalarIsNaN(lerpT)) {
|
||||
sk_sp<SkShader> SkShader::MakeBlend(SkBlendMode mode, sk_sp<SkShader> dst, sk_sp<SkShader> src) {
|
||||
switch (mode) {
|
||||
case SkBlendMode::kClear: return MakeColorShader(0);
|
||||
case SkBlendMode::kDst: return dst;
|
||||
case SkBlendMode::kSrc: return src;
|
||||
default: break;
|
||||
}
|
||||
return sk_sp<SkShader>(new SkShader_Blend(mode, std::move(dst), std::move(src)));
|
||||
}
|
||||
|
||||
sk_sp<SkShader> SkShader::MakeLerp(float weight, sk_sp<SkShader> dst, sk_sp<SkShader> src) {
|
||||
if (SkScalarIsNaN(weight)) {
|
||||
return nullptr;
|
||||
}
|
||||
lerpT = SkScalarPin(lerpT, 0, 1);
|
||||
|
||||
if (lerpT == 0) {
|
||||
if (dst == src) {
|
||||
return dst;
|
||||
} else if (lerpT == 1) {
|
||||
if (mode == SkBlendMode::kSrc) {
|
||||
return src;
|
||||
}
|
||||
if (mode == SkBlendMode::kDst) {
|
||||
return dst;
|
||||
}
|
||||
}
|
||||
return sk_sp<SkShader>(new SkComposeShader(std::move(dst), std::move(src), mode, lerpT));
|
||||
if (weight <= 0) {
|
||||
return dst;
|
||||
} else if (weight >= 1) {
|
||||
return src;
|
||||
}
|
||||
return sk_sp<SkShader>(new SkShader_Lerp(weight, std::move(dst), std::move(src)));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sk_sp<SkFlattenable> SkComposeShader::CreateProc(SkReadBuffer& buffer) {
|
||||
static bool append_shader_or_paint(const SkStageRec& rec, SkShader* shader) {
|
||||
if (shader) {
|
||||
if (!as_SB(shader)->appendStages(rec)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
rec.fPipeline->append_constant_color(rec.fAlloc, rec.fPaint.getColor4f().premul().vec());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the output of e0, and leaves the output of e1 in r,g,b,a
|
||||
static float* append_two_shaders(const SkStageRec& rec, SkShader* s0, SkShader* s1) {
|
||||
struct Storage {
|
||||
float fRes0[4 * SkRasterPipeline_kMaxStride];
|
||||
};
|
||||
auto storage = rec.fAlloc->make<Storage>();
|
||||
|
||||
if (!append_shader_or_paint(rec, s0)) {
|
||||
return nullptr;
|
||||
}
|
||||
rec.fPipeline->append(SkRasterPipeline::store_src, storage->fRes0);
|
||||
|
||||
if (!append_shader_or_paint(rec, s1)) {
|
||||
return nullptr;
|
||||
}
|
||||
return storage->fRes0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sk_sp<SkFlattenable> SkShader_Blend::CreateProc(SkReadBuffer& buffer) {
|
||||
sk_sp<SkShader> dst(buffer.readShader());
|
||||
sk_sp<SkShader> src(buffer.readShader());
|
||||
unsigned mode = buffer.read32();
|
||||
float lerp = buffer.readScalar();
|
||||
|
||||
// check for valid mode before we cast to the enum type
|
||||
if (!buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode)) {
|
||||
return nullptr;
|
||||
}
|
||||
return MakeCompose(std::move(dst), std::move(src), static_cast<SkBlendMode>(mode), lerp);
|
||||
return MakeBlend(static_cast<SkBlendMode>(mode), std::move(dst), std::move(src));
|
||||
}
|
||||
|
||||
void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
|
||||
void SkShader_Blend::flatten(SkWriteBuffer& buffer) const {
|
||||
buffer.writeFlattenable(fDst.get());
|
||||
buffer.writeFlattenable(fSrc.get());
|
||||
buffer.write32((int)fMode);
|
||||
buffer.writeScalar(fLerpT);
|
||||
}
|
||||
|
||||
bool SkComposeShader::onAppendStages(const SkStageRec& rec) const {
|
||||
struct Storage {
|
||||
float fRGBA[4 * SkRasterPipeline_kMaxStride];
|
||||
float fAlpha;
|
||||
};
|
||||
auto storage = rec.fAlloc->make<Storage>();
|
||||
|
||||
if (!as_SB(fDst)->appendStages(rec)) {
|
||||
bool SkShader_Blend::onAppendStages(const SkStageRec& rec) const {
|
||||
float* res0 = append_two_shaders(rec, fDst.get(), fSrc.get());
|
||||
if (!res0) {
|
||||
return false;
|
||||
}
|
||||
// This outputs r,g,b,a, which we'll need later when we apply the mode, so we save it off now
|
||||
rec.fPipeline->append(SkRasterPipeline::store_src, storage->fRGBA);
|
||||
|
||||
if (!as_SB(fSrc)->appendStages(rec)) {
|
||||
rec.fPipeline->append(SkRasterPipeline::load_dst, res0);
|
||||
SkBlendMode_AppendStages(fMode, rec.fPipeline);
|
||||
return true;
|
||||
}
|
||||
|
||||
sk_sp<SkFlattenable> SkShader_Lerp::CreateProc(SkReadBuffer& buffer) {
|
||||
sk_sp<SkShader> dst(buffer.readShader());
|
||||
sk_sp<SkShader> src(buffer.readShader());
|
||||
float t = buffer.readScalar();
|
||||
return buffer.isValid() ? MakeLerp(t, std::move(dst), std::move(src)) : nullptr;
|
||||
}
|
||||
|
||||
void SkShader_Lerp::flatten(SkWriteBuffer& buffer) const {
|
||||
buffer.writeFlattenable(fDst.get());
|
||||
buffer.writeFlattenable(fSrc.get());
|
||||
buffer.writeScalar(fWeight);
|
||||
}
|
||||
|
||||
bool SkShader_Lerp::onAppendStages(const SkStageRec& rec) const {
|
||||
float* res0 = append_two_shaders(rec, fDst.get(), fSrc.get());
|
||||
if (!res0) {
|
||||
return false;
|
||||
}
|
||||
// r,g,b,a now have the right input for the next step (lerp and/or mode), but we need to
|
||||
// reload dr,dg,db,da from memory, since we stashed that from our fDst invocation earlier.
|
||||
rec.fPipeline->append(SkRasterPipeline::load_dst, storage->fRGBA);
|
||||
|
||||
if (!this->isJustLerp()) {
|
||||
SkBlendMode_AppendStages(fMode, rec.fPipeline);
|
||||
}
|
||||
if (!this->isJustMode()) {
|
||||
rec.fPipeline->append(SkRasterPipeline::lerp_1_float, &fLerpT);
|
||||
}
|
||||
rec.fPipeline->append(SkRasterPipeline::load_dst, res0);
|
||||
rec.fPipeline->append(SkRasterPipeline::lerp_1_float, &fWeight);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -94,16 +134,8 @@ bool SkComposeShader::onAppendStages(const SkStageRec& rec) const {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> SkComposeShader::asFragmentProcessor(
|
||||
std::unique_ptr<GrFragmentProcessor> SkShader_Blend::asFragmentProcessor(
|
||||
const GrFPArgs& args) const {
|
||||
if (this->isJustMode()) {
|
||||
SkASSERT(fMode != SkBlendMode::kSrc && fMode != SkBlendMode::kDst); // caught in factory
|
||||
if (fMode == SkBlendMode::kClear) {
|
||||
return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
|
||||
GrConstColorProcessor::InputMode::kIgnore);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> fpA(as_SB(fDst)->asFragmentProcessor(args));
|
||||
if (!fpA) {
|
||||
return nullptr;
|
||||
@ -112,8 +144,19 @@ std::unique_ptr<GrFragmentProcessor> SkComposeShader::asFragmentProcessor(
|
||||
if (!fpB) {
|
||||
return nullptr;
|
||||
}
|
||||
// TODO: account for fLerpT when it is < 1
|
||||
return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB),
|
||||
std::move(fpA), fMode);
|
||||
}
|
||||
|
||||
std::unique_ptr<GrFragmentProcessor> SkShader_Lerp::asFragmentProcessor(const GrFPArgs& args) const {
|
||||
std::unique_ptr<GrFragmentProcessor> fpA(as_SB(fDst)->asFragmentProcessor(args));
|
||||
if (!fpA) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> fpB(as_SB(fSrc)->asFragmentProcessor(args));
|
||||
if (!fpB) {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr; // todo
|
||||
}
|
||||
#endif
|
||||
|
@ -11,41 +11,58 @@
|
||||
#include "SkShaderBase.h"
|
||||
#include "SkBlendMode.h"
|
||||
|
||||
class SkComposeShader final : public SkShaderBase {
|
||||
class SkShader_Blend final : public SkShaderBase {
|
||||
public:
|
||||
SkComposeShader(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode mode, float lerpT)
|
||||
SkShader_Blend(SkBlendMode mode, sk_sp<SkShader> dst, sk_sp<SkShader> src)
|
||||
: fDst(std::move(dst))
|
||||
, fSrc(std::move(src))
|
||||
, fLerpT(lerpT)
|
||||
, fMode(mode)
|
||||
{}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
SkShader_Blend(SkReadBuffer&);
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkShader_Blend)
|
||||
|
||||
sk_sp<SkShader> fDst;
|
||||
sk_sp<SkShader> fSrc;
|
||||
const SkBlendMode fMode;
|
||||
|
||||
typedef SkShaderBase INHERITED;
|
||||
};
|
||||
|
||||
class SkShader_Lerp final : public SkShaderBase {
|
||||
public:
|
||||
SkShader_Lerp(float weight, sk_sp<SkShader> dst, sk_sp<SkShader> src)
|
||||
: fDst(std::move(dst))
|
||||
, fSrc(std::move(src))
|
||||
, fWeight(weight)
|
||||
{
|
||||
SkASSERT(lerpT >= 0 && lerpT <= 1);
|
||||
SkASSERT(weight >= 0 && weight <= 1);
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
std::unique_ptr<GrFragmentProcessor> asFragmentProcessor(const GrFPArgs&) const override;
|
||||
#endif
|
||||
|
||||
#ifdef SK_DEBUGx
|
||||
SkShader* getShaderA() { return fShaderA.get(); }
|
||||
SkShader* getShaderB() { return fShaderB.get(); }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
SkComposeShader(SkReadBuffer&);
|
||||
SkShader_Lerp(SkReadBuffer&);
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
bool onAppendStages(const SkStageRec&) const override;
|
||||
|
||||
private:
|
||||
SK_FLATTENABLE_HOOKS(SkComposeShader)
|
||||
SK_FLATTENABLE_HOOKS(SkShader_Lerp)
|
||||
|
||||
sk_sp<SkShader> fDst;
|
||||
sk_sp<SkShader> fSrc;
|
||||
const float fLerpT;
|
||||
const SkBlendMode fMode;
|
||||
|
||||
bool isJustMode() const { return fLerpT == 1; }
|
||||
bool isJustLerp() const { return fMode == SkBlendMode::kSrc; }
|
||||
sk_sp<SkShader> fDst;
|
||||
sk_sp<SkShader> fSrc;
|
||||
const float fWeight;
|
||||
|
||||
typedef SkShaderBase INHERITED;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user