Allow sampling from SkBlenders.
Runtime shaders, color filters, and blenders are all able to sample from a blender. These use the blend-function signature; both a src-color and dst-color must be passed to sample. i.e.: sample(blender, s, d) Change-Id: I3738e6b0b4af6d1d79e62ca1815c80d6a1ae9d6f Bug: skia:12257 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/432056 Commit-Queue: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
1a2e7de8ea
commit
ce9a5c953d
@ -82,6 +82,7 @@ public:
|
||||
enum class Type {
|
||||
kShader,
|
||||
kColorFilter,
|
||||
kBlender,
|
||||
};
|
||||
|
||||
SkString name;
|
||||
@ -161,13 +162,15 @@ public:
|
||||
static Result MakeForBlender(std::unique_ptr<SkSL::Program> program, const Options&);
|
||||
static Result MakeForBlender(std::unique_ptr<SkSL::Program> program);
|
||||
|
||||
// Object that allows passing either an SkShader or SkColorFilter as a child
|
||||
// Object that allows passing a SkShader, SkColorFilter or SkBlender as a child
|
||||
struct ChildPtr {
|
||||
ChildPtr() = default;
|
||||
ChildPtr(sk_sp<SkShader> s) : shader(std::move(s)) {}
|
||||
ChildPtr(sk_sp<SkColorFilter> cf) : colorFilter(std::move(cf)) {}
|
||||
ChildPtr(sk_sp<SkBlender> b) : blender(std::move(b)) {}
|
||||
sk_sp<SkShader> shader;
|
||||
sk_sp<SkColorFilter> colorFilter;
|
||||
sk_sp<SkBlender> blender;
|
||||
};
|
||||
|
||||
sk_sp<SkShader> makeShader(sk_sp<SkData> uniforms,
|
||||
|
@ -130,7 +130,7 @@ static bool init_uniform_type(const SkSL::Context& ctx,
|
||||
|
||||
static SkRuntimeEffect::Child::Type child_type(const SkSL::Type& type) {
|
||||
switch (type.typeKind()) {
|
||||
// TODO(skia:12257): add support for kBlender
|
||||
case SkSL::Type::TypeKind::kBlender: return SkRuntimeEffect::Child::Type::kBlender;
|
||||
case SkSL::Type::TypeKind::kColorFilter: return SkRuntimeEffect::Child::Type::kColorFilter;
|
||||
case SkSL::Type::TypeKind::kShader: return SkRuntimeEffect::Child::Type::kShader;
|
||||
default: SkUNREACHABLE;
|
||||
@ -147,12 +147,17 @@ static bool verify_child_effects(const std::vector<SkRuntimeEffect::Child>& refl
|
||||
for (size_t i = 0; i < effectPtrs.size(); ++i) {
|
||||
switch (reflected[i].type) {
|
||||
case SkRuntimeEffect::Child::Type::kShader:
|
||||
if (effectPtrs[i].colorFilter) {
|
||||
if (effectPtrs[i].colorFilter || effectPtrs[i].blender) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
case SkRuntimeEffect::Child::Type::kColorFilter:
|
||||
if (effectPtrs[i].shader) {
|
||||
if (effectPtrs[i].shader || effectPtrs[i].blender) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
case SkRuntimeEffect::Child::Type::kBlender:
|
||||
if (effectPtrs[i].shader || effectPtrs[i].colorFilter) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
@ -178,6 +183,8 @@ static bool read_child_effects(SkReadBuffer& buffer,
|
||||
children->emplace_back(buffer.readShader());
|
||||
} else if (child.type == SkRuntimeEffect::Child::Type::kColorFilter) {
|
||||
children->emplace_back(buffer.readColorFilter());
|
||||
} else if (child.type == SkRuntimeEffect::Child::Type::kBlender) {
|
||||
children->emplace_back(buffer.readBlender());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -190,8 +197,10 @@ static void write_child_effects(SkWriteBuffer& buffer,
|
||||
const std::vector<SkRuntimeEffect::ChildPtr>& children) {
|
||||
buffer.write32(children.size());
|
||||
for (const auto& child : children) {
|
||||
buffer.writeFlattenable(child.shader ? (const SkFlattenable*)child.shader.get()
|
||||
: child.colorFilter.get());
|
||||
buffer.writeFlattenable(
|
||||
child.shader ? (const SkFlattenable*)child.shader.get() :
|
||||
child.colorFilter ? (const SkFlattenable*)child.colorFilter.get() :
|
||||
(const SkFlattenable*)child.blender.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,9 +578,10 @@ std::unique_ptr<SkFilterColorProgram> SkFilterColorProgram::Make(const SkRuntime
|
||||
// of those, we are unable to use this per-effect program, and callers will need to fall back
|
||||
// to another (slower) implementation.
|
||||
|
||||
// We also require that any children are *also* color filters (not shaders). In theory we could
|
||||
// detect the coords being passed to shader children, and replicate those calls, but that's
|
||||
// very complicated, and has diminishing returns. (eg, for table lookup color filters).
|
||||
// We also require that any children are *also* color filters (not shaders or blenders). In
|
||||
// theory we could detect the coords being passed to shader children, and replicate those calls,
|
||||
// but that's very complicated, and has diminishing returns. (eg, for table lookup color
|
||||
// filters).
|
||||
if (!std::all_of(effect->fChildren.begin(),
|
||||
effect->fChildren.end(),
|
||||
[](const SkRuntimeEffect::Child& c) {
|
||||
@ -777,12 +787,14 @@ static GrFPResult make_effect_fp(sk_sp<SkRuntimeEffect> effect,
|
||||
SkSTArray<8, std::unique_ptr<GrFragmentProcessor>> childFPs;
|
||||
for (const auto& child : children) {
|
||||
if (child.shader) {
|
||||
// Convert a SkShader into a child FP.
|
||||
auto childFP = as_SB(child.shader)->asFragmentProcessor(childArgs);
|
||||
if (!childFP) {
|
||||
return GrFPFailure(std::move(inputFP));
|
||||
}
|
||||
childFPs.push_back(std::move(childFP));
|
||||
} else if (child.colorFilter) {
|
||||
// Convert a SkColorFilter into a child FP.
|
||||
auto [success, childFP] = as_CFB(child.colorFilter)
|
||||
->asFragmentProcessor(/*inputFP=*/nullptr,
|
||||
childArgs.fContext,
|
||||
@ -791,7 +803,17 @@ static GrFPResult make_effect_fp(sk_sp<SkRuntimeEffect> effect,
|
||||
return GrFPFailure(std::move(inputFP));
|
||||
}
|
||||
childFPs.push_back(std::move(childFP));
|
||||
} else if (child.blender) {
|
||||
// Convert a SkBlender into a child FP.
|
||||
auto childFP = as_BB(child.blender)->asFragmentProcessor(/*srcFP=*/nullptr,
|
||||
/*dstFP=*/nullptr,
|
||||
childArgs);
|
||||
if (!childFP) {
|
||||
return GrFPFailure(std::move(inputFP));
|
||||
}
|
||||
childFPs.push_back(std::move(childFP));
|
||||
} else {
|
||||
// We have a null child effect.
|
||||
childFPs.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
@ -860,8 +882,10 @@ public:
|
||||
return color;
|
||||
};
|
||||
auto sampleBlender = [&](int ix, skvm::Color src, skvm::Color dst) {
|
||||
// TODO(skia:12257): implement sample(blender, src, dst)
|
||||
return src;
|
||||
if (SkBlender* blender = fChildren[ix].blender.get()) {
|
||||
return as_BB(blender)->program(p, src, dst, colorInfo, uniforms, alloc);
|
||||
}
|
||||
return blend(SkBlendMode::kSrcOver, src, dst);
|
||||
};
|
||||
|
||||
std::vector<skvm::Val> uniform = make_skvm_uniforms(p, uniforms, fEffect->uniformSize(),
|
||||
@ -891,8 +915,9 @@ public:
|
||||
auto evalChild = [&](int index, SkPMColor4f inColor) {
|
||||
const auto& child = fChildren[index];
|
||||
|
||||
// Guaranteed by initFilterColorInfo
|
||||
// SkFilterColorProgram::Make has guaranteed that any children will be color filters.
|
||||
SkASSERT(!child.shader);
|
||||
SkASSERT(!child.blender);
|
||||
return child.colorFilter ? as_CFB(child.colorFilter)->onFilterColor4f(inColor, dstCS)
|
||||
: inColor;
|
||||
};
|
||||
@ -1036,8 +1061,10 @@ public:
|
||||
return color;
|
||||
};
|
||||
auto sampleBlender = [&](int ix, skvm::Color src, skvm::Color dst) {
|
||||
// TODO(skia:12257): implement sample(blender, src, dst)
|
||||
return src;
|
||||
if (SkBlender* blender = fChildren[ix].blender.get()) {
|
||||
return as_BB(blender)->program(p, src, dst, colorInfo, uniforms, alloc);
|
||||
}
|
||||
return blend(SkBlendMode::kSrcOver, src, dst);
|
||||
};
|
||||
|
||||
std::vector<skvm::Val> uniform = make_skvm_uniforms(p, uniforms, fEffect->uniformSize(),
|
||||
@ -1144,8 +1171,10 @@ public:
|
||||
return color;
|
||||
};
|
||||
auto sampleBlender = [&](int ix, skvm::Color src, skvm::Color dst) {
|
||||
// TODO(skia:12257): implement sample(blender, src, dst)
|
||||
return src;
|
||||
if (SkBlender* blender = fChildren[ix].blender.get()) {
|
||||
return as_BB(blender)->program(p, src, dst, colorInfo, uniforms, alloc);
|
||||
}
|
||||
return blend(SkBlendMode::kSrcOver, src, dst);
|
||||
};
|
||||
|
||||
std::vector<skvm::Val> uniform = make_skvm_uniforms(p, uniforms, fEffect->uniformSize(),
|
||||
|
@ -146,8 +146,10 @@ public:
|
||||
}
|
||||
|
||||
String sampleBlender(int index, String src, String dst) override {
|
||||
// TODO(skia:12257): invokeChild does not yet allow sampling from a blender
|
||||
return "half4(1)";
|
||||
if (!fSelf->childProcessor(index)) {
|
||||
return String::printf("blend_src_over(%s, %s)", src.c_str(), dst.c_str());
|
||||
}
|
||||
return String(fSelf->invokeChild(index, src.c_str(), dst.c_str(), fArgs).c_str());
|
||||
}
|
||||
|
||||
GrGLSLSkSLFP* fSelf;
|
||||
|
@ -180,6 +180,6 @@ BuiltinTypes::BuiltinTypes()
|
||||
, fSkCaps(Type::MakeSpecialType("$sk_Caps", "O", Type::TypeKind::kOther))
|
||||
, fColorFilter(Type::MakeSpecialType("colorFilter", "CF", Type::TypeKind::kColorFilter))
|
||||
, fShader(Type::MakeSpecialType("shader", "SH", Type::TypeKind::kShader))
|
||||
, fBlender(Type::MakeSpecialType("$blender", "B", Type::TypeKind::kBlender)) {}
|
||||
, fBlender(Type::MakeSpecialType("blender", "B", Type::TypeKind::kBlender)) {}
|
||||
|
||||
} // namespace SkSL
|
||||
|
@ -141,7 +141,7 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
const FunctionDeclaration& function = c.function();
|
||||
const ExpressionArray& arguments = c.arguments();
|
||||
if (function.isBuiltin() && function.name() == "sample") {
|
||||
SkASSERT(arguments.size() == 2);
|
||||
SkASSERT(arguments.size() >= 2);
|
||||
const Expression* child = arguments[0].get();
|
||||
SkASSERT(child->type().isEffectChild());
|
||||
SkASSERT(child->is<VariableReference>());
|
||||
@ -164,20 +164,44 @@ void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
|
||||
SkASSERT(found);
|
||||
|
||||
// Shaders require a coordinate argument. Color filters require a color argument.
|
||||
// When we call sampleChild, the other value remains empty.
|
||||
// Blenders require two color arguments.
|
||||
String sampleOutput;
|
||||
{
|
||||
AutoOutputBuffer outputToBuffer(this);
|
||||
this->writeExpression(*arguments.back(), Precedence::kSequence);
|
||||
if (child->type().typeKind() == Type::TypeKind::kShader) {
|
||||
SkASSERT(arguments[1]->type() == *fProgram.fContext->fTypes.fFloat2);
|
||||
sampleOutput = fCallbacks->sampleShader(index, outputToBuffer.fBuffer.str());
|
||||
AutoOutputBuffer exprBuffer(this);
|
||||
this->writeExpression(*arguments[1], Precedence::kSequence);
|
||||
|
||||
} else {
|
||||
SkASSERT(child->type().typeKind() == Type::TypeKind::kColorFilter);
|
||||
SkASSERT(arguments[1]->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arguments[1]->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
sampleOutput = fCallbacks->sampleColorFilter(index, outputToBuffer.fBuffer.str());
|
||||
switch (child->type().typeKind()) {
|
||||
case Type::TypeKind::kShader: {
|
||||
SkASSERT(arguments.size() == 2);
|
||||
SkASSERT(arguments[1]->type() == *fProgram.fContext->fTypes.fFloat2);
|
||||
sampleOutput = fCallbacks->sampleShader(index, exprBuffer.fBuffer.str());
|
||||
break;
|
||||
}
|
||||
case Type::TypeKind::kColorFilter: {
|
||||
SkASSERT(arguments.size() == 2);
|
||||
SkASSERT(arguments[1]->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arguments[1]->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
sampleOutput = fCallbacks->sampleColorFilter(index, exprBuffer.fBuffer.str());
|
||||
break;
|
||||
}
|
||||
case Type::TypeKind::kBlender: {
|
||||
SkASSERT(arguments.size() == 3);
|
||||
SkASSERT(arguments[1]->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arguments[1]->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
SkASSERT(arguments[2]->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arguments[2]->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
|
||||
AutoOutputBuffer exprBuffer2(this);
|
||||
this->writeExpression(*arguments[2], Precedence::kSequence);
|
||||
|
||||
sampleOutput = fCallbacks->sampleBlender(index, exprBuffer.fBuffer.str(),
|
||||
exprBuffer2.fBuffer.str());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
SkDEBUGFAILF("cannot sample from type '%s'",
|
||||
child->type().description().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
this->write(sampleOutput);
|
||||
|
@ -873,7 +873,7 @@ Value SkVMGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
if (intrinsicKind == k_sample_IntrinsicKind) {
|
||||
// Sample is very special. The first argument is a child (shader/colorFilter/blender),
|
||||
// which is opaque and can't be evaluated.
|
||||
SkASSERT(nargs == 2);
|
||||
SkASSERT(nargs >= 2);
|
||||
const Expression* child = c.arguments()[0].get();
|
||||
SkASSERT(child->type().isEffectChild());
|
||||
SkASSERT(child->is<VariableReference>());
|
||||
@ -887,16 +887,43 @@ Value SkVMGenerator::writeIntrinsicCall(const FunctionCall& c) {
|
||||
Value argVal = this->writeExpression(*arg);
|
||||
skvm::Color color;
|
||||
|
||||
if (child->type().typeKind() == Type::TypeKind::kShader) {
|
||||
SkASSERT(arg->type() == *fProgram.fContext->fTypes.fFloat2);
|
||||
skvm::Coord coord = {f32(argVal[0]), f32(argVal[1])};
|
||||
color = fSampleShader(fp_it->second, coord);
|
||||
} else {
|
||||
SkASSERT(child->type().typeKind() == Type::TypeKind::kColorFilter);
|
||||
SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arg->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
skvm::Color inColor = {f32(argVal[0]), f32(argVal[1]), f32(argVal[2]), f32(argVal[3])};
|
||||
color = fSampleColorFilter(fp_it->second, inColor);
|
||||
switch (child->type().typeKind()) {
|
||||
case Type::TypeKind::kShader: {
|
||||
SkASSERT(nargs == 2);
|
||||
SkASSERT(arg->type() == *fProgram.fContext->fTypes.fFloat2);
|
||||
skvm::Coord coord = {f32(argVal[0]), f32(argVal[1])};
|
||||
color = fSampleShader(fp_it->second, coord);
|
||||
break;
|
||||
}
|
||||
case Type::TypeKind::kColorFilter: {
|
||||
SkASSERT(nargs == 2);
|
||||
SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arg->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
skvm::Color inColor = {f32(argVal[0]), f32(argVal[1]),
|
||||
f32(argVal[2]), f32(argVal[3])};
|
||||
color = fSampleColorFilter(fp_it->second, inColor);
|
||||
break;
|
||||
}
|
||||
case Type::TypeKind::kBlender: {
|
||||
SkASSERT(nargs == 3);
|
||||
SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arg->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
skvm::Color srcColor = {f32(argVal[0]), f32(argVal[1]),
|
||||
f32(argVal[2]), f32(argVal[3])};
|
||||
|
||||
arg = c.arguments()[2].get();
|
||||
argVal = this->writeExpression(*arg);
|
||||
SkASSERT(arg->type() == *fProgram.fContext->fTypes.fHalf4 ||
|
||||
arg->type() == *fProgram.fContext->fTypes.fFloat4);
|
||||
skvm::Color dstColor = {f32(argVal[0]), f32(argVal[1]),
|
||||
f32(argVal[2]), f32(argVal[3])};
|
||||
|
||||
color = fSampleBlender(fp_it->second, srcColor, dstColor);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
SkDEBUGFAILF("cannot sample from type '%s'", child->type().description().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
Value result(4);
|
||||
|
@ -1,4 +1,4 @@
|
||||
static uint8_t SKSL_INCLUDE_sksl_rt_blend[] = {56,0,
|
||||
static uint8_t SKSL_INCLUDE_sksl_rt_blend[] = {74,0,
|
||||
1,115,
|
||||
6,115,104,97,100,101,114,
|
||||
6,99,111,111,114,100,115,
|
||||
@ -8,7 +8,11 @@ static uint8_t SKSL_INCLUDE_sksl_rt_blend[] = {56,0,
|
||||
1,102,
|
||||
11,99,111,108,111,114,70,105,108,116,101,114,
|
||||
5,99,111,108,111,114,
|
||||
47,7,0,
|
||||
1,98,
|
||||
7,98,108,101,110,100,101,114,
|
||||
3,115,114,99,
|
||||
3,100,115,116,
|
||||
47,12,0,
|
||||
51,1,0,
|
||||
16,2,0,
|
||||
48,2,0,4,0,3,
|
||||
@ -29,8 +33,24 @@ static uint8_t SKSL_INCLUDE_sksl_rt_blend[] = {56,0,
|
||||
28,11,0,
|
||||
16,25,0,2,7,0,9,0,
|
||||
45,6,0,
|
||||
45,11,0,1,0,
|
||||
5,0,
|
||||
45,11,0,
|
||||
51,12,0,
|
||||
16,58,0,
|
||||
48,13,0,60,0,3,
|
||||
51,14,0,
|
||||
16,68,0,
|
||||
45,6,0,3,
|
||||
51,15,0,
|
||||
16,72,0,
|
||||
45,6,0,3,
|
||||
50,16,0,3,
|
||||
45,5,0,
|
||||
45,11,0,
|
||||
28,17,0,
|
||||
16,25,0,3,12,0,14,0,15,0,
|
||||
45,6,0,
|
||||
45,17,0,1,0,
|
||||
10,0,
|
||||
19,
|
||||
20,};
|
||||
static constexpr size_t SKSL_INCLUDE_sksl_rt_blend_LENGTH = sizeof(SKSL_INCLUDE_sksl_rt_blend);
|
||||
|
@ -1,4 +1,4 @@
|
||||
static uint8_t SKSL_INCLUDE_sksl_rt_colorfilter[] = {56,0,
|
||||
static uint8_t SKSL_INCLUDE_sksl_rt_colorfilter[] = {74,0,
|
||||
1,115,
|
||||
6,115,104,97,100,101,114,
|
||||
6,99,111,111,114,100,115,
|
||||
@ -8,7 +8,11 @@ static uint8_t SKSL_INCLUDE_sksl_rt_colorfilter[] = {56,0,
|
||||
1,102,
|
||||
11,99,111,108,111,114,70,105,108,116,101,114,
|
||||
5,99,111,108,111,114,
|
||||
47,7,0,
|
||||
1,98,
|
||||
7,98,108,101,110,100,101,114,
|
||||
3,115,114,99,
|
||||
3,100,115,116,
|
||||
47,12,0,
|
||||
51,1,0,
|
||||
16,2,0,
|
||||
48,2,0,4,0,3,
|
||||
@ -29,8 +33,24 @@ static uint8_t SKSL_INCLUDE_sksl_rt_colorfilter[] = {56,0,
|
||||
28,11,0,
|
||||
16,25,0,2,7,0,9,0,
|
||||
45,6,0,
|
||||
45,11,0,1,0,
|
||||
5,0,
|
||||
45,11,0,
|
||||
51,12,0,
|
||||
16,58,0,
|
||||
48,13,0,60,0,3,
|
||||
51,14,0,
|
||||
16,68,0,
|
||||
45,6,0,3,
|
||||
51,15,0,
|
||||
16,72,0,
|
||||
45,6,0,3,
|
||||
50,16,0,3,
|
||||
45,5,0,
|
||||
45,11,0,
|
||||
28,17,0,
|
||||
16,25,0,3,12,0,14,0,15,0,
|
||||
45,6,0,
|
||||
45,17,0,1,0,
|
||||
10,0,
|
||||
19,
|
||||
20,};
|
||||
static constexpr size_t SKSL_INCLUDE_sksl_rt_colorfilter_LENGTH = sizeof(SKSL_INCLUDE_sksl_rt_colorfilter);
|
||||
|
@ -1,4 +1,4 @@
|
||||
static uint8_t SKSL_INCLUDE_sksl_rt_shader[] = {76,0,
|
||||
static uint8_t SKSL_INCLUDE_sksl_rt_shader[] = {94,0,
|
||||
12,115,107,95,70,114,97,103,67,111,111,114,100,
|
||||
6,102,108,111,97,116,52,
|
||||
1,115,
|
||||
@ -10,7 +10,11 @@ static uint8_t SKSL_INCLUDE_sksl_rt_shader[] = {76,0,
|
||||
1,102,
|
||||
11,99,111,108,111,114,70,105,108,116,101,114,
|
||||
5,99,111,108,111,114,
|
||||
47,8,0,
|
||||
1,98,
|
||||
7,98,108,101,110,100,101,114,
|
||||
3,115,114,99,
|
||||
3,100,115,116,
|
||||
47,13,0,
|
||||
51,1,0,
|
||||
35,
|
||||
34,0,2,0,0,255,255,255,255,255,15,0,255,255,255,255,0,2,0,
|
||||
@ -35,8 +39,24 @@ static uint8_t SKSL_INCLUDE_sksl_rt_shader[] = {76,0,
|
||||
28,13,0,
|
||||
16,45,0,2,9,0,11,0,
|
||||
45,8,0,
|
||||
45,13,0,2,0,
|
||||
6,0,
|
||||
45,13,0,
|
||||
51,14,0,
|
||||
16,78,0,
|
||||
48,15,0,80,0,3,
|
||||
51,16,0,
|
||||
16,88,0,
|
||||
45,8,0,3,
|
||||
51,17,0,
|
||||
16,92,0,
|
||||
45,8,0,3,
|
||||
50,18,0,3,
|
||||
45,7,0,
|
||||
45,13,0,
|
||||
28,19,0,
|
||||
16,45,0,3,14,0,16,0,17,0,
|
||||
45,8,0,
|
||||
45,19,0,2,0,
|
||||
11,0,
|
||||
0,0,
|
||||
19,
|
||||
53,
|
||||
|
@ -1,2 +1,3 @@
|
||||
half4 sample(shader s, float2 coords);
|
||||
half4 sample(colorFilter f, half4 color);
|
||||
half4 sample(blender b, half4 src, half4 dst);
|
||||
|
@ -1,2 +1,3 @@
|
||||
half4 sample(shader s, float2 coords);
|
||||
half4 sample(colorFilter f, half4 color);
|
||||
half4 sample(blender b, half4 src, half4 dst);
|
||||
|
@ -2,3 +2,4 @@ layout(builtin=15) float4 sk_FragCoord;
|
||||
|
||||
half4 sample(shader s, float2 coords);
|
||||
half4 sample(colorFilter f, half4 color);
|
||||
half4 sample(blender b, half4 src, half4 dst);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "include/core/SkData.h"
|
||||
#include "include/core/SkPaint.h"
|
||||
#include "include/core/SkSurface.h"
|
||||
#include "include/effects/SkBlenders.h"
|
||||
#include "include/effects/SkRuntimeEffect.h"
|
||||
#include "include/gpu/GrDirectContext.h"
|
||||
#include "src/core/SkColorSpacePriv.h"
|
||||
@ -618,10 +619,10 @@ static void test_RuntimeEffect_Blenders(skiatest::Reporter* r, GrRecordingContex
|
||||
effect.test(0xFF888888);
|
||||
|
||||
// Fill the destination with a variety of colors (using the RGBW shader)
|
||||
SkPaint paint;
|
||||
paint.setShader(make_RGBW_shader());
|
||||
paint.setBlendMode(SkBlendMode::kSrc);
|
||||
surface->getCanvas()->drawPaint(paint);
|
||||
SkPaint rgbwPaint;
|
||||
rgbwPaint.setShader(make_RGBW_shader());
|
||||
rgbwPaint.setBlendMode(SkBlendMode::kSrc);
|
||||
surface->getCanvas()->drawPaint(rgbwPaint);
|
||||
|
||||
// Verify that we can read back the dest color exactly as-is (ignoring the source color)
|
||||
// This is equivalent to the kDst blend mode.
|
||||
@ -643,13 +644,27 @@ static void test_RuntimeEffect_Blenders(skiatest::Reporter* r, GrRecordingContex
|
||||
// Sampling children
|
||||
//
|
||||
|
||||
// Sampling a null child should return the paint color
|
||||
// Sampling a null shader/color filter should return the paint color.
|
||||
effect.build("uniform shader child;"
|
||||
"half4 main(half4 s, half4 d) { return sample(child, s.rg); }");
|
||||
effect.child("child") = nullptr;
|
||||
effect.test(0xFF00FFFF,
|
||||
[](SkCanvas*, SkPaint* paint) { paint->setColor4f({1.0f, 1.0f, 0.0f, 1.0f}); });
|
||||
|
||||
effect.build("uniform colorFilter child;"
|
||||
"half4 main(half4 s, half4 d) { return sample(child, s); }");
|
||||
effect.child("child") = nullptr;
|
||||
effect.test(0xFF00FFFF,
|
||||
[](SkCanvas*, SkPaint* paint) { paint->setColor4f({1.0f, 1.0f, 0.0f, 1.0f}); });
|
||||
|
||||
// Sampling a null blender should do a src-over blend. Draw 50% black over RGBW to verify this.
|
||||
surface->getCanvas()->drawPaint(rgbwPaint);
|
||||
effect.build("uniform blender child;"
|
||||
"half4 main(half4 s, half4 d) { return sample(child, s, d); }");
|
||||
effect.child("child") = nullptr;
|
||||
effect.test({0xFF000080, 0xFF008000, 0xFF800000, 0xFF808080},
|
||||
[](SkCanvas*, SkPaint* paint) { paint->setColor4f({0.0f, 0.0f, 0.0f, 0.497f}); });
|
||||
|
||||
// Sampling a shader at various coordinates
|
||||
effect.build("uniform shader child;"
|
||||
"uniform half2 pos;"
|
||||
@ -672,6 +687,22 @@ static void test_RuntimeEffect_Blenders(skiatest::Reporter* r, GrRecordingContex
|
||||
"half4 main(half4 s, half4 d) { return sample(child, half4(1)); }");
|
||||
effect.child("child") = SkColorFilters::Blend(0xFF012345, SkBlendMode::kSrc);
|
||||
effect.test(0xFF452301);
|
||||
|
||||
// Sampling a built-in blender
|
||||
surface->getCanvas()->drawPaint(rgbwPaint);
|
||||
effect.build("uniform blender child;"
|
||||
"half4 main(half4 s, half4 d) { return sample(child, s, d); }");
|
||||
effect.child("child") = SkBlender::Mode(SkBlendMode::kPlus);
|
||||
effect.test({0xFF4523FF, 0xFF45FF01, 0xFFFF2301, 0xFFFFFFFF},
|
||||
[](SkCanvas*, SkPaint* paint) { paint->setColor(0xFF012345); });
|
||||
|
||||
// Sampling a runtime-effect blender
|
||||
surface->getCanvas()->drawPaint(rgbwPaint);
|
||||
effect.build("uniform blender child;"
|
||||
"half4 main(half4 s, half4 d) { return sample(child, s, d); }");
|
||||
effect.child("child") = SkBlenders::Arithmetic(0, 1, 1, 0, /*enforcePremul=*/false);
|
||||
effect.test({0xFF4523FF, 0xFF45FF01, 0xFFFF2301, 0xFFFFFFFF},
|
||||
[](SkCanvas*, SkPaint* paint) { paint->setColor(0xFF012345); });
|
||||
}
|
||||
|
||||
DEF_TEST(SkRuntimeEffect_Blender_CPU, r) {
|
||||
|
Loading…
Reference in New Issue
Block a user