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