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