1/* 2 * Copyright 2021 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "modules/skottie/src/effects/Effects.h" 9 10#include "include/effects/SkRuntimeEffect.h" 11#include "modules/skottie/src/Adapter.h" 12#include "modules/skottie/src/SkottieJson.h" 13#include "modules/skottie/src/SkottieValue.h" 14#include "modules/sksg/include/SkSGColorFilter.h" 15 16namespace skottie::internal { 17 18#ifdef SK_ENABLE_SKSL 19 20namespace { 21 22// Convert to black & white, based on input luminance and a threshold uniform. 23static constexpr char gThresholdSkSL[] = R"( 24 uniform half t; 25 26 half4 main(half4 color) { 27 half4 c = unpremul(color); 28 29 half lum = dot(c.rgb, half3(0.2126, 0.7152, 0.0722)), 30 bw = step(t, lum); 31 32 return bw.xxx1 * c.a; 33 } 34)"; 35 36static sk_sp<SkRuntimeEffect> threshold_effect() { 37 static const SkRuntimeEffect* effect = 38 SkRuntimeEffect::MakeForColorFilter(SkString(gThresholdSkSL), {}).effect.release(); 39 SkASSERT(effect); 40 41 return sk_ref_sp(effect); 42} 43 44class ThresholdAdapter final : public DiscardableAdapterBase<ThresholdAdapter, 45 sksg::ExternalColorFilter> { 46public: 47 ThresholdAdapter(const skjson::ArrayValue& jprops, 48 sk_sp<sksg::RenderNode> layer, 49 const AnimationBuilder& abuilder) 50 : INHERITED(sksg::ExternalColorFilter::Make(std::move(layer))) 51 { 52 enum : size_t { 53 kLevel_Index = 0, 54 }; 55 56 EffectBinder(jprops, abuilder, this).bind(kLevel_Index, fLevel); 57 } 58 59private: 60 void onSync() override { 61 auto cf = 62 threshold_effect()->makeColorFilter(SkData::MakeWithCopy(&fLevel, sizeof(fLevel))); 63 64 this->node()->setColorFilter(std::move(cf)); 65 } 66 67 ScalarValue fLevel = 0; 68 69 using INHERITED = DiscardableAdapterBase<ThresholdAdapter, sksg::ExternalColorFilter>; 70}; 71 72} // namespace 73 74#endif // SK_ENABLE_SKSL 75 76sk_sp<sksg::RenderNode> EffectBuilder::attachThresholdEffect(const skjson::ArrayValue& jprops, 77 sk_sp<sksg::RenderNode> layer) const { 78#ifdef SK_ENABLE_SKSL 79 return fBuilder->attachDiscardableAdapter<ThresholdAdapter>(jprops, 80 std::move(layer), 81 *fBuilder); 82#else 83 // TODO(skia:12197) 84 return layer; 85#endif 86} 87 88} // namespace skottie::internal 89