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 "scene_adapter/scene_adapter.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <dlfcn.h>
198bf80f4bSopenharmony_ci#include <memory>
208bf80f4bSopenharmony_ci#include <string_view>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ci#include "napi/native_api.h"
238bf80f4bSopenharmony_ci#include "napi/native_node_api.h"
248bf80f4bSopenharmony_ci
258bf80f4bSopenharmony_ci#include <base/containers/array_view.h>
268bf80f4bSopenharmony_ci
278bf80f4bSopenharmony_ci#include <core/intf_engine.h>
288bf80f4bSopenharmony_ci#include <core/ecs/intf_system_graph_loader.h>
298bf80f4bSopenharmony_ci#include <core/engine_info.h>
308bf80f4bSopenharmony_ci#include <core/implementation_uids.h>
318bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h>
328bf80f4bSopenharmony_ci#include <core/namespace.h>
338bf80f4bSopenharmony_ci#include <core/os/intf_platform.h>
348bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin_register.h>
358bf80f4bSopenharmony_ci#include <core/property/intf_property_handle.h>
368bf80f4bSopenharmony_ci
378bf80f4bSopenharmony_ci#include <meta/interface/intf_meta_object_lib.h>
388bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue_registry.h>
398bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue.h>
408bf80f4bSopenharmony_ci#include <meta/interface/intf_object.h>
418bf80f4bSopenharmony_ci#include <meta/interface/intf_object_registry.h>
428bf80f4bSopenharmony_ci#include <meta/interface/intf_task_queue.h>
438bf80f4bSopenharmony_ci#include <meta/base/shared_ptr.h>
448bf80f4bSopenharmony_ci#include <meta/base/interface_macros.h>
458bf80f4bSopenharmony_ci#include <meta/api/make_callback.h>
468bf80f4bSopenharmony_ci#include <meta/ext/object.h>
478bf80f4bSopenharmony_ci
488bf80f4bSopenharmony_ci#include <scene_plugin/namespace.h>
498bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_scene.h>
508bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_ecs_scene.h>
518bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_mesh.h>
528bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_material.h>
538bf80f4bSopenharmony_ci#include <scene_plugin/api/scene_uid.h>
548bf80f4bSopenharmony_ci
558bf80f4bSopenharmony_ci#include "ability.h"
568bf80f4bSopenharmony_ci#include "data_ability_helper.h"
578bf80f4bSopenharmony_ci#include "napi_base_context.h"
588bf80f4bSopenharmony_ci
598bf80f4bSopenharmony_ci#include <render/implementation_uids.h>
608bf80f4bSopenharmony_ci#include <render/gles/intf_device_gles.h>
618bf80f4bSopenharmony_ci#include <render/intf_renderer.h>
628bf80f4bSopenharmony_ci#include <render/intf_render_context.h>
638bf80f4bSopenharmony_ci
648bf80f4bSopenharmony_ci#include "3d_widget_adapter_log.h"
658bf80f4bSopenharmony_ci#include "widget_trace.h"
668bf80f4bSopenharmony_ci#include "ohos/texture_layer.h"
678bf80f4bSopenharmony_ci
688bf80f4bSopenharmony_cinamespace OHOS::Render3D {
698bf80f4bSopenharmony_ciHapInfo GetHapInfo()
708bf80f4bSopenharmony_ci{
718bf80f4bSopenharmony_ci    std::shared_ptr<AbilityRuntime::ApplicationContext> context =
728bf80f4bSopenharmony_ci        AbilityRuntime::ApplicationContext::GetApplicationContext();
738bf80f4bSopenharmony_ci    if (!context) {
748bf80f4bSopenharmony_ci        WIDGET_LOGE("Failed to get application context.");
758bf80f4bSopenharmony_ci        return {};
768bf80f4bSopenharmony_ci    }
778bf80f4bSopenharmony_ci    auto resourceManager = context->GetResourceManager();
788bf80f4bSopenharmony_ci    if (!resourceManager) {
798bf80f4bSopenharmony_ci        WIDGET_LOGE("Failed to get resource manager.");
808bf80f4bSopenharmony_ci        return {};
818bf80f4bSopenharmony_ci    }
828bf80f4bSopenharmony_ci    HapInfo hapInfo;
838bf80f4bSopenharmony_ci    hapInfo.bundleName_ = resourceManager->bundleInfo.first;
848bf80f4bSopenharmony_ci    hapInfo.moduleName_ = resourceManager->bundleInfo.second;
858bf80f4bSopenharmony_ci
868bf80f4bSopenharmony_ci    // hapPath
878bf80f4bSopenharmony_ci    std::string hapPath = context->GetBundleCodeDir();
888bf80f4bSopenharmony_ci    hapInfo.hapPath_ = hapPath + "/" + hapInfo.moduleName_ + ".hap";
898bf80f4bSopenharmony_ci    WIDGET_LOGD("bundle %s, module %s, hapPath %s",
908bf80f4bSopenharmony_ci        hapInfo.bundleName_.c_str(),
918bf80f4bSopenharmony_ci        hapInfo.moduleName_.c_str(),
928bf80f4bSopenharmony_ci        hapInfo.hapPath_.c_str());
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_ci    return hapInfo;
958bf80f4bSopenharmony_ci}
968bf80f4bSopenharmony_ci
978bf80f4bSopenharmony_ciusing IntfPtr = META_NS::SharedPtrIInterface;
988bf80f4bSopenharmony_ciusing IntfWeakPtr = META_NS::WeakPtrIInterface;
998bf80f4bSopenharmony_ci
1008bf80f4bSopenharmony_cistruct EngineInstance {
1018bf80f4bSopenharmony_ci    void *libHandle_ = nullptr;
1028bf80f4bSopenharmony_ci    BASE_NS::shared_ptr<RENDER_NS::IRenderContext> renderContext_;
1038bf80f4bSopenharmony_ci    BASE_NS::shared_ptr<CORE_NS::IEngine> engine_;
1048bf80f4bSopenharmony_ci};
1058bf80f4bSopenharmony_ci
1068bf80f4bSopenharmony_cistatic EngineInstance engineInstance_;
1078bf80f4bSopenharmony_cistatic std::mutex mute;
1088bf80f4bSopenharmony_ciMETA_NS::ITaskQueue::Ptr engineThread;
1098bf80f4bSopenharmony_ciMETA_NS::ITaskQueue::Ptr ioThread;
1108bf80f4bSopenharmony_ci
1118bf80f4bSopenharmony_civoid LockCompositor()
1128bf80f4bSopenharmony_ci{
1138bf80f4bSopenharmony_ci    mute.lock();
1148bf80f4bSopenharmony_ci}
1158bf80f4bSopenharmony_ci
1168bf80f4bSopenharmony_civoid UnlockCompositor()
1178bf80f4bSopenharmony_ci{
1188bf80f4bSopenharmony_ci    mute.unlock();
1198bf80f4bSopenharmony_ci}
1208bf80f4bSopenharmony_ci
1218bf80f4bSopenharmony_cistatic constexpr BASE_NS::Uid ENGINE_THREAD { "2070e705-d061-40e4-bfb7-90fad2c280af" };
1228bf80f4bSopenharmony_cistatic constexpr BASE_NS::Uid APP_THREAD { "b2e8cef3-453a-4651-b564-5190f8b5190d" };
1238bf80f4bSopenharmony_cistatic constexpr BASE_NS::Uid IO_QUEUE { "be88e9a0-9cd8-45ab-be48-937953dc258f" };
1248bf80f4bSopenharmony_ci
1258bf80f4bSopenharmony_citemplate<typename T>
1268bf80f4bSopenharmony_cibool LoadFunc(T &fn, const char *fName, void* handle)
1278bf80f4bSopenharmony_ci{
1288bf80f4bSopenharmony_ci    fn = reinterpret_cast<T>(dlsym(handle, fName));
1298bf80f4bSopenharmony_ci    if (fn == nullptr) {
1308bf80f4bSopenharmony_ci        WIDGET_LOGE("%s open %s", __func__, dlerror());
1318bf80f4bSopenharmony_ci        return false;
1328bf80f4bSopenharmony_ci    }
1338bf80f4bSopenharmony_ci    return true;
1348bf80f4bSopenharmony_ci}
1358bf80f4bSopenharmony_ci
1368bf80f4bSopenharmony_ciSceneAdapter::~SceneAdapter()
1378bf80f4bSopenharmony_ci{
1388bf80f4bSopenharmony_ci}
1398bf80f4bSopenharmony_ci
1408bf80f4bSopenharmony_ciSceneAdapter::SceneAdapter()
1418bf80f4bSopenharmony_ci{
1428bf80f4bSopenharmony_ci    WIDGET_LOGD("scene adapter Impl create");
1438bf80f4bSopenharmony_ci}
1448bf80f4bSopenharmony_ci
1458bf80f4bSopenharmony_cibool SceneAdapter::LoadEngineLib()
1468bf80f4bSopenharmony_ci{
1478bf80f4bSopenharmony_ci    if (engineInstance_.libHandle_ != nullptr) {
1488bf80f4bSopenharmony_ci        WIDGET_LOGD("%s, already loaded", __func__);
1498bf80f4bSopenharmony_ci        return true;
1508bf80f4bSopenharmony_ci    }
1518bf80f4bSopenharmony_ci
1528bf80f4bSopenharmony_ci    #define TO_STRING(name) #name
1538bf80f4bSopenharmony_ci    #define LIB_NAME(name) TO_STRING(name)
1548bf80f4bSopenharmony_ci    constexpr std::string_view lib { LIB_NAME(LIB_ENGINE_CORE)".so" };
1558bf80f4bSopenharmony_ci    engineInstance_.libHandle_ = dlopen(lib.data(), RTLD_LAZY);
1568bf80f4bSopenharmony_ci
1578bf80f4bSopenharmony_ci    if (engineInstance_.libHandle_ == nullptr) {
1588bf80f4bSopenharmony_ci        WIDGET_LOGE("%s, open lib fail %s", __func__, dlerror());
1598bf80f4bSopenharmony_ci    }
1608bf80f4bSopenharmony_ci    #undef TO_STRING
1618bf80f4bSopenharmony_ci    #undef LIB_NAME
1628bf80f4bSopenharmony_ci
1638bf80f4bSopenharmony_ci    #define LOAD_FUNC(fn, name) LoadFunc<decltype(fn)>(fn, name, engineInstance_.libHandle_)
1648bf80f4bSopenharmony_ci    if (!(LOAD_FUNC(CORE_NS::CreatePluginRegistry,
1658bf80f4bSopenharmony_ci        "_ZN4Core20CreatePluginRegistryERKNS_18PlatformCreateInfoE")
1668bf80f4bSopenharmony_ci        && LOAD_FUNC(CORE_NS::GetPluginRegister, "_ZN4Core17GetPluginRegisterEv")
1678bf80f4bSopenharmony_ci        && LOAD_FUNC(CORE_NS::IsDebugBuild, "_ZN4Core12IsDebugBuildEv")
1688bf80f4bSopenharmony_ci        && LOAD_FUNC(CORE_NS::GetVersion, "_ZN4Core13GetVersionRevEv"))) {
1698bf80f4bSopenharmony_ci        return false;
1708bf80f4bSopenharmony_ci    }
1718bf80f4bSopenharmony_ci    #undef LOAD_FUNC
1728bf80f4bSopenharmony_ci
1738bf80f4bSopenharmony_ci    return true;
1748bf80f4bSopenharmony_ci}
1758bf80f4bSopenharmony_ci
1768bf80f4bSopenharmony_cibool SceneAdapter::LoadPlugins(const CORE_NS::PlatformCreateInfo& platformCreateInfo)
1778bf80f4bSopenharmony_ci{
1788bf80f4bSopenharmony_ci    if (engineInstance_.engine_) {
1798bf80f4bSopenharmony_ci        return true;
1808bf80f4bSopenharmony_ci    }
1818bf80f4bSopenharmony_ci    if (!LoadEngineLib()) {
1828bf80f4bSopenharmony_ci        return false;
1838bf80f4bSopenharmony_ci    }
1848bf80f4bSopenharmony_ci    WIDGET_LOGD("load engine success!");
1858bf80f4bSopenharmony_ci    const BASE_NS::Uid DefaultPluginList[] { SCENE_NS::UID_SCENE_PLUGIN };
1868bf80f4bSopenharmony_ci
1878bf80f4bSopenharmony_ci    CORE_NS::CreatePluginRegistry(platformCreateInfo);
1888bf80f4bSopenharmony_ci    if (!CORE_NS::GetPluginRegister().LoadPlugins(DefaultPluginList)) {
1898bf80f4bSopenharmony_ci        WIDGET_LOGE("fail to load scene widget plugin");
1908bf80f4bSopenharmony_ci        return false;
1918bf80f4bSopenharmony_ci    }
1928bf80f4bSopenharmony_ci    WIDGET_LOGD("load plugin success");
1938bf80f4bSopenharmony_ci    return true;
1948bf80f4bSopenharmony_ci}
1958bf80f4bSopenharmony_ci
1968bf80f4bSopenharmony_cibool SceneAdapter::InitEngine(CORE_NS::PlatformCreateInfo platformCreateInfo)
1978bf80f4bSopenharmony_ci{
1988bf80f4bSopenharmony_ci    if (engineInstance_.engine_) {
1998bf80f4bSopenharmony_ci        return true;
2008bf80f4bSopenharmony_ci    }
2018bf80f4bSopenharmony_ci    auto& tr = META_NS::GetTaskQueueRegistry();
2028bf80f4bSopenharmony_ci    auto& obr = META_NS::GetObjectRegistry();
2038bf80f4bSopenharmony_ci
2048bf80f4bSopenharmony_ci    engineThread = tr.GetTaskQueue(ENGINE_THREAD);
2058bf80f4bSopenharmony_ci    if (!engineThread) {
2068bf80f4bSopenharmony_ci        engineThread = obr.Create<META_NS::ITaskQueue>(META_NS::ClassId::ThreadedTaskQueue);
2078bf80f4bSopenharmony_ci        tr.RegisterTaskQueue(engineThread, ENGINE_THREAD);
2088bf80f4bSopenharmony_ci    }
2098bf80f4bSopenharmony_ci    ioThread = tr.GetTaskQueue(IO_QUEUE);
2108bf80f4bSopenharmony_ci    if (!ioThread) {
2118bf80f4bSopenharmony_ci        ioThread = obr.Create<META_NS::ITaskQueue>(META_NS::ClassId::ThreadedTaskQueue);
2128bf80f4bSopenharmony_ci        tr.RegisterTaskQueue(ioThread, IO_QUEUE);
2138bf80f4bSopenharmony_ci    }
2148bf80f4bSopenharmony_ci
2158bf80f4bSopenharmony_ci    auto engineInit = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([platformCreateInfo]() {
2168bf80f4bSopenharmony_ci        auto& obr = META_NS::GetObjectRegistry();
2178bf80f4bSopenharmony_ci        // Initialize lumeengine/render etc
2188bf80f4bSopenharmony_ci        CORE_NS::EngineCreateInfo engineCreateInfo { platformCreateInfo, {}, {} };
2198bf80f4bSopenharmony_ci        if (auto factory = CORE_NS::GetInstance<CORE_NS::IEngineFactory>(CORE_NS::UID_ENGINE_FACTORY)) {
2208bf80f4bSopenharmony_ci            engineInstance_.engine_.reset(factory->Create(engineCreateInfo).get());
2218bf80f4bSopenharmony_ci        }
2228bf80f4bSopenharmony_ci
2238bf80f4bSopenharmony_ci        if (!engineInstance_.engine_) {
2248bf80f4bSopenharmony_ci            WIDGET_LOGE("get engine fail");
2258bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2268bf80f4bSopenharmony_ci        }
2278bf80f4bSopenharmony_ci        engineInstance_.engine_->Init();
2288bf80f4bSopenharmony_ci
2298bf80f4bSopenharmony_ci        engineInstance_.renderContext_.reset(
2308bf80f4bSopenharmony_ci            CORE_NS::CreateInstance<RENDER_NS::IRenderContext>(*engineInstance_.engine_, RENDER_NS::UID_RENDER_CONTEXT)
2318bf80f4bSopenharmony_ci                .get());
2328bf80f4bSopenharmony_ci
2338bf80f4bSopenharmony_ci        RENDER_NS::RenderCreateInfo renderCreateInfo;
2348bf80f4bSopenharmony_ci        // this context needs to be "not busy" (not selected current in any thread) for creation to succeed.
2358bf80f4bSopenharmony_ci        std::string backendProp = "gles";
2368bf80f4bSopenharmony_ci        if (backendProp == "vulkan") {
2378bf80f4bSopenharmony_ci        } else {
2388bf80f4bSopenharmony_ci            Render::DeviceCreateInfo deviceCreateInfo;
2398bf80f4bSopenharmony_ci            RENDER_NS::BackendExtraGLES glExtra;
2408bf80f4bSopenharmony_ci            glExtra.depthBits = 24; // 24 : bit size
2418bf80f4bSopenharmony_ci            glExtra.sharedContext = EGL_NO_CONTEXT;
2428bf80f4bSopenharmony_ci            deviceCreateInfo.backendType = RENDER_NS::DeviceBackendType::OPENGLES;
2438bf80f4bSopenharmony_ci            deviceCreateInfo.backendConfiguration = &glExtra;
2448bf80f4bSopenharmony_ci            renderCreateInfo.applicationInfo = {};
2458bf80f4bSopenharmony_ci            renderCreateInfo.deviceCreateInfo = deviceCreateInfo;
2468bf80f4bSopenharmony_ci        }
2478bf80f4bSopenharmony_ci
2488bf80f4bSopenharmony_ci        auto rrc = engineInstance_.renderContext_->Init(renderCreateInfo);
2498bf80f4bSopenharmony_ci        if (rrc != RENDER_NS::RenderResultCode::RENDER_SUCCESS) {
2508bf80f4bSopenharmony_ci            WIDGET_LOGE("Failed to create render context");
2518bf80f4bSopenharmony_ci            return META_NS::IAny::Ptr {};
2528bf80f4bSopenharmony_ci        }
2538bf80f4bSopenharmony_ci
2548bf80f4bSopenharmony_ci        // Save the stuff to the default object context.
2558bf80f4bSopenharmony_ci        auto engineThread = META_NS::GetTaskQueueRegistry().GetTaskQueue(ENGINE_THREAD);
2568bf80f4bSopenharmony_ci        // thats the javascript thread...
2578bf80f4bSopenharmony_ci        auto appThread = engineThread;
2588bf80f4bSopenharmony_ci        auto doc = interface_cast<META_NS::IMetadata>(obr.GetDefaultObjectContext());
2598bf80f4bSopenharmony_ci        auto flags = META_NS::ObjectFlagBits::INTERNAL | META_NS::ObjectFlagBits::NATIVE;
2608bf80f4bSopenharmony_ci
2618bf80f4bSopenharmony_ci        doc->AddProperty(META_NS::ConstructProperty<IntfPtr>("RenderContext", nullptr, flags));
2628bf80f4bSopenharmony_ci        doc->AddProperty(META_NS::ConstructProperty<IntfPtr>("EngineQueue", nullptr, flags));
2638bf80f4bSopenharmony_ci        doc->AddProperty(META_NS::ConstructProperty<IntfPtr>("AppQueue", nullptr, flags));
2648bf80f4bSopenharmony_ci        doc->AddProperty(META_NS::ConstructArrayProperty<IntfWeakPtr>("Scenes", {}, flags));
2658bf80f4bSopenharmony_ci
2668bf80f4bSopenharmony_ci        doc->GetPropertyByName<META_NS::SharedPtrIInterface>("EngineQueue")->SetValue(engineThread);
2678bf80f4bSopenharmony_ci        doc->GetPropertyByName<META_NS::SharedPtrIInterface>("AppQueue")->SetValue(appThread);
2688bf80f4bSopenharmony_ci        doc->GetPropertyByName<META_NS::SharedPtrIInterface>("RenderContext")->SetValue(engineInstance_.renderContext_);
2698bf80f4bSopenharmony_ci
2708bf80f4bSopenharmony_ci        WIDGET_LOGD("register shader path");
2718bf80f4bSopenharmony_ci        static constexpr const RENDER_NS::IShaderManager::ShaderFilePathDesc desc { "shaders://" };
2728bf80f4bSopenharmony_ci        engineInstance_.engine_->GetFileManager().RegisterPath("shaders", "OhosRawFile://shaders", false);
2738bf80f4bSopenharmony_ci        engineInstance_.renderContext_->GetDevice().GetShaderManager().LoadShaderFiles(desc);
2748bf80f4bSopenharmony_ci
2758bf80f4bSopenharmony_ci        engineInstance_.engine_->GetFileManager().RegisterPath("appshaders", "OhosRawFile://shaders", false);
2768bf80f4bSopenharmony_ci        static constexpr const RENDER_NS::IShaderManager::ShaderFilePathDesc desc1 { "appshaders://" };
2778bf80f4bSopenharmony_ci        engineInstance_.renderContext_->GetDevice().GetShaderManager().LoadShaderFiles(desc1);
2788bf80f4bSopenharmony_ci
2798bf80f4bSopenharmony_ci        WIDGET_LOGD("init engine success");
2808bf80f4bSopenharmony_ci        return META_NS::IAny::Ptr {};
2818bf80f4bSopenharmony_ci    });
2828bf80f4bSopenharmony_ci
2838bf80f4bSopenharmony_ci    engineThread->AddWaitableTask(engineInit)->Wait();
2848bf80f4bSopenharmony_ci
2858bf80f4bSopenharmony_ci    return true;
2868bf80f4bSopenharmony_ci}
2878bf80f4bSopenharmony_ci
2888bf80f4bSopenharmony_civoid SceneAdapter::SetSceneObj(META_NS::IObject::Ptr pt)
2898bf80f4bSopenharmony_ci{
2908bf80f4bSopenharmony_ci    WIDGET_LOGD("SceneAdapterImpl::SetSceneObj");
2918bf80f4bSopenharmony_ci    sceneWidgetObj_ = pt;
2928bf80f4bSopenharmony_ci}
2938bf80f4bSopenharmony_ci
2948bf80f4bSopenharmony_cistd::shared_ptr<TextureLayer> SceneAdapter::CreateTextureLayer()
2958bf80f4bSopenharmony_ci{
2968bf80f4bSopenharmony_ci    InitRenderThread();
2978bf80f4bSopenharmony_ci    auto cb = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this]() {
2988bf80f4bSopenharmony_ci        textureLayer_ = std::make_shared<TextureLayer>(key_);
2998bf80f4bSopenharmony_ci        key_++;
3008bf80f4bSopenharmony_ci        return META_NS::IAny::Ptr {};
3018bf80f4bSopenharmony_ci    });
3028bf80f4bSopenharmony_ci    META_NS::GetTaskQueueRegistry().GetTaskQueue(ENGINE_THREAD)->AddWaitableTask(cb)->Wait();
3038bf80f4bSopenharmony_ci    return textureLayer_;
3048bf80f4bSopenharmony_ci}
3058bf80f4bSopenharmony_ci
3068bf80f4bSopenharmony_cibool SceneAdapter::LoadPluginsAndInit()
3078bf80f4bSopenharmony_ci{
3088bf80f4bSopenharmony_ci    WIDGET_LOGD("scene adapter loadPlugins");
3098bf80f4bSopenharmony_ci    hapInfo_ = GetHapInfo();
3108bf80f4bSopenharmony_ci
3118bf80f4bSopenharmony_ci    #define TO_STRING(name) #name
3128bf80f4bSopenharmony_ci    #define PLATFORM_PATH_NAME(name) TO_STRING(name)
3138bf80f4bSopenharmony_ci    CORE_NS::PlatformCreateInfo platformCreateInfo {
3148bf80f4bSopenharmony_ci        PLATFORM_PATH_NAME(PLATFORM_CORE_ROOT_PATH),
3158bf80f4bSopenharmony_ci        PLATFORM_PATH_NAME(PLATFORM_APP_ROOT_PATH),
3168bf80f4bSopenharmony_ci        PLATFORM_PATH_NAME(PLATFORM_APP_PLUGIN_PATH),
3178bf80f4bSopenharmony_ci        hapInfo_.hapPath_.c_str(),
3188bf80f4bSopenharmony_ci        hapInfo_.bundleName_.c_str(),
3198bf80f4bSopenharmony_ci        hapInfo_.moduleName_.c_str()
3208bf80f4bSopenharmony_ci    };
3218bf80f4bSopenharmony_ci    #undef TO_STRING
3228bf80f4bSopenharmony_ci    #undef PLATFORM_PATH_NAME
3238bf80f4bSopenharmony_ci    if (!LoadPlugins(platformCreateInfo)) {
3248bf80f4bSopenharmony_ci        return false;
3258bf80f4bSopenharmony_ci    }
3268bf80f4bSopenharmony_ci
3278bf80f4bSopenharmony_ci    if (!InitEngine(platformCreateInfo)) {
3288bf80f4bSopenharmony_ci        return false;
3298bf80f4bSopenharmony_ci    }
3308bf80f4bSopenharmony_ci
3318bf80f4bSopenharmony_ci    return true;
3328bf80f4bSopenharmony_ci}
3338bf80f4bSopenharmony_ci
3348bf80f4bSopenharmony_civoid SceneAdapter::OnWindowChange(const WindowChangeInfo& windowChangeInfo)
3358bf80f4bSopenharmony_ci{
3368bf80f4bSopenharmony_ci    WIDGET_LOGD("OnWindowchange");
3378bf80f4bSopenharmony_ci    auto cb = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this, &windowChangeInfo]() {
3388bf80f4bSopenharmony_ci        textureLayer_->OnWindowChange(windowChangeInfo);
3398bf80f4bSopenharmony_ci        const auto& textureInfo = textureLayer_->GetTextureInfo();
3408bf80f4bSopenharmony_ci        auto& device = engineInstance_.renderContext_->GetDevice();
3418bf80f4bSopenharmony_ci        RENDER_NS::SwapchainCreateInfo swapchainCreateInfo {
3428bf80f4bSopenharmony_ci            // reinterpret_cast<uint64_t>(eglSurface_),
3438bf80f4bSopenharmony_ci            0U,
3448bf80f4bSopenharmony_ci            RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_COLOR_BUFFER_BIT |
3458bf80f4bSopenharmony_ci            RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_DEPTH_BUFFER_BIT |
3468bf80f4bSopenharmony_ci            RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_SRGB_BIT,
3478bf80f4bSopenharmony_ci            RENDER_NS::ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
3488bf80f4bSopenharmony_ci            {
3498bf80f4bSopenharmony_ci                reinterpret_cast<uintptr_t>(textureInfo.nativeWindow_),
3508bf80f4bSopenharmony_ci                reinterpret_cast<uintptr_t>(static_cast<const RENDER_NS::DevicePlatformDataGLES&>(
3518bf80f4bSopenharmony_ci                    device.GetPlatformData()).display)
3528bf80f4bSopenharmony_ci            }
3538bf80f4bSopenharmony_ci        };
3548bf80f4bSopenharmony_ci        swapchainHandle_ = device.CreateSwapchainHandle(swapchainCreateInfo, swapchainHandle_, {});
3558bf80f4bSopenharmony_ci        return META_NS::IAny::Ptr {};
3568bf80f4bSopenharmony_ci    });
3578bf80f4bSopenharmony_ci
3588bf80f4bSopenharmony_ci    META_NS::GetTaskQueueRegistry().GetTaskQueue(ENGINE_THREAD)->AddWaitableTask(cb)->Wait();
3598bf80f4bSopenharmony_ci}
3608bf80f4bSopenharmony_ci
3618bf80f4bSopenharmony_civoid SceneAdapter::InitRenderThread()
3628bf80f4bSopenharmony_ci{
3638bf80f4bSopenharmony_ci    // Task used for oneshot renders
3648bf80f4bSopenharmony_ci    singleFrameAsync = META_NS::MakeCallback<META_NS::ITaskQueueTask>([this]() {
3658bf80f4bSopenharmony_ci        RenderFunction();
3668bf80f4bSopenharmony_ci        return 0;
3678bf80f4bSopenharmony_ci    });
3688bf80f4bSopenharmony_ci    // Task used for oneshot synchronous renders
3698bf80f4bSopenharmony_ci    singleFrameSync = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this]() {
3708bf80f4bSopenharmony_ci        RenderFunction();
3718bf80f4bSopenharmony_ci        return META_NS::IAny::Ptr {};
3728bf80f4bSopenharmony_ci    });
3738bf80f4bSopenharmony_ci}
3748bf80f4bSopenharmony_ci// where to put this deinit
3758bf80f4bSopenharmony_civoid SceneAdapter::DeinitRenderThread()
3768bf80f4bSopenharmony_ci{
3778bf80f4bSopenharmony_ci    auto ioThread = META_NS::GetTaskQueueRegistry().GetTaskQueue(IO_QUEUE);
3788bf80f4bSopenharmony_ci    if (renderTask) {
3798bf80f4bSopenharmony_ci        engineThread->CancelTask(renderTask);
3808bf80f4bSopenharmony_ci        renderTask = nullptr;
3818bf80f4bSopenharmony_ci    }
3828bf80f4bSopenharmony_ci    auto engine_deinit = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([]() {
3838bf80f4bSopenharmony_ci        // destroy all swapchains
3848bf80f4bSopenharmony_ci        auto &obr = META_NS::GetObjectRegistry();
3858bf80f4bSopenharmony_ci        auto doc = interface_cast<META_NS::IMetadata>(obr.GetDefaultObjectContext());
3868bf80f4bSopenharmony_ci
3878bf80f4bSopenharmony_ci        // hmm.. this is somewhat uncool
3888bf80f4bSopenharmony_ci        {
3898bf80f4bSopenharmony_ci            auto p1 = doc->GetPropertyByName<IntfPtr>("EngineQueue");
3908bf80f4bSopenharmony_ci            doc->RemoveProperty(p1);
3918bf80f4bSopenharmony_ci            auto p2 = doc->GetPropertyByName<IntfPtr>("AppQueue");
3928bf80f4bSopenharmony_ci            doc->RemoveProperty(p2);
3938bf80f4bSopenharmony_ci            auto p3 = doc->GetPropertyByName<IntfPtr>("RenderContext");
3948bf80f4bSopenharmony_ci            doc->RemoveProperty(p3);
3958bf80f4bSopenharmony_ci        }
3968bf80f4bSopenharmony_ci
3978bf80f4bSopenharmony_ci        doc->GetArrayPropertyByName<IntfWeakPtr>("Scenes")->Reset();
3988bf80f4bSopenharmony_ci        engineInstance_.renderContext_.reset();
3998bf80f4bSopenharmony_ci        engineInstance_.engine_.reset();
4008bf80f4bSopenharmony_ci
4018bf80f4bSopenharmony_ci        return META_NS::IAny::Ptr{};
4028bf80f4bSopenharmony_ci    });
4038bf80f4bSopenharmony_ci    engineThread->AddWaitableTask(engine_deinit)->Wait();
4048bf80f4bSopenharmony_ci    singleFrameAsync.reset();
4058bf80f4bSopenharmony_ci    auto &tr = META_NS::GetTaskQueueRegistry();
4068bf80f4bSopenharmony_ci    tr.UnregisterTaskQueue(ENGINE_THREAD);
4078bf80f4bSopenharmony_ci    engineThread.reset();
4088bf80f4bSopenharmony_ci    tr.UnregisterTaskQueue(IO_QUEUE);
4098bf80f4bSopenharmony_ci    ioThread.reset();
4108bf80f4bSopenharmony_ci}
4118bf80f4bSopenharmony_ci
4128bf80f4bSopenharmony_civoid SceneAdapter::RenderFunction()
4138bf80f4bSopenharmony_ci{
4148bf80f4bSopenharmony_ci    WIDGET_SCOPED_TRACE("SceneAdapter::RenderFunction");
4158bf80f4bSopenharmony_ci    auto &obr = META_NS::GetObjectRegistry();
4168bf80f4bSopenharmony_ci    auto doc = interface_cast<META_NS::IMetadata>(obr.GetDefaultObjectContext());
4178bf80f4bSopenharmony_ci    BASE_NS::shared_ptr<RENDER_NS::IRenderContext> rc;
4188bf80f4bSopenharmony_ci    if (auto prp = doc->GetPropertyByName<IntfPtr>("RenderContext")) {
4198bf80f4bSopenharmony_ci        rc = interface_pointer_cast<RENDER_NS::IRenderContext>(prp->GetValue());
4208bf80f4bSopenharmony_ci    }
4218bf80f4bSopenharmony_ci    LockCompositor();
4228bf80f4bSopenharmony_ci    auto scene = interface_pointer_cast<SCENE_NS::IScene>(sceneWidgetObj_);
4238bf80f4bSopenharmony_ci    if (!bitmap_) {
4248bf80f4bSopenharmony_ci        auto cams = scene->GetCameras();
4258bf80f4bSopenharmony_ci        if (!cams.empty()) {
4268bf80f4bSopenharmony_ci            for (auto c : cams) {
4278bf80f4bSopenharmony_ci                AttachSwapchain(interface_pointer_cast<META_NS::IObject>(c), swapchainHandle_);
4288bf80f4bSopenharmony_ci            }
4298bf80f4bSopenharmony_ci        }
4308bf80f4bSopenharmony_ci    }
4318bf80f4bSopenharmony_ci    scene->RenderCameras();
4328bf80f4bSopenharmony_ci    rc->GetRenderer().RenderDeferredFrame();
4338bf80f4bSopenharmony_ci    UnlockCompositor();
4348bf80f4bSopenharmony_ci}
4358bf80f4bSopenharmony_ci
4368bf80f4bSopenharmony_civoid SceneAdapter::RenderFrame(bool needsSyncPaint)
4378bf80f4bSopenharmony_ci{
4388bf80f4bSopenharmony_ci    if (renderTask) {
4398bf80f4bSopenharmony_ci        engineThread->CancelTask(renderTask);
4408bf80f4bSopenharmony_ci        renderTask = nullptr;
4418bf80f4bSopenharmony_ci    }
4428bf80f4bSopenharmony_ci
4438bf80f4bSopenharmony_ci    if (!needsSyncPaint) {
4448bf80f4bSopenharmony_ci        renderTask = engineThread->AddTask(singleFrameAsync);
4458bf80f4bSopenharmony_ci    } else {
4468bf80f4bSopenharmony_ci        engineThread->AddWaitableTask(singleFrameSync)->Wait();
4478bf80f4bSopenharmony_ci    }
4488bf80f4bSopenharmony_ci}
4498bf80f4bSopenharmony_ci
4508bf80f4bSopenharmony_cibool SceneAdapter::NeedsRepaint()
4518bf80f4bSopenharmony_ci{
4528bf80f4bSopenharmony_ci    return needsRepaint_;
4538bf80f4bSopenharmony_ci}
4548bf80f4bSopenharmony_ci
4558bf80f4bSopenharmony_civoid SceneAdapter::AttachSwapchain(META_NS::IObject::Ptr cameraObj, RENDER_NS::RenderHandleReference swapchain)
4568bf80f4bSopenharmony_ci{
4578bf80f4bSopenharmony_ci    WIDGET_LOGD("attach swapchain");
4588bf80f4bSopenharmony_ci    auto scene = interface_cast<SCENE_NS::INode>(cameraObj)->GetScene();
4598bf80f4bSopenharmony_ci    auto camera = interface_pointer_cast<SCENE_NS::ICamera>(cameraObj);
4608bf80f4bSopenharmony_ci    if (scene->IsCameraActive(camera)) {
4618bf80f4bSopenharmony_ci        auto externalBitmapUid = BASE_NS::Uid("77b38a92-8182-4562-bd3f-deab7b40cedc");
4628bf80f4bSopenharmony_ci        bitmap_ = META_NS::GetObjectRegistry().Create<SCENE_NS::IBitmap>(externalBitmapUid);
4638bf80f4bSopenharmony_ci
4648bf80f4bSopenharmony_ci        scene->SetBitmap(bitmap_, camera);
4658bf80f4bSopenharmony_ci        const auto &info = textureLayer_->GetTextureInfo();
4668bf80f4bSopenharmony_ci
4678bf80f4bSopenharmony_ci        bitmap_->SetRenderHandle(swapchainHandle_,
4688bf80f4bSopenharmony_ci            { static_cast<uint32_t>(info.width_ * info.widthScale_),
4698bf80f4bSopenharmony_ci                static_cast<uint32_t>(info.height_ * info.heightScale_) });
4708bf80f4bSopenharmony_ci    }
4718bf80f4bSopenharmony_ci}
4728bf80f4bSopenharmony_ci} // namespace OHOS::Render3D
473