xref: /aosp_15_r20/external/skia/modules/skottie/src/effects/ThresholdEffect.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "include/core/SkData.h"
9 #include "include/core/SkRefCnt.h"
10 #include "include/core/SkString.h"
11 #include "include/effects/SkRuntimeEffect.h"
12 #include "include/private/base/SkAssert.h"
13 #include "modules/skottie/src/Adapter.h"
14 #include "modules/skottie/src/SkottiePriv.h"
15 #include "modules/skottie/src/SkottieValue.h"
16 #include "modules/skottie/src/effects/Effects.h"
17 #include "modules/sksg/include/SkSGColorFilter.h"
18 #include "modules/sksg/include/SkSGRenderNode.h"
19 
20 #include <cstddef>
21 #include <utility>
22 
23 namespace skjson {
24 class ArrayValue;
25 }
26 
27 namespace skottie::internal {
28 namespace {
29 
30 // Convert to black & white, based on input luminance and a threshold uniform.
31 static constexpr char gThresholdSkSL[] =
32     "uniform half t;"
33 
34     "half4 main(half4 color) {"
35         "half4 c = unpremul(color);"
36 
37         "half lum = dot(c.rgb, half3(0.2126, 0.7152, 0.0722)),"
38               "bw = step(t, lum);"
39 
40         "return bw.xxx1 * c.a;"
41     "}"
42 ;
43 
threshold_effect()44 static sk_sp<SkRuntimeEffect> threshold_effect() {
45     static const SkRuntimeEffect* effect =
46         SkRuntimeEffect::MakeForColorFilter(SkString(gThresholdSkSL), {}).effect.release();
47     SkASSERT(effect);
48 
49     return sk_ref_sp(effect);
50 }
51 
52 class ThresholdAdapter final : public DiscardableAdapterBase<ThresholdAdapter,
53                                                              sksg::ExternalColorFilter> {
54 public:
ThresholdAdapter(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder & abuilder)55     ThresholdAdapter(const skjson::ArrayValue& jprops,
56                      sk_sp<sksg::RenderNode> layer,
57                      const AnimationBuilder& abuilder)
58         : INHERITED(sksg::ExternalColorFilter::Make(std::move(layer)))
59     {
60         enum : size_t {
61             kLevel_Index = 0,
62         };
63 
64         EffectBinder(jprops, abuilder, this).bind(kLevel_Index, fLevel);
65     }
66 
67 private:
onSync()68     void onSync() override {
69         auto cf =
70                 threshold_effect()->makeColorFilter(SkData::MakeWithCopy(&fLevel, sizeof(fLevel)));
71 
72         this->node()->setColorFilter(std::move(cf));
73     }
74 
75     ScalarValue fLevel = 0;
76 
77     using INHERITED = DiscardableAdapterBase<ThresholdAdapter, sksg::ExternalColorFilter>;
78 };
79 
80 } // namespace
81 
attachThresholdEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const82 sk_sp<sksg::RenderNode> EffectBuilder::attachThresholdEffect(const skjson::ArrayValue& jprops,
83                                                              sk_sp<sksg::RenderNode> layer) const {
84     return fBuilder->attachDiscardableAdapter<ThresholdAdapter>(jprops,
85                                                                 std::move(layer),
86                                                                 *fBuilder);
87 }
88 
89 } // namespace skottie::internal
90