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 "ToneMapJS.h"
16
17 #include <meta/api/make_callback.h>
18 #include <meta/interface/intf_task_queue.h>
19 #include <meta/interface/intf_task_queue_registry.h>
20 #include <meta/interface/property/property_events.h>
21 #include <scene_plugin/api/camera.h> //for the classid...
22 #include <scene_plugin/api/node_uid.h>
23 #include <scene_plugin/interface/intf_ecs_scene.h>
24 #include <scene_plugin/interface/intf_node.h>
25 #include <scene_plugin/interface/intf_postprocess.h>
26 #include <scene_plugin/interface/intf_scene.h>
27
28 #include <render/intf_render_context.h>
29
30 #include "PostProcJS.h"
31 using IntfPtr = BASE_NS::shared_ptr<CORE_NS::IInterface>;
32 using IntfWeakPtr = BASE_NS::weak_ptr<CORE_NS::IInterface>;
33 using namespace SCENE_NS;
ConvertTo(ToneMapJS::ToneMappingType typeI)34 SCENE_NS::ITonemap::TonemapType ConvertTo(ToneMapJS::ToneMappingType typeI)
35 {
36 SCENE_NS::ITonemap::TonemapType type;
37 switch (typeI) {
38 case ToneMapJS::ToneMappingType::ACES:
39 type = SCENE_NS::ITonemap::TonemapType::ACES;
40 break;
41 case ToneMapJS::ToneMappingType::ACES_2020:
42 type = SCENE_NS::ITonemap::TonemapType::ACES_2020;
43 break;
44 case ToneMapJS::ToneMappingType::FILMIC:
45 type = SCENE_NS::ITonemap::TonemapType::FILMIC;
46 break;
47 default:
48 // default from lowlev..
49 type = ITonemap::TonemapType::ACES;
50 break;
51 }
52 return type;
53 }
ConvertFrom(SCENE_NS::ITonemap::TonemapType typeI)54 ToneMapJS::ToneMappingType ConvertFrom(SCENE_NS::ITonemap::TonemapType typeI)
55 {
56 ToneMapJS::ToneMappingType type;
57 switch (typeI) {
58 case SCENE_NS::ITonemap::TonemapType::ACES:
59 type = ToneMapJS::ToneMappingType::ACES;
60 break;
61 case SCENE_NS::ITonemap::TonemapType::ACES_2020:
62 type = ToneMapJS::ToneMappingType::ACES_2020;
63 break;
64 case SCENE_NS::ITonemap::TonemapType::FILMIC:
65 type = ToneMapJS::ToneMappingType ::FILMIC;
66 break;
67 default:
68 // default from lowlev..
69 type = ToneMapJS::ToneMappingType ::ACES;
70 break;
71 }
72 return type;
73 }
74
ConvertTo(uint32_t typeI)75 SCENE_NS::ITonemap::TonemapType ConvertTo(uint32_t typeI)
76 {
77 return ConvertTo(static_cast<ToneMapJS::ToneMappingType>(typeI));
78 }
Init(napi_env env,napi_value exports)79 void ToneMapJS::Init(napi_env env, napi_value exports)
80 {
81 using namespace NapiApi;
82
83 BASE_NS::vector<napi_property_descriptor> node_props;
84 // clang-format off
85 node_props.emplace_back(GetSetProperty<uint32_t, ToneMapJS, &ToneMapJS::GetType, &ToneMapJS::SetType>("type"));
86 node_props.emplace_back(GetSetProperty<float, ToneMapJS, &ToneMapJS::GetExposure,
87 &ToneMapJS::SetExposure>("exposure"));
88 node_props.push_back(MakeTROMethod<NapiApi::FunctionContext<>, ToneMapJS, &ToneMapJS::Dispose>("destroy"));
89 // clang-format on
90
91 napi_value func;
92 auto status = napi_define_class(env, "ToneMappingSettings", NAPI_AUTO_LENGTH, BaseObject::ctor<ToneMapJS>(),
93 nullptr, node_props.size(), node_props.data(), &func);
94
95 NapiApi::MyInstanceState* mis;
96 napi_get_instance_data(env, (void**)&mis);
97 mis->StoreCtor("ToneMappingSettings", func);
98
99 NapiApi::Object exp(env, exports);
100
101 napi_value eType;
102 napi_value v;
103 napi_create_object(env, &eType);
104 #define DECL_ENUM(enu, x) \
105 napi_create_uint32(env, ToneMappingType::x, &v); \
106 napi_set_named_property(env, enu, #x, v);
107
108 DECL_ENUM(eType, ACES);
109 DECL_ENUM(eType, ACES_2020);
110 DECL_ENUM(eType, FILMIC);
111 #undef DECL_ENUM
112 exp.Set("ToneMappingType", eType);
113 }
114
Dispose(NapiApi::FunctionContext<> & ctx)115 napi_value ToneMapJS::Dispose(NapiApi::FunctionContext<>& ctx)
116 {
117 LOG_F("ToneMapJS::Dispose");
118 DisposeNative();
119 return {};
120 }
DisposeNative()121 void ToneMapJS::DisposeNative()
122 {
123 if (!disposed_) {
124 disposed_ = true;
125 LOG_F("ToneMapJS::DisposeNative");
126 if (auto tmp = interface_pointer_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
127 // reset the native object refs
128 SetNativeObject(nullptr, false);
129 SetNativeObject(nullptr, true);
130
131 ExecSyncTask([scn = BASE_NS::move(tmp)]() { return META_NS::IAny::Ptr {}; });
132 }
133 }
134 }
GetInstanceImpl(uint32_t id)135 void* ToneMapJS::GetInstanceImpl(uint32_t id)
136 {
137 if (id == ToneMapJS::ID) {
138 return this;
139 }
140 return nullptr;
141 }
Finalize(napi_env env)142 void ToneMapJS::Finalize(napi_env env)
143 {
144 // hmm.. do i need to do something BEFORE the object gets deleted..
145 DisposeNative();
146 BaseObject<ToneMapJS>::Finalize(env);
147 }
148
ToneMapJS(napi_env e,napi_callback_info i)149 ToneMapJS::ToneMapJS(napi_env e, napi_callback_info i) : BaseObject<ToneMapJS>(e, i)
150 {
151 LOG_F("ToneMapJS ++");
152 NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
153 if (!fromJs) {
154 // no arguments. so internal create.
155 // expecting caller to finish
156 return;
157 }
158 // postprocess that we bind to..
159 NapiApi::Object postProcJS = fromJs.Arg<0>();
160 auto postproc = GetNativeMeta<SCENE_NS::IPostProcess>(postProcJS);
161 NapiApi::Object toneMapArgs = fromJs.Arg<1>();
162 // now, based on parameters, initialize the object
163 // so it is a tonemap
164 float exposure = toneMapArgs.Get<float>("exposure").valueOrDefault(0.7);
165 SCENE_NS::ITonemap::TonemapType type =
166 ConvertTo(toneMapArgs.Get<uint32_t>("type").valueOrDefault(ToneMappingType::ACES));
167
168 auto tonemap = GetNativeObjectParam<SCENE_NS::ITonemap>(toneMapArgs);
169
170 ExecSyncTask([&tonemap, exposure, type, postproc]() -> META_NS::IAny::Ptr {
171 if (!tonemap) {
172 tonemap = META_NS::GetObjectRegistry().Create<SCENE_NS::ITonemap>(SCENE_NS::ClassId::Tonemap);
173 }
174 tonemap->Type()->SetValue(type);
175 tonemap->Exposure()->SetValue(exposure);
176 tonemap->Enabled()->SetValue(true);
177 postproc->Tonemap()->SetValue(tonemap);
178 return {};
179 });
180 auto obj = interface_pointer_cast<META_NS::IObject>(tonemap);
181 // process constructor args..
182 NapiApi::Object meJs(e, fromJs.This());
183 // weak ref, due to the ToneMap class being owned by the postprocess.
184 SetNativeObject(obj, false);
185 StoreJsObj(obj, meJs);
186 }
187
~ToneMapJS()188 ToneMapJS::~ToneMapJS()
189 {
190 LOG_F("ToneMapJS --");
191 DisposeNative();
192 if (!GetNativeObject()) {
193 return;
194 }
195 }
196
GetType(NapiApi::FunctionContext<> & ctx)197 napi_value ToneMapJS::GetType(NapiApi::FunctionContext<>& ctx)
198 {
199 SCENE_NS::ITonemap::TonemapType type = SCENE_NS::ITonemap::TonemapType::ACES; // default
200 if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
201 ExecSyncTask([toneMap, &type]() {
202 type = toneMap->Type()->GetValue();
203 return META_NS::IAny::Ptr {};
204 });
205 }
206
207 auto typeI = ConvertFrom(type);
208 napi_value value;
209 napi_status status = napi_create_uint32(ctx, static_cast<uint32_t>(typeI), &value);
210 return value;
211 }
SetType(NapiApi::FunctionContext<uint32_t> & ctx)212 void ToneMapJS::SetType(NapiApi::FunctionContext<uint32_t>& ctx)
213 {
214 auto type = ConvertTo(ctx.Arg<0>());
215
216 if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
217 ExecSyncTask([toneMap, type]() {
218 toneMap->Type()->SetValue(type);
219 return META_NS::IAny::Ptr {};
220 });
221 }
222 }
223
GetExposure(NapiApi::FunctionContext<> & ctx)224 napi_value ToneMapJS::GetExposure(NapiApi::FunctionContext<>& ctx)
225 {
226 float exp = 0.0;
227 if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
228 ExecSyncTask([toneMap, &exp]() {
229 exp = toneMap->Exposure()->GetValue();
230 return META_NS::IAny::Ptr {};
231 });
232 }
233
234 napi_value value;
235 napi_status status = napi_create_double(ctx, exp, &value);
236 return value;
237 }
238
SetExposure(NapiApi::FunctionContext<float> & ctx)239 void ToneMapJS::SetExposure(NapiApi::FunctionContext<float>& ctx)
240 {
241 float exp = ctx.Arg<0>();
242 if (auto toneMap = interface_cast<SCENE_NS::ITonemap>(GetNativeObject())) {
243 ExecSyncTask([toneMap, exp]() {
244 toneMap->Exposure()->SetValue(exp);
245 return META_NS::IAny::Ptr {};
246 });
247 }
248 }
249