1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <scene_plugin/api/postprocess_uid.h>
16 
17 #include <3d/ecs/components/post_process_component.h>
18 #include <render/datastore/render_data_store_render_pods.h>
19 
20 #include <meta/ext/concrete_base_object.h>
21 #include <meta/interface/property/property.h>
22 
23 #include "bind_templates.inl"
24 #include "intf_postprocess_private.h"
25 #include "node_impl.h"
26 #include "task_utils.h"
27 
28 using SCENE_NS::MakeTask;
29 
30 namespace {
31 
32 class PostProcessImpl
33     : public META_NS::ObjectFwd<PostProcessImpl, SCENE_NS::ClassId::PostProcess, META_NS::ClassId::Object,
34           SCENE_NS::IPostProcess, IPostProcessPrivate, SCENE_NS::IProxyObject> {
35     META_IMPLEMENT_INTERFACE_PROPERTY(META_NS::INamed, BASE_NS::string, Name)
36     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IBloom::Ptr, Bloom)
37     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IBlur::Ptr, Blur)
38     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IColorConversion::Ptr, ColorConversion)
39     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IColorFringe::Ptr, ColorFringe)
40     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IDepthOfField::Ptr, DepthOfField)
41     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IDither::Ptr, Dither)
42     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IFxaa::Ptr, Fxaa)
43     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IMotionBlur::Ptr, MotionBlur)
44     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::ITaa::Ptr, Taa)
45     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::ITonemap::Ptr, Tonemap)
46     META_IMPLEMENT_INTERFACE_PROPERTY(SCENE_NS::IPostProcess, SCENE_NS::IVignette::Ptr, Vignette)
47 
48     static constexpr BASE_NS::string_view PP_ENABLE_FLAGS = "PostProcessComponent.enableFlags"; // uint32_t
IsBitSet(META_NS::Property<uint32_t> property,uint32_t bit)49     bool IsBitSet(META_NS::Property<uint32_t> property, uint32_t bit)
50     {
51         auto value = property->GetValue();
52         return static_cast<bool>(value& bit);
53     }
54 
SetBit(META_NS::Property<uint32_t> property,uint32_t bit,bool set)55     void SetBit(META_NS::Property<uint32_t> property, uint32_t bit, bool set)
56     {
57         auto value = property->GetValue();
58         if (set) {
59             value |= bit;
60         } else {
61             value &= ~bit;
62         }
63         property->SetValue(value);
64     }
65 
66     META_NS::PropertyChangedEventHandler handler_[11];
67 
~PostProcessImpl()68     ~PostProcessImpl()
69     {
70         SCENE_PLUGIN_VERBOSE_LOG("%s", __func__);
71     }
72 
Build(const IMetadata::Ptr & data)73     bool Build(const IMetadata::Ptr& data) override
74     {
75         auto& obr = META_NS::GetObjectRegistry();
76         if (auto bloom = obr.Create<SCENE_NS::IBloom>(SCENE_NS::ClassId::Bloom)) {
77             META_NS::SetValue(interface_cast<META_NS::INamed>(bloom)->Name(), "Bloom");
78             META_NS::SetValue(Bloom(), bloom);
79         }
80         if (auto blur = obr.Create<SCENE_NS::IBlur>(SCENE_NS::ClassId::Blur)) {
81             META_NS::SetValue(interface_cast<META_NS::INamed>(blur)->Name(), "Blur");
82             META_NS::SetValue(Blur(), blur);
83         }
84         if (auto colorConversion =
85                 obr.Create<SCENE_NS::IColorConversion>(SCENE_NS::ClassId::ColorConversion)) {
86             META_NS::SetValue(interface_cast<META_NS::INamed>(colorConversion)->Name(), "ColorConversion");
87             META_NS::SetValue(ColorConversion(), colorConversion);
88         }
89         if (auto colorFringe =
90                 obr.Create<SCENE_NS::IColorFringe>(SCENE_NS::ClassId::ColorFringe)) {
91             META_NS::SetValue(interface_cast<META_NS::INamed>(colorFringe)->Name(), "ColorFringe");
92             META_NS::SetValue(ColorFringe(), colorFringe);
93         }
94         if (auto depthOfField =
95                 obr.Create<SCENE_NS::IDepthOfField>(SCENE_NS::ClassId::DepthOfField)) {
96             META_NS::SetValue(interface_cast<META_NS::INamed>(depthOfField)->Name(), "DepthOfField");
97             META_NS::SetValue(DepthOfField(), depthOfField);
98         }
99         if (auto dither = obr.Create<SCENE_NS::IDither>(SCENE_NS::ClassId::Dither)) {
100             META_NS::SetValue(interface_cast<META_NS::INamed>(dither)->Name(), "Dither");
101             META_NS::SetValue(Dither(), dither);
102         }
103         if (auto fxaaSettings = obr.Create<SCENE_NS::IFxaa>(SCENE_NS::ClassId::Fxaa)) {
104             META_NS::SetValue(interface_cast<META_NS::INamed>(fxaaSettings)->Name(), "Fxaa");
105             META_NS::SetValue(Fxaa(), fxaaSettings);
106         }
107         if (auto blur = obr.Create<SCENE_NS::IMotionBlur>(SCENE_NS::ClassId::MotionBlur)) {
108             META_NS::SetValue(interface_cast<META_NS::INamed>(blur)->Name(), "MotionBlur");
109             META_NS::SetValue(MotionBlur(), blur);
110         }
111         if (auto taaSettings = obr.Create<SCENE_NS::ITaa>(SCENE_NS::ClassId::Taa)) {
112             META_NS::SetValue(interface_cast<META_NS::INamed>(taaSettings)->Name(), "Taa");
113             META_NS::SetValue(Taa(), taaSettings);
114         }
115         if (auto tonemap = obr.Create<SCENE_NS::ITonemap>(SCENE_NS::ClassId::Tonemap)) {
116             META_NS::SetValue(interface_cast<META_NS::INamed>(tonemap)->Name(), "Tonemap");
117             META_NS::SetValue(Tonemap(), tonemap);
118         }
119         if (auto vignette = obr.Create<SCENE_NS::IVignette>(SCENE_NS::ClassId::Vignette)) {
120             META_NS::SetValue(interface_cast<META_NS::INamed>(vignette)->Name(), "Vignette");
121             META_NS::SetValue(Vignette(), vignette);
122         }
123 
124         if (auto meta = GetSelf<META_NS::IMetadata>()) {
125             for (auto& prop : meta->GetAllProperties()) {
126                 auto name = prop->GetName();
127 
128                 if (auto iptr = interface_cast<IPostProcessEffectPrivate>(GetPointer(prop))) {
129                     META_NS::PropertyLock p(prop);
130                     p->OnChanged()->AddHandler(
131                         META_NS::MakeCallback<META_NS::IOnChanged>(
132                             [this, weak = BASE_NS::weak_ptr(prop)]() {
133                                 if (auto intPtr = weak.lock()) {
134                                     if (auto valueObject =
135                                             interface_cast<IPostProcessEffectPrivate>(GetPointer(intPtr))) {
136                                         // prefer values from toolkit
137                                         valueObject->Bind(ecsObject_, sh_, false);
138                                     }
139                                 }
140                             }),
141                         reinterpret_cast<uint64_t>(this)
142                     );
143                 }
144             }
145         }
146 
147         return true;
148     }
149 
GetEntity()150     CORE_NS::Entity GetEntity() override
151     {
152         if (ecsObject_) {
153             return ecsObject_->GetEntity();
154         }
155         return {};
156     }
157     // In principle, this implementation should be splitted to two parts which run the introspection
158     // first on ecs queue and then bind the metaproperties on toolkit side
SetEntity(CORE_NS::Entity entity,SceneHolder::Ptr sh,bool preferEcsValues)159     void SetEntity(CORE_NS::Entity entity, SceneHolder::Ptr sh, bool preferEcsValues) override
160     {
161         if (ecsObject_ && ecsObject_->GetEntity() == entity) {
162             return;
163         }
164 
165         ecsObject_ = META_NS::GetObjectRegistry().Create<SCENE_NS::IEcsObject>(SCENE_NS::ClassId::EcsObject);
166         sh_ = sh;
167 
168         if (auto proxyIf = interface_pointer_cast<SCENE_NS::IEcsProxyObject>(ecsObject_)) {
169             proxyIf->SetCommonListener(sh->GetCommonEcsListener());
170         }
171 
172         auto ecs = sh->GetEcs();
173         ecsObject_->SetEntity(ecs, ecs->GetEntityManager().GetReferenceCounted(entity));
174 
175         if (auto tonemap = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(Tonemap()))) {
176             tonemap->Bind(ecsObject_, sh, preferEcsValues);
177         }
178         if (auto bloom = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(Bloom()))) {
179             bloom->Bind(ecsObject_, sh, preferEcsValues);
180         }
181         if (auto vignette = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(Vignette()))) {
182             vignette->Bind(ecsObject_, sh, preferEcsValues);
183         }
184         if (auto colorFringe = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(ColorFringe()))) {
185             colorFringe->Bind(ecsObject_, sh, preferEcsValues);
186         }
187         if (auto dither = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(Dither()))) {
188             dither->Bind(ecsObject_, sh, preferEcsValues);
189         }
190         if (auto fxaa = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(Fxaa()))) {
191             fxaa->Bind(ecsObject_, sh, preferEcsValues);
192         }
193         if (auto taa = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(Taa()))) {
194             taa->Bind(ecsObject_, sh, preferEcsValues);
195         }
196         if (auto dof = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(DepthOfField()))) {
197             dof->Bind(ecsObject_, sh, preferEcsValues);
198         }
199         if (auto mb = interface_cast<IPostProcessEffectPrivate>(META_NS::GetValue(MotionBlur()))) {
200             mb->Bind(ecsObject_, sh, preferEcsValues);
201         }
202         propHandler_.Reset();
203 
204         propHandler_.SetUseEcsDefaults(preferEcsValues);
205 
206         auto meta = interface_pointer_cast<META_NS::IMetadata>(ecsObject_);
207         if (!meta) {
208             return;
209         }
210 
211         auto postState = meta->GetPropertyByName(PP_ENABLE_FLAGS);
212         if (!postState) {
213             return;
214         }
215         using namespace META_NS;
216         using namespace CORE3D_NS;
217 
218         auto func = [](PostProcessImpl* me, IProperty::Ptr fxState, IProperty::Ptr postprocessState, uint32_t bit) {
219             bool enabled = false;
220             if (fxState) {
221                 fxState->GetValue().GetValue<bool>(enabled);
222             }
223             auto val = me->currentEnabled;
224             if (enabled) {
225                 val |= bit;
226             } else {
227                 val &= ~bit;
228             }
229             if (val != me->currentEnabled) {
230                 me->currentEnabled = val;
231                 META_NS::Property<uint32_t> pps(postprocessState);
232                 pps->SetValue(me->currentEnabled);
233             }
234         };
235 #define ADD_HANDLER(Fx, Bit) \
236     { \
237         auto prop = Fx()->GetValue()->Enabled().GetProperty(); \
238         handler_[idx++].Subscribe(prop, \
239             MakeCallback<IOnChanged>(func, this, prop, postState, static_cast<uint32_t>(Bit))); \
240         func(this, prop, postState, static_cast<uint32_t>(Bit)); \
241     }
242         uint32_t idx = 0;
243         ADD_HANDLER(Bloom, PostProcessComponent::BLOOM_BIT);
244         ADD_HANDLER(Blur, PostProcessComponent::BLUR_BIT);
245         ADD_HANDLER(ColorConversion, PostProcessComponent::COLOR_CONVERSION_BIT);
246         ADD_HANDLER(ColorFringe, PostProcessComponent::COLOR_FRINGE_BIT);
247         ADD_HANDLER(DepthOfField, PostProcessComponent::DOF_BIT);
248         ADD_HANDLER(Dither, PostProcessComponent::DITHER_BIT);
249         ADD_HANDLER(Fxaa, PostProcessComponent::FXAA_BIT);
250         ADD_HANDLER(MotionBlur, PostProcessComponent::MOTION_BLUR_BIT);
251         ADD_HANDLER(Taa, PostProcessComponent::TAA_BIT);
252         ADD_HANDLER(Tonemap, PostProcessComponent::TONEMAP_BIT);
253         ADD_HANDLER(Vignette, PostProcessComponent::VIGNETTE_BIT);
254     }
255 
ListBoundProperties() const256     BASE_NS::vector<SCENE_NS::IProxyObject::PropertyPair> ListBoundProperties() const override
257     {
258         return propHandler_.GetBoundProperties();
259     }
260 
261     uint32_t currentEnabled { 0 };
262     SCENE_NS::IEcsObject::Ptr ecsObject_;
263     SceneHolder::Ptr sh_;
264     PropertyHandlerArrayHolder propHandler_ {};
265 };
266 
267 } // namespace
268 
SCENE_BEGIN_NAMESPACE()269 SCENE_BEGIN_NAMESPACE()
270 
271 void RegisterPostprocessImpl()
272 {
273     auto& registry = META_NS::GetObjectRegistry();
274     registry.RegisterObjectType<PostProcessImpl>();
275 }
276 
UnregisterPostprocessImpl()277 void UnregisterPostprocessImpl()
278 {
279     auto& registry = META_NS::GetObjectRegistry();
280     registry.UnregisterObjectType<PostProcessImpl>();
281 }
282 
283 SCENE_END_NAMESPACE()
284