| /* |
| * Copyright 2022 Google LLC |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "include/core/SkTypes.h" |
| |
| #ifdef SK_ENABLE_PRECOMPILE |
| |
| #include "src/gpu/graphite/FactoryFunctions.h" |
| #include "src/gpu/graphite/Precompile.h" |
| #include "src/gpu/graphite/PrecompileBasePriv.h" |
| |
| namespace skgpu::graphite { |
| |
| //-------------------------------------------------------------------------------------------------- |
| class PrecompileBlendModeBlender : public PrecompileBlender { |
| public: |
| PrecompileBlendModeBlender(SkBlendMode blendMode) : fBlendMode(blendMode) {} |
| |
| std::optional<SkBlendMode> asBlendMode() const final { return fBlendMode; } |
| |
| private: |
| SkBlendMode fBlendMode; |
| }; |
| |
| sk_sp<PrecompileBlender> PrecompileBlender::Mode(SkBlendMode blendMode) { |
| return sk_make_sp<PrecompileBlendModeBlender>(blendMode); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| class PrecompileColorShader : public PrecompileShader { |
| public: |
| PrecompileColorShader() {} |
| }; |
| |
| sk_sp<PrecompileShader> PrecompileShaders::Color() { |
| return sk_make_sp<PrecompileColorShader>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| class PrecompileBlendShader : public PrecompileShader { |
| public: |
| PrecompileBlendShader(SkSpan<const sk_sp<PrecompileBlender>> blenders, |
| SkSpan<const sk_sp<PrecompileShader>> dsts, |
| SkSpan<const sk_sp<PrecompileShader>> srcs) |
| : fBlenders(blenders.begin(), blenders.end()) |
| , fDsts(dsts.begin(), dsts.end()) |
| , fSrcs(srcs.begin(), srcs.end()) { |
| } |
| |
| private: |
| int numChildCombinations() const override { |
| int numBlenderCombos = CountBlenderCombos(fBlenders); |
| |
| int numDstCombos = 0; |
| for (auto d : fDsts) { |
| numDstCombos += d->priv().numChildCombinations(); |
| } |
| |
| int numSrcCombos = 0; |
| for (auto s : fSrcs) { |
| numSrcCombos += s->priv().numChildCombinations(); |
| } |
| |
| return numBlenderCombos * numDstCombos * numSrcCombos; |
| } |
| |
| std::vector<sk_sp<PrecompileBlender>> fBlenders; |
| std::vector<sk_sp<PrecompileShader>> fDsts; |
| std::vector<sk_sp<PrecompileShader>> fSrcs; |
| }; |
| |
| sk_sp<PrecompileShader> PrecompileShaders::Blend( |
| SkSpan<const sk_sp<PrecompileBlender>> blenders, |
| SkSpan<const sk_sp<PrecompileShader>> dsts, |
| SkSpan<const sk_sp<PrecompileShader>> srcs) { |
| return sk_make_sp<PrecompileBlendShader>(std::move(blenders), |
| std::move(dsts), std::move(srcs)); |
| } |
| |
| sk_sp<PrecompileShader> PrecompileShaders::Blend( |
| SkSpan<SkBlendMode> blendModes, |
| SkSpan<const sk_sp<PrecompileShader>> dsts, |
| SkSpan<const sk_sp<PrecompileShader>> srcs) { |
| std::vector<sk_sp<PrecompileBlender>> tmp; |
| tmp.reserve(blendModes.size()); |
| for (SkBlendMode bm : blendModes) { |
| tmp.emplace_back(PrecompileBlender::Mode(bm)); |
| } |
| |
| return sk_make_sp<PrecompileBlendShader>(tmp, std::move(dsts), std::move(srcs)); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sk_sp<PrecompileShader> PrecompileShaders::Image() { |
| return sk_make_sp<PrecompileShader>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sk_sp<PrecompileShader> PrecompileShaders::LinearGradient() { |
| return sk_make_sp<PrecompileShader>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sk_sp<PrecompileShader> PrecompileShaders::RadialGradient() { |
| return sk_make_sp<PrecompileShader>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sk_sp<PrecompileShader> PrecompileShaders::TwoPointConicalGradient() { |
| return sk_make_sp<PrecompileShader>(); |
| } |
| |
| sk_sp<PrecompileShader> PrecompileShaders::SweepGradient() { |
| return sk_make_sp<PrecompileShader>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sk_sp<PrecompileMaskFilter> PrecompileMaskFilters::Blur() { |
| return sk_make_sp<PrecompileMaskFilter>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sk_sp<PrecompileColorFilter> PrecompileColorFilters::Matrix() { |
| return sk_make_sp<PrecompileColorFilter>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| sk_sp<PrecompileImageFilter> PrecompileImageFilters::Blur() { |
| return sk_make_sp<PrecompileImageFilter>(); |
| } |
| |
| sk_sp<PrecompileImageFilter> PrecompileImageFilters::Image() { |
| return sk_make_sp<PrecompileImageFilter>(); |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| PrecompileChildPtr::PrecompileChildPtr(sk_sp<PrecompileShader> s) : fChild(std::move(s)) {} |
| PrecompileChildPtr::PrecompileChildPtr(sk_sp<PrecompileColorFilter> cf) |
| : fChild(std::move(cf)) { |
| } |
| PrecompileChildPtr::PrecompileChildPtr(sk_sp<PrecompileBlender> b) : fChild(std::move(b)) {} |
| |
| namespace { |
| |
| #ifdef SK_DEBUG |
| |
| bool precompilebase_is_valid_as_child(const PrecompileBase *child) { |
| if (!child) { |
| return true; |
| } |
| |
| switch (child->type()) { |
| case PrecompileBase::Type::kShader: |
| case PrecompileBase::Type::kColorFilter: |
| case PrecompileBase::Type::kBlender: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| #endif // SK_DEBUG |
| |
| } // anonymous namespace |
| |
| PrecompileChildPtr::PrecompileChildPtr(sk_sp<PrecompileBase> child) |
| : fChild(std::move(child)) { |
| SkASSERT(precompilebase_is_valid_as_child(fChild.get())); |
| } |
| |
| std::optional<SkRuntimeEffect::ChildType> PrecompileChildPtr::type() const { |
| if (fChild) { |
| switch (fChild->type()) { |
| case PrecompileBase::Type::kShader: |
| return SkRuntimeEffect::ChildType::kShader; |
| case PrecompileBase::Type::kColorFilter: |
| return SkRuntimeEffect::ChildType::kColorFilter; |
| case PrecompileBase::Type::kBlender: |
| return SkRuntimeEffect::ChildType::kBlender; |
| default: |
| break; |
| } |
| } |
| return std::nullopt; |
| } |
| |
| PrecompileShader* PrecompileChildPtr::shader() const { |
| return (fChild && fChild->type() == PrecompileBase::Type::kShader) |
| ? static_cast<PrecompileShader*>(fChild.get()) |
| : nullptr; |
| } |
| |
| PrecompileColorFilter* PrecompileChildPtr::colorFilter() const { |
| return (fChild && fChild->type() == PrecompileBase::Type::kColorFilter) |
| ? static_cast<PrecompileColorFilter*>(fChild.get()) |
| : nullptr; |
| } |
| |
| PrecompileBlender* PrecompileChildPtr::blender() const { |
| return (fChild && fChild->type() == PrecompileBase::Type::kBlender) |
| ? static_cast<PrecompileBlender*>(fChild.get()) |
| : nullptr; |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| template<typename T> |
| class PrecompileRTEffect : public T { |
| public: |
| PrecompileRTEffect(sk_sp<SkRuntimeEffect> effect, |
| SkSpan<const PrecompileChildOptions> childOptions) |
| : fEffect(std::move(effect)) { |
| fChildOptions.reserve(childOptions.size()); |
| for (PrecompileChildOptions c : childOptions) { |
| fChildOptions.push_back({ c.begin(), c.end() }); |
| } |
| } |
| |
| private: |
| int numChildCombinations() const override { |
| return fChildOptions.size(); |
| } |
| |
| sk_sp<SkRuntimeEffect> fEffect; |
| std::vector<std::vector<PrecompileChildPtr>> fChildOptions; |
| }; |
| |
| sk_sp<PrecompileShader> MakePrecompileShader( |
| sk_sp<SkRuntimeEffect> effect, |
| SkSpan<const PrecompileChildOptions> childOptions) { |
| // TODO: check that 'effect' has the kAllowShader_Flag bit set and: |
| // for each entry in childOptions: |
| // all the SkPrecompileChildPtrs have the same type as the corresponding child in the effect |
| return sk_make_sp<PrecompileRTEffect<PrecompileShader>>(std::move(effect), childOptions); |
| } |
| |
| sk_sp<PrecompileColorFilter> MakePrecompileColorFilter( |
| sk_sp<SkRuntimeEffect> effect, |
| SkSpan<const PrecompileChildOptions> childOptions) { |
| // TODO: check that 'effect' has the kAllowColorFilter_Flag bit set and: |
| // for each entry in childOptions: |
| // all the SkPrecompileChildPtrs have the same type as the corresponding child in the effect |
| return sk_make_sp<PrecompileRTEffect<PrecompileColorFilter>>(std::move(effect), |
| childOptions); |
| } |
| |
| sk_sp<PrecompileBlender> MakePrecompileBlender( |
| sk_sp<SkRuntimeEffect> effect, |
| SkSpan<const PrecompileChildOptions> childOptions) { |
| // TODO: check that 'effect' has the kAllowBlender_Flag bit set and: |
| // for each entry in childOptions: |
| // all the SkPrecompileChildPtrs have the same type as the corresponding child in the effect |
| return sk_make_sp<PrecompileRTEffect<PrecompileBlender>>(std::move(effect), childOptions); |
| } |
| |
| } // namespace skgpu::graphite |
| |
| //-------------------------------------------------------------------------------------------------- |
| |
| #endif // SK_ENABLE_PRECOMPILE |