18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (C) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#include "PostProcJS.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <meta/api/make_callback.h> 198bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue.h> 208bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue_registry.h> 218bf80f4bSopenharmony_ci#include <meta/interface/property/property_events.h> 228bf80f4bSopenharmony_ci#include <scene_plugin/api/camera.h> //for the classid... 238bf80f4bSopenharmony_ci#include <scene_plugin/api/node_uid.h> 248bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_ecs_scene.h> 258bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_node.h> 268bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_scene.h> 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_ci#include <render/intf_render_context.h> 298bf80f4bSopenharmony_ci 308bf80f4bSopenharmony_ci#include "CameraJS.h" 318bf80f4bSopenharmony_ciusing IntfPtr = BASE_NS::shared_ptr<CORE_NS::IInterface>; 328bf80f4bSopenharmony_ciusing IntfWeakPtr = BASE_NS::weak_ptr<CORE_NS::IInterface>; 338bf80f4bSopenharmony_ciusing namespace SCENE_NS; 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_civoid PostProcJS::Init(napi_env env, napi_value exports) 368bf80f4bSopenharmony_ci{ 378bf80f4bSopenharmony_ci using namespace NapiApi; 388bf80f4bSopenharmony_ci 398bf80f4bSopenharmony_ci BASE_NS::vector<napi_property_descriptor> node_props; 408bf80f4bSopenharmony_ci // clang-format off 418bf80f4bSopenharmony_ci 428bf80f4bSopenharmony_ci node_props.push_back(GetSetProperty<bool, PostProcJS, &PostProcJS::GetBloom, &PostProcJS::SetBloom>("bloom")); 438bf80f4bSopenharmony_ci node_props.emplace_back(GetSetProperty<Object, PostProcJS, &PostProcJS::GetToneMapping, 448bf80f4bSopenharmony_ci &PostProcJS::SetToneMapping>("toneMapping")); 458bf80f4bSopenharmony_ci node_props.push_back(MakeTROMethod<NapiApi::FunctionContext<>, PostProcJS, &PostProcJS::Dispose>("destroy")); 468bf80f4bSopenharmony_ci 478bf80f4bSopenharmony_ci // clang-format on 488bf80f4bSopenharmony_ci 498bf80f4bSopenharmony_ci napi_value func; 508bf80f4bSopenharmony_ci auto status = napi_define_class(env, "PostProcessSettings", NAPI_AUTO_LENGTH, BaseObject::ctor<PostProcJS>(), 518bf80f4bSopenharmony_ci nullptr, node_props.size(), node_props.data(), &func); 528bf80f4bSopenharmony_ci 538bf80f4bSopenharmony_ci NapiApi::MyInstanceState* mis; 548bf80f4bSopenharmony_ci napi_get_instance_data(env, (void**)&mis); 558bf80f4bSopenharmony_ci mis->StoreCtor("PostProcessSettings", func); 568bf80f4bSopenharmony_ci} 578bf80f4bSopenharmony_ci 588bf80f4bSopenharmony_cinapi_value PostProcJS::Dispose(NapiApi::FunctionContext<>& ctx) 598bf80f4bSopenharmony_ci{ 608bf80f4bSopenharmony_ci LOG_F("PostProcJS::Dispose"); 618bf80f4bSopenharmony_ci DisposeNative(); 628bf80f4bSopenharmony_ci return {}; 638bf80f4bSopenharmony_ci} 648bf80f4bSopenharmony_civoid PostProcJS::DisposeNative() 658bf80f4bSopenharmony_ci{ 668bf80f4bSopenharmony_ci if (!disposed_) { 678bf80f4bSopenharmony_ci disposed_ = true; 688bf80f4bSopenharmony_ci LOG_F("PostProcJS::DisposeNative"); 698bf80f4bSopenharmony_ci // make sure we release toneMap settings 708bf80f4bSopenharmony_ci 718bf80f4bSopenharmony_ci auto tmjs = toneMap_.GetObject(); 728bf80f4bSopenharmony_ci if (tmjs) { 738bf80f4bSopenharmony_ci NapiApi::Function func = tmjs.Get<NapiApi::Function>("destroy"); 748bf80f4bSopenharmony_ci if (func) { 758bf80f4bSopenharmony_ci func.Invoke(tmjs); 768bf80f4bSopenharmony_ci } 778bf80f4bSopenharmony_ci } 788bf80f4bSopenharmony_ci toneMap_.Reset(); 798bf80f4bSopenharmony_ci 808bf80f4bSopenharmony_ci if (auto post = interface_pointer_cast<IPostProcess>(GetNativeObject())) { 818bf80f4bSopenharmony_ci // reset the native object refs 828bf80f4bSopenharmony_ci SetNativeObject(nullptr, false); 838bf80f4bSopenharmony_ci SetNativeObject(nullptr, true); 848bf80f4bSopenharmony_ci 858bf80f4bSopenharmony_ci auto cameraJS = camera_.GetObject(); 868bf80f4bSopenharmony_ci if (cameraJS) { 878bf80f4bSopenharmony_ci auto* rootobject = cameraJS.Native<TrueRootObject>(); 888bf80f4bSopenharmony_ci CameraJS* cam = (CameraJS*)(rootobject); 898bf80f4bSopenharmony_ci 908bf80f4bSopenharmony_ci ExecSyncTask([cam, post = BASE_NS::move(post)]() { 918bf80f4bSopenharmony_ci cam->ReleaseObject(META_NS::interface_pointer_cast<META_NS::IObject>(post)); 928bf80f4bSopenharmony_ci post->Tonemap()->SetValue(nullptr); 938bf80f4bSopenharmony_ci return META_NS::IAny::Ptr {}; 948bf80f4bSopenharmony_ci }); 958bf80f4bSopenharmony_ci } 968bf80f4bSopenharmony_ci } 978bf80f4bSopenharmony_ci } 988bf80f4bSopenharmony_ci} 998bf80f4bSopenharmony_civoid* PostProcJS::GetInstanceImpl(uint32_t id) 1008bf80f4bSopenharmony_ci{ 1018bf80f4bSopenharmony_ci if (id == PostProcJS::ID) { 1028bf80f4bSopenharmony_ci return this; 1038bf80f4bSopenharmony_ci } 1048bf80f4bSopenharmony_ci return nullptr; 1058bf80f4bSopenharmony_ci} 1068bf80f4bSopenharmony_civoid PostProcJS::Finalize(napi_env env) 1078bf80f4bSopenharmony_ci{ 1088bf80f4bSopenharmony_ci // need to do something BEFORE the object gets deleted.. 1098bf80f4bSopenharmony_ci DisposeNative(); 1108bf80f4bSopenharmony_ci BaseObject<PostProcJS>::Finalize(env); 1118bf80f4bSopenharmony_ci} 1128bf80f4bSopenharmony_ci 1138bf80f4bSopenharmony_ciPostProcJS::PostProcJS(napi_env e, napi_callback_info i) : BaseObject<PostProcJS>(e, i) 1148bf80f4bSopenharmony_ci{ 1158bf80f4bSopenharmony_ci LOG_F("PostProcJS ++"); 1168bf80f4bSopenharmony_ci NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i); 1178bf80f4bSopenharmony_ci if (!fromJs) { 1188bf80f4bSopenharmony_ci // no arguments. so internal create. 1198bf80f4bSopenharmony_ci // expecting caller to finish 1208bf80f4bSopenharmony_ci return; 1218bf80f4bSopenharmony_ci } 1228bf80f4bSopenharmony_ci 1238bf80f4bSopenharmony_ci // camera that we bind to.. 1248bf80f4bSopenharmony_ci NapiApi::Object cameraJS = fromJs.Arg<0>(); 1258bf80f4bSopenharmony_ci camera_ = { cameraJS }; 1268bf80f4bSopenharmony_ci auto* rootobject = cameraJS.Native<TrueRootObject>(); 1278bf80f4bSopenharmony_ci auto postproc = interface_pointer_cast<SCENE_NS::IPostProcess>( 1288bf80f4bSopenharmony_ci ((CameraJS*)(rootobject))->CreateObject(SCENE_NS::ClassId::PostProcess)); 1298bf80f4bSopenharmony_ci 1308bf80f4bSopenharmony_ci // create a postprocess object owned by CameraJS. 1318bf80f4bSopenharmony_ci 1328bf80f4bSopenharmony_ci // process constructor args.. 1338bf80f4bSopenharmony_ci NapiApi::Object meJs(e, fromJs.This()); 1348bf80f4bSopenharmony_ci // weak ref, as we expect to be owned by the camera. 1358bf80f4bSopenharmony_ci SetNativeObject(interface_pointer_cast<META_NS::IObject>(postproc), false); 1368bf80f4bSopenharmony_ci StoreJsObj(interface_pointer_cast<META_NS::IObject>(postproc), meJs); 1378bf80f4bSopenharmony_ci // now, based on parameters, create correct objects. 1388bf80f4bSopenharmony_ci if (NapiApi::Object args = fromJs.Arg<1>()) { 1398bf80f4bSopenharmony_ci if (auto prm = args.Get("toneMapping")) { 1408bf80f4bSopenharmony_ci // enable tonemap. 1418bf80f4bSopenharmony_ci napi_value args[] = { 1428bf80f4bSopenharmony_ci meJs, // postprocess 1438bf80f4bSopenharmony_ci prm // tonemap settings 1448bf80f4bSopenharmony_ci }; 1458bf80f4bSopenharmony_ci SCENE_NS::ITonemap::Ptr tone; 1468bf80f4bSopenharmony_ci ExecSyncTask([postproc, &tone]() { 1478bf80f4bSopenharmony_ci tone = postproc->Tonemap()->GetValue(); 1488bf80f4bSopenharmony_ci return META_NS::IAny::Ptr {}; 1498bf80f4bSopenharmony_ci }); 1508bf80f4bSopenharmony_ci MakeNativeObjectParam(e, tone, BASE_NS::countof(args), args); 1518bf80f4bSopenharmony_ci NapiApi::Object tonemapJS(GetJSConstructor(e, "ToneMappingSettings"), BASE_NS::countof(args), args); 1528bf80f4bSopenharmony_ci meJs.Set("toneMapping", tonemapJS); 1538bf80f4bSopenharmony_ci } 1548bf80f4bSopenharmony_ci if (auto prm = args.Get("bloom")) { 1558bf80f4bSopenharmony_ci ExecSyncTask([postproc]() -> META_NS::IAny::Ptr { 1568bf80f4bSopenharmony_ci SCENE_NS::IBloom::Ptr bloom = postproc->Bloom()->GetValue(); 1578bf80f4bSopenharmony_ci bloom->Enabled()->SetValue(true); 1588bf80f4bSopenharmony_ci return {}; 1598bf80f4bSopenharmony_ci }); 1608bf80f4bSopenharmony_ci } 1618bf80f4bSopenharmony_ci } 1628bf80f4bSopenharmony_ci} 1638bf80f4bSopenharmony_ci 1648bf80f4bSopenharmony_ciPostProcJS::~PostProcJS() 1658bf80f4bSopenharmony_ci{ 1668bf80f4bSopenharmony_ci LOG_F("PostProcJS --"); 1678bf80f4bSopenharmony_ci DisposeNative(); 1688bf80f4bSopenharmony_ci if (!GetNativeObject()) { 1698bf80f4bSopenharmony_ci return; 1708bf80f4bSopenharmony_ci } 1718bf80f4bSopenharmony_ci} 1728bf80f4bSopenharmony_ci 1738bf80f4bSopenharmony_civoid PostProcJS::SetToneMapping(NapiApi::FunctionContext<NapiApi::Object>& ctx) 1748bf80f4bSopenharmony_ci{ 1758bf80f4bSopenharmony_ci auto postproc = interface_cast<SCENE_NS::IPostProcess>(GetNativeObject()); 1768bf80f4bSopenharmony_ci if (!postproc) { 1778bf80f4bSopenharmony_ci // not possible. 1788bf80f4bSopenharmony_ci return; 1798bf80f4bSopenharmony_ci } 1808bf80f4bSopenharmony_ci NapiApi::Object tonemapJS = ctx.Arg<0>(); 1818bf80f4bSopenharmony_ci 1828bf80f4bSopenharmony_ci if (auto currentlySet = toneMap_.GetObject()) { 1838bf80f4bSopenharmony_ci if ((napi_value)currentlySet == (napi_value)tonemapJS) { 1848bf80f4bSopenharmony_ci // setting the exactly the same tonemap setting. do nothing. 1858bf80f4bSopenharmony_ci return; 1868bf80f4bSopenharmony_ci } 1878bf80f4bSopenharmony_ci // dispose the old bound object.. 1888bf80f4bSopenharmony_ci NapiApi::Function func = currentlySet.Get<NapiApi::Function>("destroy"); 1898bf80f4bSopenharmony_ci if (func) { 1908bf80f4bSopenharmony_ci func.Invoke(currentlySet); 1918bf80f4bSopenharmony_ci } 1928bf80f4bSopenharmony_ci toneMap_.Reset(); 1938bf80f4bSopenharmony_ci } 1948bf80f4bSopenharmony_ci 1958bf80f4bSopenharmony_ci TrueRootObject* native { nullptr }; 1968bf80f4bSopenharmony_ci SCENE_NS::ITonemap::Ptr tonemap; 1978bf80f4bSopenharmony_ci // does the input parameter already have a bridge.. 1988bf80f4bSopenharmony_ci native = tonemapJS.Native<TrueRootObject>(); 1998bf80f4bSopenharmony_ci if (!native) { 2008bf80f4bSopenharmony_ci // nope.. so create a new bridge object based on the input. 2018bf80f4bSopenharmony_ci napi_value args[] = { 2028bf80f4bSopenharmony_ci ctx.This(), // postproc.. 2038bf80f4bSopenharmony_ci ctx.Arg<0>() // "javascript object for values" 2048bf80f4bSopenharmony_ci }; 2058bf80f4bSopenharmony_ci NapiApi::Object res(GetJSConstructor(ctx, "ToneMappingSettings"), BASE_NS::countof(args), args); 2068bf80f4bSopenharmony_ci native = res.Native<TrueRootObject>(); 2078bf80f4bSopenharmony_ci tonemapJS = res; 2088bf80f4bSopenharmony_ci } else { 2098bf80f4bSopenharmony_ci tonemap = interface_pointer_cast<SCENE_NS::ITonemap>(native->GetNativeObject()); 2108bf80f4bSopenharmony_ci ExecSyncTask([postproc, tonemap]() { 2118bf80f4bSopenharmony_ci postproc->Tonemap()->SetValue(tonemap); 2128bf80f4bSopenharmony_ci return META_NS::IAny::Ptr {}; 2138bf80f4bSopenharmony_ci }); 2148bf80f4bSopenharmony_ci } 2158bf80f4bSopenharmony_ci toneMap_ = { ctx, tonemapJS }; // take ownership of the object. 2168bf80f4bSopenharmony_ci} 2178bf80f4bSopenharmony_ci 2188bf80f4bSopenharmony_cinapi_value PostProcJS::GetToneMapping(NapiApi::FunctionContext<>& ctx) 2198bf80f4bSopenharmony_ci{ 2208bf80f4bSopenharmony_ci if (auto postproc = interface_cast<SCENE_NS::IPostProcess>(GetNativeObject())) { 2218bf80f4bSopenharmony_ci SCENE_NS::ITonemap::Ptr tone; 2228bf80f4bSopenharmony_ci ExecSyncTask([postproc, &tone]() { 2238bf80f4bSopenharmony_ci tone = postproc->Tonemap()->GetValue(); 2248bf80f4bSopenharmony_ci return META_NS::IAny::Ptr {}; 2258bf80f4bSopenharmony_ci }); 2268bf80f4bSopenharmony_ci auto obj = interface_pointer_cast<META_NS::IObject>(tone); 2278bf80f4bSopenharmony_ci 2288bf80f4bSopenharmony_ci if (auto cached = FetchJsObj(obj)) { 2298bf80f4bSopenharmony_ci // always return the same js object. 2308bf80f4bSopenharmony_ci return cached; 2318bf80f4bSopenharmony_ci } 2328bf80f4bSopenharmony_ci 2338bf80f4bSopenharmony_ci napi_value args[] = { 2348bf80f4bSopenharmony_ci ctx.This() // postproc.. 2358bf80f4bSopenharmony_ci }; 2368bf80f4bSopenharmony_ci MakeNativeObjectParam(ctx, tone, BASE_NS::countof(args), args); 2378bf80f4bSopenharmony_ci napi_value tonemapJS = CreateFromNativeInstance(ctx, obj, false, BASE_NS::countof(args), args); 2388bf80f4bSopenharmony_ci toneMap_ = { ctx, tonemapJS }; // take ownership of the object. 2398bf80f4bSopenharmony_ci return tonemapJS; 2408bf80f4bSopenharmony_ci } 2418bf80f4bSopenharmony_ci toneMap_.Reset(); 2428bf80f4bSopenharmony_ci return ctx.GetUndefined(); 2438bf80f4bSopenharmony_ci} 2448bf80f4bSopenharmony_ci 2458bf80f4bSopenharmony_cinapi_value PostProcJS::GetBloom(NapiApi::FunctionContext<>& ctx) 2468bf80f4bSopenharmony_ci{ 2478bf80f4bSopenharmony_ci bool enabled = false; 2488bf80f4bSopenharmony_ci if (auto postproc = interface_pointer_cast<SCENE_NS::IPostProcess>(GetNativeObject())) { 2498bf80f4bSopenharmony_ci ExecSyncTask([postproc, &enabled]() { 2508bf80f4bSopenharmony_ci SCENE_NS::IBloom::Ptr bloom = postproc->Bloom()->GetValue(); 2518bf80f4bSopenharmony_ci enabled = bloom->Enabled()->GetValue(); 2528bf80f4bSopenharmony_ci return META_NS::IAny::Ptr {}; 2538bf80f4bSopenharmony_ci }); 2548bf80f4bSopenharmony_ci } 2558bf80f4bSopenharmony_ci 2568bf80f4bSopenharmony_ci napi_value value; 2578bf80f4bSopenharmony_ci napi_status status = napi_get_boolean(ctx, enabled, &value); 2588bf80f4bSopenharmony_ci return value; 2598bf80f4bSopenharmony_ci} 2608bf80f4bSopenharmony_ci 2618bf80f4bSopenharmony_civoid PostProcJS::SetBloom(NapiApi::FunctionContext<bool>& ctx) 2628bf80f4bSopenharmony_ci{ 2638bf80f4bSopenharmony_ci bool enable = ctx.Arg<0>(); 2648bf80f4bSopenharmony_ci if (auto postproc = interface_pointer_cast<SCENE_NS::IPostProcess>(GetNativeObject())) { 2658bf80f4bSopenharmony_ci ExecSyncTask([postproc, enable]() { 2668bf80f4bSopenharmony_ci SCENE_NS::IBloom::Ptr bloom = postproc->Bloom()->GetValue(); 2678bf80f4bSopenharmony_ci bloom->Enabled()->SetValue(enable); 2688bf80f4bSopenharmony_ci return META_NS::IAny::Ptr {}; 2698bf80f4bSopenharmony_ci }); 2708bf80f4bSopenharmony_ci } 2718bf80f4bSopenharmony_ci} 272