Reduce size of ChildPtr object.
We take advantage of their shared SkFlattenable lineage to store all
three types of object in the same sk_sp, and check their
Flattenable type to distinguish between them. Accessors allow us to
mimic the coding style of having three distinct fields.
Change-Id: I16426377f10fa2abffbf09bb7998c968614433df
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/435019
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/include/effects/SkRuntimeEffect.h b/include/effects/SkRuntimeEffect.h
index a5c3e3b..08c8e8d 100644
--- a/include/effects/SkRuntimeEffect.h
+++ b/include/effects/SkRuntimeEffect.h
@@ -18,6 +18,7 @@
#include "include/core/SkString.h"
#include "include/private/SkOnce.h"
#include "include/private/SkSLSampleUsage.h"
+#include "include/private/SkTOptional.h"
#include <string>
#include <vector>
@@ -78,16 +79,16 @@
};
// Reflected description of a uniform child (shader or colorFilter) in the effect's SkSL
- struct Child {
- enum class Type {
- kShader,
- kColorFilter,
- kBlender,
- };
+ enum class ChildType {
+ kShader,
+ kColorFilter,
+ kBlender,
+ };
- SkString name;
- Type type;
- int index;
+ struct Child {
+ SkString name;
+ ChildType type;
+ int index;
};
class Options {
@@ -163,14 +164,22 @@
static Result MakeForBlender(std::unique_ptr<SkSL::Program> program);
// Object that allows passing a SkShader, SkColorFilter or SkBlender as a child
- struct ChildPtr {
+ class ChildPtr {
+ public:
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;
+ ChildPtr(sk_sp<SkShader> s) : fChild(std::move(s)) {}
+ ChildPtr(sk_sp<SkColorFilter> cf) : fChild(std::move(cf)) {}
+ ChildPtr(sk_sp<SkBlender> b) : fChild(std::move(b)) {}
+
+ skstd::optional<ChildType> type() const;
+
+ SkShader* shader() const;
+ SkColorFilter* colorFilter() const;
+ SkBlender* blender() const;
+ SkFlattenable* flattenable() const { return fChild.get(); }
+
+ private:
+ sk_sp<SkFlattenable> fChild;
};
sk_sp<SkShader> makeShader(sk_sp<SkData> uniforms,
diff --git a/src/core/SkRuntimeEffect.cpp b/src/core/SkRuntimeEffect.cpp
index d137599..2c9794e 100644
--- a/src/core/SkRuntimeEffect.cpp
+++ b/src/core/SkRuntimeEffect.cpp
@@ -44,6 +44,8 @@
#include <algorithm>
+using ChildType = SkRuntimeEffect::ChildType;
+
#ifdef SK_ENABLE_SKSL
namespace SkSL {
@@ -128,11 +130,11 @@
return false;
}
-static SkRuntimeEffect::Child::Type child_type(const SkSL::Type& type) {
+static ChildType child_type(const SkSL::Type& type) {
switch (type.typeKind()) {
- 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;
+ case SkSL::Type::TypeKind::kBlender: return ChildType::kBlender;
+ case SkSL::Type::TypeKind::kColorFilter: return ChildType::kColorFilter;
+ case SkSL::Type::TypeKind::kShader: return ChildType::kShader;
default: SkUNREACHABLE;
}
}
@@ -143,26 +145,13 @@
if (reflected.size() != effectPtrs.size()) {
return false;
}
+
// Verify that each child object's type matches its declared type in the SkSL.
for (size_t i = 0; i < effectPtrs.size(); ++i) {
- switch (reflected[i].type) {
- case SkRuntimeEffect::Child::Type::kShader:
- if (effectPtrs[i].colorFilter || effectPtrs[i].blender) {
- return false;
- }
- continue;
- case SkRuntimeEffect::Child::Type::kColorFilter:
- 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;
+ skstd::optional<ChildType> effectType = effectPtrs[i].type();
+ if (effectType && effectType != reflected[i].type) {
+ return false;
}
- SkDEBUGFAILF("unrecognized SkSL child type %d", (int)reflected[i].type);
}
return true;
}
@@ -179,11 +168,11 @@
children->reserve_back(childCount);
for (const auto& child : effect->children()) {
- if (child.type == SkRuntimeEffect::Child::Type::kShader) {
+ if (child.type == ChildType::kShader) {
children->emplace_back(buffer.readShader());
- } else if (child.type == SkRuntimeEffect::Child::Type::kColorFilter) {
+ } else if (child.type == ChildType::kColorFilter) {
children->emplace_back(buffer.readColorFilter());
- } else if (child.type == SkRuntimeEffect::Child::Type::kBlender) {
+ } else if (child.type == ChildType::kBlender) {
children->emplace_back(buffer.readBlender());
} else {
return false;
@@ -197,10 +186,7 @@
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 ? (const SkFlattenable*)child.colorFilter.get() :
- (const SkFlattenable*)child.blender.get());
+ buffer.writeFlattenable(child.flattenable());
}
}
@@ -585,7 +571,7 @@
if (!std::all_of(effect->fChildren.begin(),
effect->fChildren.end(),
[](const SkRuntimeEffect::Child& c) {
- return c.type == SkRuntimeEffect::Child::Type::kColorFilter;
+ return c.type == ChildType::kColorFilter;
})) {
return nullptr;
}
@@ -786,16 +772,17 @@
const GrFPArgs& childArgs) {
SkSTArray<8, std::unique_ptr<GrFragmentProcessor>> childFPs;
for (const auto& child : children) {
- if (child.shader) {
+ skstd::optional<ChildType> type = child.type();
+ if (type == ChildType::kShader) {
// Convert a SkShader into a child FP.
- auto childFP = as_SB(child.shader)->asFragmentProcessor(childArgs);
+ 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) {
+ } else if (type == ChildType::kColorFilter) {
// Convert a SkColorFilter into a child FP.
- auto [success, childFP] = as_CFB(child.colorFilter)
+ auto [success, childFP] = as_CFB(child.colorFilter())
->asFragmentProcessor(/*inputFP=*/nullptr,
childArgs.fContext,
*childArgs.fDstColorInfo);
@@ -803,11 +790,11 @@
return GrFPFailure(std::move(inputFP));
}
childFPs.push_back(std::move(childFP));
- } else if (child.blender) {
+ } else if (type == ChildType::kBlender) {
// Convert a SkBlender into a child FP.
- auto childFP = as_BB(child.blender)->asFragmentProcessor(/*srcFP=*/nullptr,
- /*dstFP=*/nullptr,
- childArgs);
+ auto childFP = as_BB(child.blender())->asFragmentProcessor(/*srcFP=*/nullptr,
+ /*dstFP=*/nullptr,
+ childArgs);
if (!childFP) {
return GrFPFailure(std::move(inputFP));
}
@@ -868,7 +855,7 @@
SkASSERT(inputs);
auto sampleShader = [&](int ix, skvm::Coord coord) {
- if (SkShader* shader = fChildren[ix].shader.get()) {
+ if (SkShader* shader = fChildren[ix].shader()) {
SkSimpleMatrixProvider mats{SkMatrix::I()};
return as_SB(shader)->program(p, coord, coord, c, mats, /*localM=*/nullptr,
colorInfo, uniforms, alloc);
@@ -876,13 +863,13 @@
return c;
};
auto sampleColorFilter = [&](int ix, skvm::Color color) {
- if (SkColorFilter* colorFilter = fChildren[ix].colorFilter.get()) {
+ if (SkColorFilter* colorFilter = fChildren[ix].colorFilter()) {
return as_CFB(colorFilter)->program(p, color, colorInfo, uniforms, alloc);
}
return color;
};
auto sampleBlender = [&](int ix, skvm::Color src, skvm::Color dst) {
- if (SkBlender* blender = fChildren[ix].blender.get()) {
+ if (SkBlender* blender = fChildren[ix].blender()) {
return as_BB(blender)->program(p, src, dst, colorInfo, uniforms, alloc);
}
return blend(SkBlendMode::kSrcOver, src, dst);
@@ -916,10 +903,12 @@
const auto& child = fChildren[index];
// 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;
+ SkASSERT(!child.shader());
+ SkASSERT(!child.blender());
+ if (SkColorFilter* colorFilter = child.colorFilter()) {
+ return as_CFB(colorFilter)->onFilterColor4f(inColor, dstCS);
+ }
+ return inColor;
};
return program->eval(color, inputs->data(), evalChild);
@@ -1047,7 +1036,7 @@
local = SkShaderBase::ApplyMatrix(p,inv,local,uniforms);
auto sampleShader = [&](int ix, skvm::Coord coord) {
- if (SkShader* shader = fChildren[ix].shader.get()) {
+ if (SkShader* shader = fChildren[ix].shader()) {
SkOverrideDeviceMatrixProvider mats{matrices, SkMatrix::I()};
return as_SB(shader)->program(p, device, coord, paint, mats, /*localM=*/nullptr,
colorInfo, uniforms, alloc);
@@ -1055,13 +1044,13 @@
return paint;
};
auto sampleColorFilter = [&](int ix, skvm::Color color) {
- if (SkColorFilter* colorFilter = fChildren[ix].colorFilter.get()) {
+ if (SkColorFilter* colorFilter = fChildren[ix].colorFilter()) {
return as_CFB(colorFilter)->program(p, color, colorInfo, uniforms, alloc);
}
return color;
};
auto sampleBlender = [&](int ix, skvm::Color src, skvm::Color dst) {
- if (SkBlender* blender = fChildren[ix].blender.get()) {
+ if (SkBlender* blender = fChildren[ix].blender()) {
return as_BB(blender)->program(p, src, dst, colorInfo, uniforms, alloc);
}
return blend(SkBlendMode::kSrcOver, src, dst);
@@ -1157,7 +1146,7 @@
SkASSERT(inputs);
auto sampleShader = [&](int ix, skvm::Coord coord) {
- if (SkShader* shader = fChildren[ix].shader.get()) {
+ if (SkShader* shader = fChildren[ix].shader()) {
SkSimpleMatrixProvider mats{SkMatrix::I()};
return as_SB(shader)->program(p, coord, coord, src, mats, /*localM=*/nullptr,
colorInfo, uniforms, alloc);
@@ -1165,13 +1154,13 @@
return src;
};
auto sampleColorFilter = [&](int ix, skvm::Color color) {
- if (SkColorFilter* colorFilter = fChildren[ix].colorFilter.get()) {
+ if (SkColorFilter* colorFilter = fChildren[ix].colorFilter()) {
return as_CFB(colorFilter)->program(p, color, colorInfo, uniforms, alloc);
}
return color;
};
auto sampleBlender = [&](int ix, skvm::Color src, skvm::Color dst) {
- if (SkBlender* blender = fChildren[ix].blender.get()) {
+ if (SkBlender* blender = fChildren[ix].blender()) {
return as_BB(blender)->program(p, src, dst, colorInfo, uniforms, alloc);
}
return blend(SkBlendMode::kSrcOver, src, dst);
@@ -1303,10 +1292,11 @@
SkSTArray<8, std::unique_ptr<GrFragmentProcessor>> childFPs;
for (size_t i = 0; i < children.size(); ++i) {
// TODO: add support for other types of child effects
- if (!children[i].shader) {
+ if (SkShader* shader = children[i].shader()) {
+ childFPs.push_back(as_SB(shader)->asFragmentProcessor(args));
+ } else {
return nullptr;
}
- childFPs.push_back(as_SB(children[i].shader)->asFragmentProcessor(args));
}
auto fp = GrSkSLFP::MakeWithData(sk_ref_sp(this),
"runtime_image",
@@ -1408,6 +1398,42 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
+skstd::optional<ChildType> SkRuntimeEffect::ChildPtr::type() const {
+ if (fChild) {
+ switch (fChild->getFlattenableType()) {
+ case SkFlattenable::kSkShader_Type:
+ return ChildType::kShader;
+ case SkFlattenable::kSkColorFilter_Type:
+ return ChildType::kColorFilter;
+ case SkFlattenable::kSkBlender_Type:
+ return ChildType::kBlender;
+ default:
+ break;
+ }
+ }
+ return skstd::nullopt;
+}
+
+SkShader* SkRuntimeEffect::ChildPtr::shader() const {
+ return (fChild && fChild->getFlattenableType() == SkFlattenable::kSkShader_Type)
+ ? static_cast<SkShader*>(fChild.get())
+ : nullptr;
+}
+
+SkColorFilter* SkRuntimeEffect::ChildPtr::colorFilter() const {
+ return (fChild && fChild->getFlattenableType() == SkFlattenable::kSkColorFilter_Type)
+ ? static_cast<SkColorFilter*>(fChild.get())
+ : nullptr;
+}
+
+SkBlender* SkRuntimeEffect::ChildPtr::blender() const {
+ return (fChild && fChild->getFlattenableType() == SkFlattenable::kSkBlender_Type)
+ ? static_cast<SkBlender*>(fChild.get())
+ : nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
void SkRuntimeEffect::RegisterFlattenables() {
SK_REGISTER_FLATTENABLE(SkRuntimeColorFilter);
SK_REGISTER_FLATTENABLE(SkRTShader);