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>
This commit is contained in:
John Stiles 2021-07-30 14:17:24 -04:00 committed by SkCQ
parent ae2171eba6
commit 82c99d19a2
2 changed files with 103 additions and 68 deletions

View File

@ -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 @@ public:
};
// 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 @@ public:
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,

View File

@ -44,6 +44,8 @@
#include <algorithm>
using ChildType = SkRuntimeEffect::ChildType;
#ifdef SK_ENABLE_SKSL
namespace SkSL {
@ -128,11 +130,11 @@ static bool init_uniform_type(const SkSL::Context& ctx,
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 @@ static bool verify_child_effects(const std::vector<SkRuntimeEffect::Child>& refl
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 @@ static bool read_child_effects(SkReadBuffer& buffer,
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 @@ 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 ? (const SkFlattenable*)child.colorFilter.get() :
(const SkFlattenable*)child.blender.get());
buffer.writeFlattenable(child.flattenable());
}
}
@ -585,7 +571,7 @@ std::unique_ptr<SkFilterColorProgram> SkFilterColorProgram::Make(const SkRuntime
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 @@ static GrFPResult make_effect_fp(sk_sp<SkRuntimeEffect> effect,
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 @@ static GrFPResult make_effect_fp(sk_sp<SkRuntimeEffect> effect,
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ sk_sp<SkImage> SkRuntimeEffect::makeImage(GrRecordingContext* recordingContext,
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 @@ sk_sp<SkBlender> SkRuntimeEffect::makeBlender(sk_sp<SkData> uniforms,
///////////////////////////////////////////////////////////////////////////////////////////////////
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);