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 "graphics_context.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci
208bf80f4bSopenharmony_ci#include <base/containers/string_view.h>
218bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h>
228bf80f4bSopenharmony_ci#include <base/util/uid.h>
238bf80f4bSopenharmony_ci#include <core/ecs/intf_ecs.h>
248bf80f4bSopenharmony_ci#include <core/ecs/intf_entity_manager.h>
258bf80f4bSopenharmony_ci#include <core/intf_engine.h>
268bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h>
278bf80f4bSopenharmony_ci#include <core/log.h>
288bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin.h>
298bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin_register.h>
308bf80f4bSopenharmony_ci#include <core/property/intf_property_handle.h>
318bf80f4bSopenharmony_ci#include <render/datastore/intf_render_data_store_manager.h>
328bf80f4bSopenharmony_ci#include <render/datastore/intf_render_data_store_pod.h>
338bf80f4bSopenharmony_ci#include <render/device/intf_device.h>
348bf80f4bSopenharmony_ci#include <render/device/intf_gpu_resource_manager.h>
358bf80f4bSopenharmony_ci#include <render/device/intf_shader_manager.h>
368bf80f4bSopenharmony_ci#include <render/implementation_uids.h>
378bf80f4bSopenharmony_ci#include <render/intf_plugin.h>
388bf80f4bSopenharmony_ci#include <render/intf_render_context.h>
398bf80f4bSopenharmony_ci#include <render/loader/intf_render_data_configuration_loader.h>
408bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_node_graph_manager.h>
418bf80f4bSopenharmony_ci
428bf80f4bSopenharmony_ci#if (RENDER_HAS_VULKAN_BACKEND)
438bf80f4bSopenharmony_ci#include <render/vulkan/intf_device_vk.h>
448bf80f4bSopenharmony_ci#endif
458bf80f4bSopenharmony_ci
468bf80f4bSopenharmony_ci#include <3d/ecs/components/material_component.h>
478bf80f4bSopenharmony_ci#include <3d/ecs/components/uri_component.h>
488bf80f4bSopenharmony_ci#include <3d/ecs/systems/intf_render_system.h>
498bf80f4bSopenharmony_ci#include <3d/implementation_uids.h>
508bf80f4bSopenharmony_ci#include <3d/intf_plugin.h>
518bf80f4bSopenharmony_ci#include <3d/loaders/intf_scene_loader.h>
528bf80f4bSopenharmony_ci#include <3d/render/default_material_constants.h>
538bf80f4bSopenharmony_ci#include <3d/render/intf_render_node_scene_util.h>
548bf80f4bSopenharmony_ci#include <3d/util/intf_mesh_util.h>
558bf80f4bSopenharmony_ci#include <3d/util/intf_scene_util.h>
568bf80f4bSopenharmony_ci
578bf80f4bSopenharmony_ci#include "gltf/gltf2.h"
588bf80f4bSopenharmony_ci#include "render/render_node_scene_util.h"
598bf80f4bSopenharmony_ci#include "util/mesh_builder.h"
608bf80f4bSopenharmony_ci#include "util/mesh_util.h"
618bf80f4bSopenharmony_ci#include "util/picking.h"
628bf80f4bSopenharmony_ci#include "util/render_util.h"
638bf80f4bSopenharmony_ci#include "util/scene_util.h"
648bf80f4bSopenharmony_ci#include "util/uri_lookup.h"
658bf80f4bSopenharmony_ci
668bf80f4bSopenharmony_ciextern "C" void InitRegistry(CORE_NS::IPluginRegister& pluginRegistry);
678bf80f4bSopenharmony_ci
688bf80f4bSopenharmony_ciCORE3D_BEGIN_NAMESPACE()
698bf80f4bSopenharmony_ciusing namespace BASE_NS;
708bf80f4bSopenharmony_ciusing namespace CORE_NS;
718bf80f4bSopenharmony_ciusing namespace RENDER_NS;
728bf80f4bSopenharmony_ci
738bf80f4bSopenharmony_cinamespace {
748bf80f4bSopenharmony_cistruct RegisterPathStrings {
758bf80f4bSopenharmony_ci    string_view protocol;
768bf80f4bSopenharmony_ci    string_view uri;
778bf80f4bSopenharmony_ci};
788bf80f4bSopenharmony_cistatic constexpr RegisterPathStrings RENDER_DATA_PATHS[] = {
798bf80f4bSopenharmony_ci    { "3dshaders", "rofs3D://shaders/" },
808bf80f4bSopenharmony_ci    { "3dshaderstates", "rofs3D://shaderstates/" },
818bf80f4bSopenharmony_ci    { "3dvertexinputdeclarations", "rofs3D://vertexinputdeclarations/" },
828bf80f4bSopenharmony_ci    { "3dpipelinelayouts", "rofs3D://pipelinelayouts/" },
838bf80f4bSopenharmony_ci    { "3drenderdataconfigurations", "rofs3D://renderdataconfigurations/" },
848bf80f4bSopenharmony_ci    { "3drendernodegraphs", "rofs3D://rendernodegraphs/" },
858bf80f4bSopenharmony_ci};
868bf80f4bSopenharmony_ci
878bf80f4bSopenharmony_cistatic constexpr IShaderManager::ShaderFilePathDesc SHADER_FILE_PATHS {
888bf80f4bSopenharmony_ci    "3dshaders://",
898bf80f4bSopenharmony_ci    "3dshaderstates://",
908bf80f4bSopenharmony_ci    "3dpipelinelayouts://",
918bf80f4bSopenharmony_ci    "3dvertexinputdeclarations://",
928bf80f4bSopenharmony_ci};
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_cistatic constexpr string_view POST_PROCESS_PATH { "3drenderdataconfigurations://postprocess/" };
958bf80f4bSopenharmony_cistatic constexpr string_view POST_PROCESS_DATA_STORE_NAME { "RenderDataStorePod" };
968bf80f4bSopenharmony_cistatic constexpr string_view POST_PROCESS_NAME { "PostProcess" };
978bf80f4bSopenharmony_ci
988bf80f4bSopenharmony_civoid CreateDefaultImages(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
998bf80f4bSopenharmony_ci{
1008bf80f4bSopenharmony_ci    IGpuResourceManager& gpuResourceMgr = device.GetGpuResourceManager();
1018bf80f4bSopenharmony_ci
1028bf80f4bSopenharmony_ci    // default material gpu images
1038bf80f4bSopenharmony_ci    GpuImageDesc desc { ImageType::CORE_IMAGE_TYPE_2D, ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
1048bf80f4bSopenharmony_ci        Format::BASE_FORMAT_R8G8B8A8_SRGB, ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
1058bf80f4bSopenharmony_ci        ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_DST_BIT,
1068bf80f4bSopenharmony_ci        MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0, 2, 2, 1, 1, 1,
1078bf80f4bSopenharmony_ci        SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, {} };
1088bf80f4bSopenharmony_ci    constexpr uint32_t sizeOfUint32 = sizeof(uint32_t);
1098bf80f4bSopenharmony_ci
1108bf80f4bSopenharmony_ci    desc.format = Format::BASE_FORMAT_R8G8B8A8_UNORM;
1118bf80f4bSopenharmony_ci    {
1128bf80f4bSopenharmony_ci        constexpr const uint32_t normalData[4u] = { 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f, 0xFFFF7f7f };
1138bf80f4bSopenharmony_ci        const auto normalDataView =
1148bf80f4bSopenharmony_ci            array_view(reinterpret_cast<const uint8_t*>(normalData), sizeOfUint32 * countof(normalData));
1158bf80f4bSopenharmony_ci        defaultGpuResources.push_back(gpuResourceMgr.Create(
1168bf80f4bSopenharmony_ci            DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_NORMAL, desc, normalDataView));
1178bf80f4bSopenharmony_ci    }
1188bf80f4bSopenharmony_ci
1198bf80f4bSopenharmony_ci    desc.format = Format::BASE_FORMAT_R8_UNORM;
1208bf80f4bSopenharmony_ci    {
1218bf80f4bSopenharmony_ci        constexpr const uint8_t byteData[4u] = { 0xff, 0xff, 0xff, 0xff };
1228bf80f4bSopenharmony_ci        const auto byteDataView =
1238bf80f4bSopenharmony_ci            array_view(reinterpret_cast<const uint8_t*>(byteData), sizeof(uint8_t) * countof(byteData));
1248bf80f4bSopenharmony_ci        defaultGpuResources.push_back(
1258bf80f4bSopenharmony_ci            gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_MATERIAL_AO, desc, byteDataView));
1268bf80f4bSopenharmony_ci    }
1278bf80f4bSopenharmony_ci
1288bf80f4bSopenharmony_ci    // env cubemaps
1298bf80f4bSopenharmony_ci    desc.imageViewType = ImageViewType::CORE_IMAGE_VIEW_TYPE_CUBE;
1308bf80f4bSopenharmony_ci    desc.format = Format::BASE_FORMAT_R8G8B8A8_SRGB;
1318bf80f4bSopenharmony_ci    desc.createFlags = ImageCreateFlagBits::CORE_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
1328bf80f4bSopenharmony_ci    desc.layerCount = 6u;
1338bf80f4bSopenharmony_ci    {
1348bf80f4bSopenharmony_ci        // Env color is currently in rgbd format (alpha channel is used as a divider for the rgb values).
1358bf80f4bSopenharmony_ci        const vector<uint32_t> cubeData(4u * 6u, 0xFFFFffff);
1368bf80f4bSopenharmony_ci        const array_view<const uint8_t> cubeDataView(
1378bf80f4bSopenharmony_ci            reinterpret_cast<const uint8_t*>(cubeData.data()), cubeData.size() * sizeOfUint32);
1388bf80f4bSopenharmony_ci        defaultGpuResources.push_back(gpuResourceMgr.Create(
1398bf80f4bSopenharmony_ci            DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP, desc, cubeDataView));
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ci        // Skybox is currently in rgbd format (alpha channel is used as a divider for the rgb values).
1428bf80f4bSopenharmony_ci        defaultGpuResources.push_back(gpuResourceMgr.Create(
1438bf80f4bSopenharmony_ci            DefaultMaterialGpuResourceConstants::CORE_DEFAULT_SKYBOX_CUBEMAP, desc, cubeDataView));
1448bf80f4bSopenharmony_ci    }
1458bf80f4bSopenharmony_ci}
1468bf80f4bSopenharmony_ci
1478bf80f4bSopenharmony_civoid CreateDefaultSamplers(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
1488bf80f4bSopenharmony_ci{
1498bf80f4bSopenharmony_ci    IGpuResourceManager& gpuResourceMgr = device.GetGpuResourceManager();
1508bf80f4bSopenharmony_ci    {
1518bf80f4bSopenharmony_ci        GpuSamplerDesc sampler {
1528bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // magFilter
1538bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // minFilter
1548bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // mipMapMode
1558bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
1568bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
1578bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
1588bf80f4bSopenharmony_ci        };
1598bf80f4bSopenharmony_ci        constexpr float CUBE_MAP_LOD_COEFF { 8.0f };
1608bf80f4bSopenharmony_ci        sampler.minLod = 0.0f;
1618bf80f4bSopenharmony_ci        sampler.maxLod = CUBE_MAP_LOD_COEFF;
1628bf80f4bSopenharmony_ci        defaultGpuResources.push_back(
1638bf80f4bSopenharmony_ci            gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_RADIANCE_CUBEMAP_SAMPLER, sampler));
1648bf80f4bSopenharmony_ci    }
1658bf80f4bSopenharmony_ci    {
1668bf80f4bSopenharmony_ci        GpuSamplerDesc sampler {
1678bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // magFilter
1688bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // minFilter
1698bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // mipMapMode
1708bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
1718bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
1728bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
1738bf80f4bSopenharmony_ci        };
1748bf80f4bSopenharmony_ci        defaultGpuResources.push_back(
1758bf80f4bSopenharmony_ci            gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_VSM_SHADOW_SAMPLER, sampler));
1768bf80f4bSopenharmony_ci
1778bf80f4bSopenharmony_ci        sampler.compareOp = CompareOp::CORE_COMPARE_OP_GREATER;
1788bf80f4bSopenharmony_ci        sampler.enableCompareOp = true;
1798bf80f4bSopenharmony_ci        defaultGpuResources.push_back(
1808bf80f4bSopenharmony_ci            gpuResourceMgr.Create(DefaultMaterialGpuResourceConstants::CORE_DEFAULT_PCF_SHADOW_SAMPLER, sampler));
1818bf80f4bSopenharmony_ci    }
1828bf80f4bSopenharmony_ci}
1838bf80f4bSopenharmony_ci
1848bf80f4bSopenharmony_civoid CreateDefaultResources(IDevice& device, vector<RenderHandleReference>& defaultGpuResources)
1858bf80f4bSopenharmony_ci{
1868bf80f4bSopenharmony_ci    CreateDefaultImages(device, defaultGpuResources);
1878bf80f4bSopenharmony_ci    CreateDefaultSamplers(device, defaultGpuResources);
1888bf80f4bSopenharmony_ci}
1898bf80f4bSopenharmony_ci} // namespace
1908bf80f4bSopenharmony_ci
1918bf80f4bSopenharmony_ci// Core Rofs Data.
1928bf80f4bSopenharmony_ciextern "C" {
1938bf80f4bSopenharmony_ciextern const void* const BINARY_DATA_FOR_3D[];
1948bf80f4bSopenharmony_ciextern const uint64_t SIZE_OF_DATA_FOR_3D;
1958bf80f4bSopenharmony_ci}
1968bf80f4bSopenharmony_ci
1978bf80f4bSopenharmony_ciarray_view<const RenderDataStoreTypeInfo> GetRenderDataStores3D();
1988bf80f4bSopenharmony_ciarray_view<const RenderNodeTypeInfo> GetRenderNodes3D();
1998bf80f4bSopenharmony_ciarray_view<const ComponentManagerTypeInfo> GetComponentManagers3D();
2008bf80f4bSopenharmony_ciarray_view<const SystemTypeInfo> GetSystems3D();
2018bf80f4bSopenharmony_ci
2028bf80f4bSopenharmony_cistruct Agp3DPluginState {
2038bf80f4bSopenharmony_ci    IRenderContext& renderContext;
2048bf80f4bSopenharmony_ci    unique_ptr<GraphicsContext> context;
2058bf80f4bSopenharmony_ci
2068bf80f4bSopenharmony_ci    vector<RenderHandleReference> defaultGpuResources;
2078bf80f4bSopenharmony_ci    vector<string> defaultPostProcesses;
2088bf80f4bSopenharmony_ci
2098bf80f4bSopenharmony_ci    Picking picker_;
2108bf80f4bSopenharmony_ci    RenderNodeSceneUtilImpl renderNodeSceneUtil;
2118bf80f4bSopenharmony_ci    InterfaceTypeInfo interfaces[4] = {
2128bf80f4bSopenharmony_ci        InterfaceTypeInfo {
2138bf80f4bSopenharmony_ci            this,
2148bf80f4bSopenharmony_ci            UID_MESH_BUILDER,
2158bf80f4bSopenharmony_ci            CORE_NS::GetName<IMeshBuilder>().data(),
2168bf80f4bSopenharmony_ci            [](IClassFactory&, PluginToken token) -> IInterface* {
2178bf80f4bSopenharmony_ci                if (token) {
2188bf80f4bSopenharmony_ci                    Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
2198bf80f4bSopenharmony_ci                    return new MeshBuilder(state->renderContext);
2208bf80f4bSopenharmony_ci                }
2218bf80f4bSopenharmony_ci                return nullptr;
2228bf80f4bSopenharmony_ci            },
2238bf80f4bSopenharmony_ci            nullptr,
2248bf80f4bSopenharmony_ci        },
2258bf80f4bSopenharmony_ci        InterfaceTypeInfo {
2268bf80f4bSopenharmony_ci            this,
2278bf80f4bSopenharmony_ci            UID_PICKING,
2288bf80f4bSopenharmony_ci            CORE_NS::GetName<IPicking>().data(),
2298bf80f4bSopenharmony_ci            nullptr,
2308bf80f4bSopenharmony_ci            [](IClassRegister& registry, PluginToken token) -> IInterface* {
2318bf80f4bSopenharmony_ci                if (token) {
2328bf80f4bSopenharmony_ci                    Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
2338bf80f4bSopenharmony_ci                    return &state->picker_;
2348bf80f4bSopenharmony_ci                }
2358bf80f4bSopenharmony_ci                return nullptr;
2368bf80f4bSopenharmony_ci            },
2378bf80f4bSopenharmony_ci        },
2388bf80f4bSopenharmony_ci        InterfaceTypeInfo {
2398bf80f4bSopenharmony_ci            this,
2408bf80f4bSopenharmony_ci            UID_RENDER_NODE_SCENE_UTIL,
2418bf80f4bSopenharmony_ci            CORE_NS::GetName<IRenderNodeSceneUtil>().data(),
2428bf80f4bSopenharmony_ci            nullptr,
2438bf80f4bSopenharmony_ci            [](IClassRegister& registry, PluginToken token) -> IInterface* {
2448bf80f4bSopenharmony_ci                if (token) {
2458bf80f4bSopenharmony_ci                    Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
2468bf80f4bSopenharmony_ci                    return &state->renderNodeSceneUtil;
2478bf80f4bSopenharmony_ci                }
2488bf80f4bSopenharmony_ci                return nullptr;
2498bf80f4bSopenharmony_ci            },
2508bf80f4bSopenharmony_ci        },
2518bf80f4bSopenharmony_ci        InterfaceTypeInfo {
2528bf80f4bSopenharmony_ci            this,
2538bf80f4bSopenharmony_ci            UID_GRAPHICS_CONTEXT,
2548bf80f4bSopenharmony_ci            CORE_NS::GetName<IGraphicsContext>().data(),
2558bf80f4bSopenharmony_ci            [](IClassFactory& registry, PluginToken token) -> IInterface* {
2568bf80f4bSopenharmony_ci                if (token) {
2578bf80f4bSopenharmony_ci                    Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
2588bf80f4bSopenharmony_ci                    if (!state->context) {
2598bf80f4bSopenharmony_ci                        state->context = make_unique<GraphicsContext>(*state, state->renderContext);
2608bf80f4bSopenharmony_ci                    }
2618bf80f4bSopenharmony_ci                    return state->context->GetInterface(IInterface::UID);
2628bf80f4bSopenharmony_ci                }
2638bf80f4bSopenharmony_ci                return nullptr;
2648bf80f4bSopenharmony_ci            },
2658bf80f4bSopenharmony_ci            [](IClassRegister& registry, PluginToken token) -> IInterface* {
2668bf80f4bSopenharmony_ci                if (token) {
2678bf80f4bSopenharmony_ci                    Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
2688bf80f4bSopenharmony_ci                    return state->context->GetInterface(IInterface::UID);
2698bf80f4bSopenharmony_ci                }
2708bf80f4bSopenharmony_ci                return nullptr;
2718bf80f4bSopenharmony_ci            },
2728bf80f4bSopenharmony_ci        },
2738bf80f4bSopenharmony_ci    };
2748bf80f4bSopenharmony_ci
2758bf80f4bSopenharmony_ci    void Destroy()
2768bf80f4bSopenharmony_ci    {
2778bf80f4bSopenharmony_ci        context.reset();
2788bf80f4bSopenharmony_ci    }
2798bf80f4bSopenharmony_ci};
2808bf80f4bSopenharmony_ci
2818bf80f4bSopenharmony_ciGraphicsContext::GraphicsContext(struct Agp3DPluginState& factory, IRenderContext& context)
2828bf80f4bSopenharmony_ci    : factory_(factory), context_(context)
2838bf80f4bSopenharmony_ci{}
2848bf80f4bSopenharmony_ci
2858bf80f4bSopenharmony_ciGraphicsContext ::~GraphicsContext()
2868bf80f4bSopenharmony_ci{
2878bf80f4bSopenharmony_ci    GetPluginRegister().RemoveListener(*this);
2888bf80f4bSopenharmony_ci
2898bf80f4bSopenharmony_ci    for (auto& info : plugins_) {
2908bf80f4bSopenharmony_ci        if (info.second && info.second->destroyPlugin) {
2918bf80f4bSopenharmony_ci            info.second->destroyPlugin(info.first);
2928bf80f4bSopenharmony_ci        }
2938bf80f4bSopenharmony_ci    }
2948bf80f4bSopenharmony_ci    if (sceneUtil_ && gltf2_) {
2958bf80f4bSopenharmony_ci        sceneUtil_->UnregisterSceneLoader(IInterface::Ptr { gltf2_->GetInterface(ISceneLoader::UID) });
2968bf80f4bSopenharmony_ci    }
2978bf80f4bSopenharmony_ci}
2988bf80f4bSopenharmony_ci
2998bf80f4bSopenharmony_civoid GraphicsContext::Init()
3008bf80f4bSopenharmony_ci{
3018bf80f4bSopenharmony_ci    if (initialized_) {
3028bf80f4bSopenharmony_ci        return;
3038bf80f4bSopenharmony_ci    }
3048bf80f4bSopenharmony_ci    auto& engine = context_.GetEngine();
3058bf80f4bSopenharmony_ci
3068bf80f4bSopenharmony_ci    meshUtil_ = make_unique<MeshUtil>(engine);
3078bf80f4bSopenharmony_ci    gltf2_ = make_unique<Gltf2>(*this);
3088bf80f4bSopenharmony_ci    sceneUtil_ = make_unique<SceneUtil>(*this);
3098bf80f4bSopenharmony_ci    renderUtil_ = make_unique<RenderUtil>(*this);
3108bf80f4bSopenharmony_ci    sceneUtil_->RegisterSceneLoader(IInterface::Ptr { gltf2_->GetInterface(ISceneLoader::UID) });
3118bf80f4bSopenharmony_ci    initialized_ = true;
3128bf80f4bSopenharmony_ci
3138bf80f4bSopenharmony_ci    GetPluginRegister().AddListener(*this);
3148bf80f4bSopenharmony_ci
3158bf80f4bSopenharmony_ci    for (auto info : CORE_NS::GetPluginRegister().GetTypeInfos(I3DPlugin::UID)) {
3168bf80f4bSopenharmony_ci        if (auto plugin = static_cast<const I3DPlugin*>(info); plugin && plugin->createPlugin) {
3178bf80f4bSopenharmony_ci            auto token = plugin->createPlugin(*this);
3188bf80f4bSopenharmony_ci            plugins_.push_back({ token, plugin });
3198bf80f4bSopenharmony_ci        }
3208bf80f4bSopenharmony_ci    }
3218bf80f4bSopenharmony_ci}
3228bf80f4bSopenharmony_ci
3238bf80f4bSopenharmony_ciIRenderContext& GraphicsContext::GetRenderContext() const
3248bf80f4bSopenharmony_ci{
3258bf80f4bSopenharmony_ci    return context_;
3268bf80f4bSopenharmony_ci}
3278bf80f4bSopenharmony_ci
3288bf80f4bSopenharmony_ciarray_view<const RenderHandleReference> GraphicsContext::GetRenderNodeGraphs(const IEcs& ecs) const
3298bf80f4bSopenharmony_ci{
3308bf80f4bSopenharmony_ci    // NOTE: gets the render node graphs from built-in RenderSystem
3318bf80f4bSopenharmony_ci    if (IRenderSystem* rs = GetSystem<IRenderSystem>(ecs); rs) {
3328bf80f4bSopenharmony_ci        return rs->GetRenderNodeGraphs();
3338bf80f4bSopenharmony_ci    } else {
3348bf80f4bSopenharmony_ci        return {};
3358bf80f4bSopenharmony_ci    }
3368bf80f4bSopenharmony_ci}
3378bf80f4bSopenharmony_ci
3388bf80f4bSopenharmony_ciISceneUtil& GraphicsContext::GetSceneUtil() const
3398bf80f4bSopenharmony_ci{
3408bf80f4bSopenharmony_ci    return *sceneUtil_;
3418bf80f4bSopenharmony_ci}
3428bf80f4bSopenharmony_ci
3438bf80f4bSopenharmony_ciIMeshUtil& GraphicsContext::GetMeshUtil() const
3448bf80f4bSopenharmony_ci{
3458bf80f4bSopenharmony_ci    return *meshUtil_;
3468bf80f4bSopenharmony_ci}
3478bf80f4bSopenharmony_ci
3488bf80f4bSopenharmony_ciIGltf2& GraphicsContext::GetGltf() const
3498bf80f4bSopenharmony_ci{
3508bf80f4bSopenharmony_ci    return *gltf2_;
3518bf80f4bSopenharmony_ci}
3528bf80f4bSopenharmony_ci
3538bf80f4bSopenharmony_ciIRenderUtil& GraphicsContext::GetRenderUtil() const
3548bf80f4bSopenharmony_ci{
3558bf80f4bSopenharmony_ci    return *renderUtil_;
3568bf80f4bSopenharmony_ci}
3578bf80f4bSopenharmony_ci
3588bf80f4bSopenharmony_ciconst IInterface* GraphicsContext::GetInterface(const Uid& uid) const
3598bf80f4bSopenharmony_ci{
3608bf80f4bSopenharmony_ci    if (uid == IGraphicsContext::UID) {
3618bf80f4bSopenharmony_ci        return static_cast<const IGraphicsContext*>(this);
3628bf80f4bSopenharmony_ci    } else if (uid == IInterface::UID) {
3638bf80f4bSopenharmony_ci        return static_cast<const IInterface*>(static_cast<const IGraphicsContext*>(this));
3648bf80f4bSopenharmony_ci    } else if (uid == IClassRegister::UID) {
3658bf80f4bSopenharmony_ci        return static_cast<const IClassRegister*>(this);
3668bf80f4bSopenharmony_ci    } else if (uid == IClassFactory::UID) {
3678bf80f4bSopenharmony_ci        return static_cast<const IClassFactory*>(this);
3688bf80f4bSopenharmony_ci    }
3698bf80f4bSopenharmony_ci    return nullptr;
3708bf80f4bSopenharmony_ci}
3718bf80f4bSopenharmony_ci
3728bf80f4bSopenharmony_ciIInterface* GraphicsContext::GetInterface(const Uid& uid)
3738bf80f4bSopenharmony_ci{
3748bf80f4bSopenharmony_ci    if (uid == IGraphicsContext::UID) {
3758bf80f4bSopenharmony_ci        return static_cast<IGraphicsContext*>(this);
3768bf80f4bSopenharmony_ci    } else if (uid == IInterface::UID) {
3778bf80f4bSopenharmony_ci        return static_cast<IInterface*>(static_cast<IGraphicsContext*>(this));
3788bf80f4bSopenharmony_ci    } else if (uid == IClassRegister::UID) {
3798bf80f4bSopenharmony_ci        return static_cast<IClassRegister*>(this);
3808bf80f4bSopenharmony_ci    } else if (uid == IClassFactory::UID) {
3818bf80f4bSopenharmony_ci        return static_cast<IClassFactory*>(this);
3828bf80f4bSopenharmony_ci    }
3838bf80f4bSopenharmony_ci    return nullptr;
3848bf80f4bSopenharmony_ci}
3858bf80f4bSopenharmony_ci
3868bf80f4bSopenharmony_civoid GraphicsContext::Ref()
3878bf80f4bSopenharmony_ci{
3888bf80f4bSopenharmony_ci    refcnt_++;
3898bf80f4bSopenharmony_ci}
3908bf80f4bSopenharmony_ci
3918bf80f4bSopenharmony_civoid GraphicsContext::Unref()
3928bf80f4bSopenharmony_ci{
3938bf80f4bSopenharmony_ci    if (--refcnt_ == 0) {
3948bf80f4bSopenharmony_ci        factory_.Destroy();
3958bf80f4bSopenharmony_ci    }
3968bf80f4bSopenharmony_ci}
3978bf80f4bSopenharmony_ci
3988bf80f4bSopenharmony_civoid GraphicsContext::RegisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
3998bf80f4bSopenharmony_ci{
4008bf80f4bSopenharmony_ci    // keep interfaceTypeInfos_ sorted according to UIDs
4018bf80f4bSopenharmony_ci    const auto pos = std::upper_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
4028bf80f4bSopenharmony_ci        [](Uid value, const InterfaceTypeInfo* element) { return value < element->uid; });
4038bf80f4bSopenharmony_ci    interfaceTypeInfos_.insert(pos, &interfaceInfo);
4048bf80f4bSopenharmony_ci}
4058bf80f4bSopenharmony_ci
4068bf80f4bSopenharmony_civoid GraphicsContext::UnregisterInterfaceType(const InterfaceTypeInfo& interfaceInfo)
4078bf80f4bSopenharmony_ci{
4088bf80f4bSopenharmony_ci    if (!interfaceTypeInfos_.empty()) {
4098bf80f4bSopenharmony_ci        const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), interfaceInfo.uid,
4108bf80f4bSopenharmony_ci            [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
4118bf80f4bSopenharmony_ci        if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == interfaceInfo.uid) {
4128bf80f4bSopenharmony_ci            interfaceTypeInfos_.erase(pos);
4138bf80f4bSopenharmony_ci        }
4148bf80f4bSopenharmony_ci    }
4158bf80f4bSopenharmony_ci}
4168bf80f4bSopenharmony_ci
4178bf80f4bSopenharmony_ciarray_view<const InterfaceTypeInfo* const> GraphicsContext::GetInterfaceMetadata() const
4188bf80f4bSopenharmony_ci{
4198bf80f4bSopenharmony_ci    return interfaceTypeInfos_;
4208bf80f4bSopenharmony_ci}
4218bf80f4bSopenharmony_ci
4228bf80f4bSopenharmony_ciconst InterfaceTypeInfo& GraphicsContext::GetInterfaceMetadata(const Uid& uid) const
4238bf80f4bSopenharmony_ci{
4248bf80f4bSopenharmony_ci    static InterfaceTypeInfo invalidType {};
4258bf80f4bSopenharmony_ci
4268bf80f4bSopenharmony_ci    if (!interfaceTypeInfos_.empty()) {
4278bf80f4bSopenharmony_ci        const auto pos = std::lower_bound(interfaceTypeInfos_.cbegin(), interfaceTypeInfos_.cend(), uid,
4288bf80f4bSopenharmony_ci            [](const InterfaceTypeInfo* element, Uid value) { return element->uid < value; });
4298bf80f4bSopenharmony_ci        if ((pos != interfaceTypeInfos_.cend()) && (*pos)->uid == uid) {
4308bf80f4bSopenharmony_ci            return *(*pos);
4318bf80f4bSopenharmony_ci        }
4328bf80f4bSopenharmony_ci    }
4338bf80f4bSopenharmony_ci    return invalidType;
4348bf80f4bSopenharmony_ci}
4358bf80f4bSopenharmony_ci
4368bf80f4bSopenharmony_ciIInterface* GraphicsContext::GetInstance(const BASE_NS::Uid& uid) const
4378bf80f4bSopenharmony_ci{
4388bf80f4bSopenharmony_ci    const auto& data = GetInterfaceMetadata(uid);
4398bf80f4bSopenharmony_ci    if (data.getInterface) {
4408bf80f4bSopenharmony_ci        return data.getInterface(const_cast<GraphicsContext&>(*this), data.token);
4418bf80f4bSopenharmony_ci    }
4428bf80f4bSopenharmony_ci    return nullptr;
4438bf80f4bSopenharmony_ci}
4448bf80f4bSopenharmony_ci
4458bf80f4bSopenharmony_ciIInterface::Ptr GraphicsContext::CreateInstance(const BASE_NS::Uid& uid)
4468bf80f4bSopenharmony_ci{
4478bf80f4bSopenharmony_ci    const auto& data = GetInterfaceMetadata(uid);
4488bf80f4bSopenharmony_ci    if (data.createInterface) {
4498bf80f4bSopenharmony_ci        return IInterface::Ptr { data.createInterface(*this, data.token) };
4508bf80f4bSopenharmony_ci    }
4518bf80f4bSopenharmony_ci    return IInterface::Ptr {};
4528bf80f4bSopenharmony_ci}
4538bf80f4bSopenharmony_ci
4548bf80f4bSopenharmony_civoid GraphicsContext::OnTypeInfoEvent(EventType type, array_view<const ITypeInfo* const> typeInfos)
4558bf80f4bSopenharmony_ci{
4568bf80f4bSopenharmony_ci    if (type == EventType::ADDED) {
4578bf80f4bSopenharmony_ci        for (const auto* info : typeInfos) {
4588bf80f4bSopenharmony_ci            if (info && info->typeUid == I3DPlugin::UID && static_cast<const I3DPlugin*>(info)->createPlugin) {
4598bf80f4bSopenharmony_ci                auto plugin = static_cast<const I3DPlugin*>(info);
4608bf80f4bSopenharmony_ci                if (std::none_of(plugins_.begin(), plugins_.end(),
4618bf80f4bSopenharmony_ci                        [plugin](const pair<PluginToken, const I3DPlugin*>& pluginData) {
4628bf80f4bSopenharmony_ci                            return pluginData.second == plugin;
4638bf80f4bSopenharmony_ci                        })) {
4648bf80f4bSopenharmony_ci                    auto token = plugin->createPlugin(*this);
4658bf80f4bSopenharmony_ci                    plugins_.push_back({ token, plugin });
4668bf80f4bSopenharmony_ci                }
4678bf80f4bSopenharmony_ci            }
4688bf80f4bSopenharmony_ci        }
4698bf80f4bSopenharmony_ci    } else if (type == EventType::REMOVED) {
4708bf80f4bSopenharmony_ci        for (const auto* info : typeInfos) {
4718bf80f4bSopenharmony_ci            if (info && info->typeUid == I3DPlugin::UID) {
4728bf80f4bSopenharmony_ci                auto plugin = static_cast<const I3DPlugin*>(info);
4738bf80f4bSopenharmony_ci                if (auto pos = std::find_if(plugins_.begin(), plugins_.end(),
4748bf80f4bSopenharmony_ci                        [plugin](const pair<PluginToken, const I3DPlugin*>& pluginData) {
4758bf80f4bSopenharmony_ci                            return pluginData.second == plugin;
4768bf80f4bSopenharmony_ci                        });
4778bf80f4bSopenharmony_ci                    pos != plugins_.end()) {
4788bf80f4bSopenharmony_ci                    if (plugin->destroyPlugin) {
4798bf80f4bSopenharmony_ci                        plugin->destroyPlugin(pos->first);
4808bf80f4bSopenharmony_ci                    }
4818bf80f4bSopenharmony_ci                    plugins_.erase(pos);
4828bf80f4bSopenharmony_ci                }
4838bf80f4bSopenharmony_ci            }
4848bf80f4bSopenharmony_ci        }
4858bf80f4bSopenharmony_ci    }
4868bf80f4bSopenharmony_ci}
4878bf80f4bSopenharmony_ci
4888bf80f4bSopenharmony_civoid RegisterTypes(IPluginRegister& pluginRegistry);
4898bf80f4bSopenharmony_civoid UnregisterTypes(IPluginRegister& pluginRegistry);
4908bf80f4bSopenharmony_ci
4918bf80f4bSopenharmony_cinamespace {
4928bf80f4bSopenharmony_ciPluginToken CreatePlugin3D(IRenderContext& context)
4938bf80f4bSopenharmony_ci{
4948bf80f4bSopenharmony_ci    Agp3DPluginState* token = new Agp3DPluginState { context, {}, {}, {}, {}, {} };
4958bf80f4bSopenharmony_ci    auto& registry = *context.GetInterface<IClassRegister>();
4968bf80f4bSopenharmony_ci    for (const auto& info : token->interfaces) {
4978bf80f4bSopenharmony_ci        registry.RegisterInterfaceType(info);
4988bf80f4bSopenharmony_ci    }
4998bf80f4bSopenharmony_ci
5008bf80f4bSopenharmony_ci    IFileManager& fileManager = context.GetEngine().GetFileManager();
5018bf80f4bSopenharmony_ci#if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
5028bf80f4bSopenharmony_ci    // Create engine:// protocol that points to embedded asset files.
5038bf80f4bSopenharmony_ci    fileManager.RegisterFilesystem("rofs3D", fileManager.CreateROFilesystem(BINARY_DATA_FOR_3D, SIZE_OF_DATA_FOR_3D));
5048bf80f4bSopenharmony_ci#endif
5058bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
5068bf80f4bSopenharmony_ci        fileManager.RegisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri, false);
5078bf80f4bSopenharmony_ci    }
5088bf80f4bSopenharmony_ci    context.GetDevice().GetShaderManager().LoadShaderFiles(SHADER_FILE_PATHS);
5098bf80f4bSopenharmony_ci
5108bf80f4bSopenharmony_ci    CreateDefaultResources(context.GetDevice(), token->defaultGpuResources);
5118bf80f4bSopenharmony_ci    {
5128bf80f4bSopenharmony_ci        auto* renderDataConfigurationLoader = CORE_NS::GetInstance<IRenderDataConfigurationLoader>(
5138bf80f4bSopenharmony_ci            *context.GetInterface<IClassRegister>(), UID_RENDER_DATA_CONFIGURATION_LOADER);
5148bf80f4bSopenharmony_ci        auto* dataStore = context.GetRenderDataStoreManager().GetRenderDataStore(POST_PROCESS_DATA_STORE_NAME);
5158bf80f4bSopenharmony_ci        if (renderDataConfigurationLoader && dataStore) {
5168bf80f4bSopenharmony_ci            auto& fileMgr = context.GetEngine().GetFileManager();
5178bf80f4bSopenharmony_ci            constexpr string_view ppPath = POST_PROCESS_PATH;
5188bf80f4bSopenharmony_ci            if (auto dir = fileMgr.OpenDirectory(ppPath); dir) {
5198bf80f4bSopenharmony_ci                for (const auto& entry : dir->GetEntries()) {
5208bf80f4bSopenharmony_ci                    if (entry.type == IDirectory::Entry::Type::FILE) {
5218bf80f4bSopenharmony_ci                        const auto loadedPP =
5228bf80f4bSopenharmony_ci                            renderDataConfigurationLoader->LoadPostProcess(fileMgr, ppPath + entry.name);
5238bf80f4bSopenharmony_ci                        if (loadedPP.loadResult.success) {
5248bf80f4bSopenharmony_ci                            token->defaultPostProcesses.push_back(loadedPP.name);
5258bf80f4bSopenharmony_ci                            auto pod = static_cast<IRenderDataStorePod*>(dataStore);
5268bf80f4bSopenharmony_ci                            pod->CreatePod(
5278bf80f4bSopenharmony_ci                                POST_PROCESS_NAME, loadedPP.name, arrayviewU8(loadedPP.postProcessConfiguration));
5288bf80f4bSopenharmony_ci                        }
5298bf80f4bSopenharmony_ci                    }
5308bf80f4bSopenharmony_ci                }
5318bf80f4bSopenharmony_ci            }
5328bf80f4bSopenharmony_ci        }
5338bf80f4bSopenharmony_ci    }
5348bf80f4bSopenharmony_ci
5358bf80f4bSopenharmony_ci    return token;
5368bf80f4bSopenharmony_ci}
5378bf80f4bSopenharmony_ci
5388bf80f4bSopenharmony_civoid DestroyPlugin3D(PluginToken token)
5398bf80f4bSopenharmony_ci{
5408bf80f4bSopenharmony_ci    Agp3DPluginState* state = static_cast<Agp3DPluginState*>(token);
5418bf80f4bSopenharmony_ci    IFileManager& fileManager = state->renderContext.GetEngine().GetFileManager();
5428bf80f4bSopenharmony_ci
5438bf80f4bSopenharmony_ci    state->defaultGpuResources.clear();
5448bf80f4bSopenharmony_ci    {
5458bf80f4bSopenharmony_ci        auto* renderDataConfigurationLoader = CORE_NS::GetInstance<IRenderDataConfigurationLoader>(
5468bf80f4bSopenharmony_ci            *state->renderContext.GetInterface<IClassRegister>(), UID_RENDER_DATA_CONFIGURATION_LOADER);
5478bf80f4bSopenharmony_ci        auto* dataStore =
5488bf80f4bSopenharmony_ci            state->renderContext.GetRenderDataStoreManager().GetRenderDataStore(POST_PROCESS_DATA_STORE_NAME);
5498bf80f4bSopenharmony_ci        if (renderDataConfigurationLoader && dataStore) {
5508bf80f4bSopenharmony_ci            auto pod = static_cast<IRenderDataStorePod*>(dataStore);
5518bf80f4bSopenharmony_ci            for (const auto& ref : state->defaultPostProcesses) {
5528bf80f4bSopenharmony_ci                pod->DestroyPod(POST_PROCESS_NAME, ref);
5538bf80f4bSopenharmony_ci            }
5548bf80f4bSopenharmony_ci        }
5558bf80f4bSopenharmony_ci        state->defaultPostProcesses.clear();
5568bf80f4bSopenharmony_ci    }
5578bf80f4bSopenharmony_ci    state->renderContext.GetDevice().GetShaderManager().UnloadShaderFiles(SHADER_FILE_PATHS);
5588bf80f4bSopenharmony_ci#if (CORE3D_EMBEDDED_ASSETS_ENABLED == 1)
5598bf80f4bSopenharmony_ci    fileManager.UnregisterFilesystem("rofs3D");
5608bf80f4bSopenharmony_ci#endif
5618bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < countof(RENDER_DATA_PATHS); ++idx) {
5628bf80f4bSopenharmony_ci        fileManager.UnregisterPath(RENDER_DATA_PATHS[idx].protocol, RENDER_DATA_PATHS[idx].uri);
5638bf80f4bSopenharmony_ci    }
5648bf80f4bSopenharmony_ci
5658bf80f4bSopenharmony_ci    auto& registry = *state->renderContext.GetInterface<IClassRegister>();
5668bf80f4bSopenharmony_ci    for (const auto& info : state->interfaces) {
5678bf80f4bSopenharmony_ci        registry.UnregisterInterfaceType(info);
5688bf80f4bSopenharmony_ci    }
5698bf80f4bSopenharmony_ci
5708bf80f4bSopenharmony_ci    delete state;
5718bf80f4bSopenharmony_ci}
5728bf80f4bSopenharmony_ci
5738bf80f4bSopenharmony_ciPluginToken CreateEcsPlugin3D(IEcs& ecs)
5748bf80f4bSopenharmony_ci{
5758bf80f4bSopenharmony_ci    return {};
5768bf80f4bSopenharmony_ci}
5778bf80f4bSopenharmony_ci
5788bf80f4bSopenharmony_civoid DestroyEcsPlugin3D(PluginToken token) {}
5798bf80f4bSopenharmony_ci
5808bf80f4bSopenharmony_ciconstexpr IRenderPlugin RENDER_PLUGIN(CreatePlugin3D, DestroyPlugin3D);
5818bf80f4bSopenharmony_ciconstexpr IEcsPlugin ECS_PLUGIN(CreateEcsPlugin3D, DestroyEcsPlugin3D);
5828bf80f4bSopenharmony_ci} // namespace
5838bf80f4bSopenharmony_ci
5848bf80f4bSopenharmony_ciPluginToken RegisterInterfaces3D(IPluginRegister& pluginRegistry)
5858bf80f4bSopenharmony_ci{
5868bf80f4bSopenharmony_ci    InitRegistry(pluginRegistry);
5878bf80f4bSopenharmony_ci    pluginRegistry.RegisterTypeInfo(RENDER_PLUGIN);
5888bf80f4bSopenharmony_ci    pluginRegistry.RegisterTypeInfo(ECS_PLUGIN);
5898bf80f4bSopenharmony_ci
5908bf80f4bSopenharmony_ci    RegisterTypes(GetPluginRegister());
5918bf80f4bSopenharmony_ci
5928bf80f4bSopenharmony_ci    return &pluginRegistry;
5938bf80f4bSopenharmony_ci}
5948bf80f4bSopenharmony_ci
5958bf80f4bSopenharmony_civoid UnregisterInterfaces3D(PluginToken token)
5968bf80f4bSopenharmony_ci{
5978bf80f4bSopenharmony_ci    IPluginRegister* pluginRegistry = static_cast<IPluginRegister*>(token);
5988bf80f4bSopenharmony_ci
5998bf80f4bSopenharmony_ci    UnregisterTypes(GetPluginRegister());
6008bf80f4bSopenharmony_ci
6018bf80f4bSopenharmony_ci    pluginRegistry->UnregisterTypeInfo(ECS_PLUGIN);
6028bf80f4bSopenharmony_ci    pluginRegistry->UnregisterTypeInfo(RENDER_PLUGIN);
6038bf80f4bSopenharmony_ci}
6048bf80f4bSopenharmony_ciCORE3D_END_NAMESPACE()
605