• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "scene_adapter/scene_adapter.h"
17 
18 #include <dlfcn.h>
19 #include <memory>
20 #include <string_view>
21 
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 
25 #include <base/containers/array_view.h>
26 
27 #include <core/intf_engine.h>
28 #include <core/ecs/intf_system_graph_loader.h>
29 #include <core/engine_info.h>
30 #include <core/image/intf_image_loader_manager.h>
31 #include <core/implementation_uids.h>
32 #include <core/io/intf_file_manager.h>
33 #include <core/namespace.h>
34 #include <core/os/intf_platform.h>
35 #include <core/plugin/intf_plugin_register.h>
36 #include <core/property/intf_property_handle.h>
37 
38 #include <jpg/implementation_uids.h>
39 
40 #include <meta/interface/intf_meta_object_lib.h>
41 #include <meta/interface/intf_task_queue_registry.h>
42 #include <meta/interface/intf_task_queue.h>
43 #include <meta/interface/intf_object.h>
44 #include <meta/interface/intf_object_registry.h>
45 #include <meta/interface/intf_task_queue.h>
46 #include <meta/base/shared_ptr.h>
47 #include <meta/base/interface_macros.h>
48 #include <meta/api/make_callback.h>
49 #include <meta/ext/object.h>
50 
51 #include <png/implementation_uids.h>
52 #include <scene/base/namespace.h>
53 #include <scene/interface/intf_scene.h>
54 #include <3d/ecs/components/environment_component.h>
55 #include <3d/ecs/components/render_handle_component.h>
56 #include <3d/ecs/components/uri_component.h>
57 #include <scene/ext/intf_internal_scene.h>
58 #include <scene/interface/intf_mesh.h>
59 #include <scene/interface/intf_material.h>
60 #include <scene/ext/intf_render_resource.h>
61 #include <scene/interface/intf_camera.h>
62 #include <scene/ext/intf_internal_scene.h>
63 #include <scene/ext/intf_ecs_context.h>
64 
65 #include <scene/ext/intf_ecs_object_access.h>
66 #include <text_3d/implementation_uids.h>
67 #include "ability.h"
68 
69 #include "data_ability_helper.h"
70 
71 #include "napi_base_context.h"
72 
73 #include <render/implementation_uids.h>
74 #include <render/gles/intf_device_gles.h>
75 #include <render/intf_renderer.h>
76 #include <render/intf_render_context.h>
77 #include <render/util/intf_render_util.h>
78 #include <render/vulkan/intf_device_vk.h>
79 
80 #include "3d_widget_adapter_log.h"
81 #include "widget_trace.h"
82 #include "ohos/texture_layer.h"
83 #include "lume_render_config.h"
84 
85 #include <cam_preview/namespace.h>
86 #include <cam_preview/implementation_uids.h>
87 
88 // surface buffer
89 #include <native_buffer.h>
90 #include <surface_buffer.h>
91 #include <securec.h>
92 
93 namespace OHOS::Render3D {
94 #define RETURN_IF_NULL(ptr)                             \
95 do {                                                    \
96     if (!(ptr)) {                                       \
97         WIDGET_LOGE("%s is null in %s", #ptr, __func__); \
98         return;                                         \
99     }                                                   \
100 } while (0)                                              \
101 
102 #define RETURN_FALSE_IF_NULL(ptr)                       \
103 do {                                                    \
104     if (!(ptr)) {                                       \
105         WIDGET_LOGE("%s is null in %s", #ptr, __func__); \
106         return false;                                   \
107     }                                                   \
108 } while (0)                                              \
109 
110 
GetHapInfo()111 HapInfo GetHapInfo()
112 {
113     WIDGET_SCOPED_TRACE("SceneAdapter::GetHapInfo");
114     std::shared_ptr<AbilityRuntime::ApplicationContext> context =
115         AbilityRuntime::ApplicationContext::GetApplicationContext();
116     if (!context) {
117         WIDGET_LOGE("Failed to get application context.");
118         return {};
119     }
120     auto resourceManager = context->GetResourceManager();
121     if (!resourceManager) {
122         WIDGET_LOGE("Failed to get resource manager.");
123         return {};
124     }
125     HapInfo hapInfo;
126     hapInfo.bundleName_ = resourceManager->bundleInfo.first;
127     hapInfo.moduleName_ = resourceManager->bundleInfo.second;
128     hapInfo.resourceManager_ = context->CreateModuleResourceManager(hapInfo.bundleName_, hapInfo.moduleName_);
129     // hapPath
130     std::string hapPath = context->GetBundleCodeDir();
131     hapInfo.hapPath_ = hapPath + "/" + hapInfo.moduleName_ + ".hap";
132     WIDGET_LOGD("bundle %s, module %s, hapPath %s",
133         hapInfo.bundleName_.c_str(),
134         hapInfo.moduleName_.c_str(),
135         hapInfo.hapPath_.c_str());
136 
137     return hapInfo;
138 }
139 
140 using IntfPtr = META_NS::SharedPtrIInterface;
141 using IntfWeakPtr = META_NS::WeakPtrIInterface;
142 
143 struct EngineInstance {
144     void *libHandle_ = nullptr;
145     BASE_NS::shared_ptr<RENDER_NS::IRenderContext> renderContext_;
146     BASE_NS::shared_ptr<CORE_NS::IEngine> engine_;
147 };
148 
149 static EngineInstance engineInstance_;
150 static std::mutex mute;
151 static HapInfo hapInfo_;
152 META_NS::ITaskQueue::Ptr engineThread;
153 META_NS::ITaskQueue::Ptr ioThread;
154 META_NS::ITaskQueue::Ptr releaseThread;
155 META_NS::ITaskQueue::Token renderTask {};
156 
LockCompositor()157 void LockCompositor()
158 {
159     mute.lock();
160 }
161 
UnlockCompositor()162 void UnlockCompositor()
163 {
164     mute.unlock();
165 }
166 
167 static constexpr BASE_NS::Uid ENGINE_THREAD { "2070e705-d061-40e4-bfb7-90fad2c280af" };
168 static constexpr BASE_NS::Uid APP_THREAD { "b2e8cef3-453a-4651-b564-5190f8b5190d" };
169 static constexpr BASE_NS::Uid IO_QUEUE { "be88e9a0-9cd8-45ab-be48-937953dc258f" };
170 static constexpr BASE_NS::Uid JS_RELEASE_THREAD { "3784fa96-b25b-4e9c-bbf1-e897d36f73af" };
171 static constexpr uint32_t FLOAT_TO_BYTE = sizeof(float) / sizeof(uint8_t);
172 static constexpr uint32_t TRANSFORM_MATRIX_SIZE = 16;
173 static const char* const RENDER_DATA_STORE_DEFAULT_STAGING = "RenderDataStoreDefaultStaging";
174 static const char* const ENV_PROPERTIES_BUFFER_NAME = "AR_CAMERA_TRANSFORM_MATRIX";
175 static constexpr uint64_t BUFFER_FENCE_HANDLE_BASE { 0xAAAAAAAAaaaaaaaa };
176 static constexpr uint32_t TIME_OUT_MILLISECONDS = 5000;
177 
178 template<typename T>
LoadFunc(T & fn,const char * fName,void * handle)179 bool LoadFunc(T &fn, const char *fName, void* handle)
180 {
181     fn = reinterpret_cast<T>(dlsym(handle, fName));
182     if (fn == nullptr) {
183         WIDGET_LOGE("%s open %s", __func__, dlerror());
184         return false;
185     }
186     return true;
187 }
188 
~SceneAdapter()189 SceneAdapter::~SceneAdapter()
190 {
191 }
192 
SceneAdapter()193 SceneAdapter::SceneAdapter()
194 {
195     WIDGET_LOGD("scene adapter Impl create");
196 }
197 
LoadEngineLib()198 bool SceneAdapter::LoadEngineLib()
199 {
200     if (engineInstance_.libHandle_ != nullptr) {
201         WIDGET_LOGD("%s, already loaded", __func__);
202         return true;
203     }
204 
205     #define TO_STRING(name) #name
206     #define LIB_NAME(name) TO_STRING(name)
207     constexpr std::string_view lib { LIB_NAME(LIB_ENGINE_CORE)".so" };
208     engineInstance_.libHandle_ = dlopen(lib.data(), RTLD_LAZY);
209 
210     if (engineInstance_.libHandle_ == nullptr) {
211         WIDGET_LOGE("%s, open lib fail %s", __func__, dlerror());
212     }
213     #undef TO_STRING
214     #undef LIB_NAME
215 
216     #define LOAD_FUNC(fn, name) LoadFunc<decltype(fn)>(fn, name, engineInstance_.libHandle_)
217     if (!(LOAD_FUNC(CORE_NS::CreatePluginRegistry,
218         "_ZN4Core20CreatePluginRegistryERKNS_18PlatformCreateInfoE")
219         && LOAD_FUNC(CORE_NS::GetPluginRegister, "_ZN4Core17GetPluginRegisterEv")
220         && LOAD_FUNC(CORE_NS::IsDebugBuild, "_ZN4Core12IsDebugBuildEv")
221         && LOAD_FUNC(CORE_NS::GetVersion, "_ZN4Core13GetVersionRevEv"))) {
222         return false;
223     }
224     #undef LOAD_FUNC
225 
226     return true;
227 }
228 
LoadPlugins(const CORE_NS::PlatformCreateInfo & platformCreateInfo)229 bool SceneAdapter::LoadPlugins(const CORE_NS::PlatformCreateInfo& platformCreateInfo)
230 {
231     if (engineInstance_.libHandle_) {
232         WIDGET_LOGI("%s, already loaded", __func__);
233         return true;
234     }
235     if (!LoadEngineLib()) {
236         return false;
237     }
238     WIDGET_LOGD("load engine suceess!");
239 
240     BASE_NS::vector<BASE_NS::Uid> DefaultPluginVector = {
241         CAM_PREVIEW_NS::UID_CAMERA_PREVIEW_PLUGIN,
242         SCENE_NS::UID_SCENE_PLUGIN,
243 #if defined(USE_LIB_PNG_JPEG_DYNAMIC_PLUGIN) && USE_LIB_PNG_JPEG_DYNAMIC_PLUGIN
244         JPGPlugin::UID_JPG_PLUGIN,
245         PNGPlugin::UID_PNG_PLUGIN,
246 #endif
247     };
248     const BASE_NS::array_view<BASE_NS::Uid> DefaultPluginList(DefaultPluginVector.data(), DefaultPluginVector.size());
249     CORE_NS::CreatePluginRegistry(platformCreateInfo);
250     if (!CORE_NS::GetPluginRegister().LoadPlugins(DefaultPluginList)) {
251         WIDGET_LOGE("fail to load scene widget plugin");
252         return false;
253     }
254     WIDGET_LOGI("load plugin success");
255     return true;
256 }
257 
InitEngine(CORE_NS::PlatformCreateInfo platformCreateInfo)258 bool SceneAdapter::InitEngine(CORE_NS::PlatformCreateInfo platformCreateInfo)
259 {
260     auto& tr = META_NS::GetTaskQueueRegistry();
261     auto& obr = META_NS::GetObjectRegistry();
262 
263     engineThread = tr.GetTaskQueue(ENGINE_THREAD);
264     if (!engineThread) {
265         engineThread = obr.Create<META_NS::ITaskQueue>(META_NS::ClassId::ThreadedTaskQueue);
266         tr.RegisterTaskQueue(engineThread, ENGINE_THREAD);
267     }
268     ioThread = tr.GetTaskQueue(IO_QUEUE);
269     if (!ioThread) {
270         ioThread = obr.Create<META_NS::ITaskQueue>(META_NS::ClassId::ThreadedTaskQueue);
271         tr.RegisterTaskQueue(ioThread, IO_QUEUE);
272     }
273     releaseThread = tr.GetTaskQueue(JS_RELEASE_THREAD);
274     if (!releaseThread) {
275         auto &obr = META_NS::GetObjectRegistry();
276         releaseThread = obr.Create<META_NS::ITaskQueue>(META_NS::ClassId::ThreadedTaskQueue);
277         tr.RegisterTaskQueue(releaseThread, JS_RELEASE_THREAD);
278     }
279 
280     bool inited = false;
281     auto initCheck = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([&inited]() {
282         inited = (engineInstance_.engine_ != nullptr);
283         return META_NS::IAny::Ptr {};
284     });
285     engineThread->AddWaitableTask(initCheck)->Wait();
286     if (inited) {
287         WIDGET_LOGI("engine already inited");
288         return true;
289     }
290 
291     auto engineInit = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([platformCreateInfo]() {
292         auto &obr = META_NS::GetObjectRegistry();
293         // Initialize lumeengine/render etc
294         CORE_NS::EngineCreateInfo engineCreateInfo{platformCreateInfo, {}, {}};
295         if (auto factory = CORE_NS::GetInstance<CORE_NS::IEngineFactory>(CORE_NS::UID_ENGINE_FACTORY)) {
296             engineInstance_.engine_.reset(factory->Create(engineCreateInfo).get());
297         } else {
298             WIDGET_LOGE("could not get engine factory");
299             return META_NS::IAny::Ptr {};
300         }
301         if (!engineInstance_.engine_) {
302             WIDGET_LOGE("get engine fail");
303             return META_NS::IAny::Ptr {};
304         }
305         auto &fileManager = engineInstance_.engine_->GetFileManager();
306         const auto &platform = engineInstance_.engine_->GetPlatform();
307         platform.RegisterDefaultPaths(fileManager);
308         engineInstance_.engine_->Init();
309 
310         engineInstance_.renderContext_.reset(CORE_NS::CreateInstance<RENDER_NS::IRenderContext>(
311             *engineInstance_.engine_->GetInterface<Core::IClassFactory>(), RENDER_NS::UID_RENDER_CONTEXT).get());
312 
313         RENDER_NS::RenderCreateInfo renderCreateInfo{};
314         RENDER_NS::BackendExtraGLES glExtra{};
315         Render::DeviceCreateInfo deviceCreateInfo{};
316 
317         std::string backendProp = LumeRenderConfig::GetInstance().renderBackend_ == "force_vulkan" ? "vulkan" : "gles";
318         if (backendProp == "vulkan") {
319             WIDGET_LOGI("backend vulkan");
320         } else {
321             WIDGET_LOGI("backend gles");
322             glExtra.depthBits = 24; // 24 : bits size
323             glExtra.sharedContext = EGL_NO_CONTEXT;
324             deviceCreateInfo.backendType = RENDER_NS::DeviceBackendType::OPENGLES;
325             deviceCreateInfo.backendConfiguration = &glExtra;
326             renderCreateInfo.applicationInfo = {};
327             renderCreateInfo.deviceCreateInfo = deviceCreateInfo;
328         }
329 
330         auto rrc = engineInstance_.renderContext_->Init(renderCreateInfo);
331         if (rrc != RENDER_NS::RenderResultCode::RENDER_SUCCESS) {
332             WIDGET_LOGE("Failed to create render context");
333             return META_NS::IAny::Ptr {};
334         }
335 
336         // Save the stuff to the default object context.
337         auto engineThread = META_NS::GetTaskQueueRegistry().GetTaskQueue(ENGINE_THREAD);
338         // thats the javascript thread...
339         auto appThread = engineThread;
340         auto doc = interface_cast<META_NS::IMetadata>(obr.GetDefaultObjectContext());
341         if (doc == nullptr) {
342             WIDGET_LOGE("nullptr from interface_cast");
343             return META_NS::IAny::Ptr {};
344         }
345         auto flags = META_NS::ObjectFlagBits::INTERNAL | META_NS::ObjectFlagBits::NATIVE;
346 
347         doc->AddProperty(META_NS::ConstructProperty<IntfPtr>("RenderContext", nullptr, flags));
348         doc->AddProperty(META_NS::ConstructProperty<IntfPtr>("EngineQueue", nullptr, flags));
349         doc->AddProperty(META_NS::ConstructProperty<IntfPtr>("AppQueue", nullptr, flags));
350         doc->AddProperty(META_NS::ConstructArrayProperty<IntfWeakPtr>("Scenes", {}, flags));
351 
352         doc->GetProperty<META_NS::SharedPtrIInterface>("EngineQueue")->SetValue(engineThread);
353         doc->GetProperty<META_NS::SharedPtrIInterface>("AppQueue")->SetValue(appThread);
354         doc->GetProperty<META_NS::SharedPtrIInterface>("RenderContext")->SetValue(engineInstance_.renderContext_);
355 
356         WIDGET_LOGD("register shader paths");
357         static constexpr const RENDER_NS::IShaderManager::ShaderFilePathDesc desc { "shaders://" };
358         engineInstance_.engine_->GetFileManager().RegisterPath("shaders", "OhosRawFile://shaders", false);
359         engineInstance_.renderContext_->GetDevice().GetShaderManager().LoadShaderFiles(desc);
360 
361         engineInstance_.engine_->GetFileManager().RegisterPath("appshaders", "OhosRawFile://shaders", false);
362         engineInstance_.engine_->GetFileManager().RegisterPath("apppipelinelayouts",
363             "OhosRawFile:///pipelinelayouts/", true);
364         engineInstance_.engine_->GetFileManager().RegisterPath("fonts", "OhosRawFile:///fonts", true);
365 
366         static constexpr const RENDER_NS::IShaderManager::ShaderFilePathDesc desc1 { "appshaders://" };
367         engineInstance_.renderContext_->GetDevice().GetShaderManager().LoadShaderFiles(desc1);
368 
369         // "render" one frame. this is to initialize all the default resources etc.
370         // if we never render a single frame, we will get "false positive" leaks of gpu resources.
371         engineInstance_.renderContext_->GetRenderer().RenderFrame({});
372         WIDGET_LOGI("init engine success");
373         return META_NS::IAny::Ptr {};
374     });
375     engineThread->AddWaitableTask(engineInit)->Wait();
376     return true;
377 }
378 
SetSceneObj(META_NS::IObject::Ptr pt)379 void SceneAdapter::SetSceneObj(META_NS::IObject::Ptr pt)
380 {
381     WIDGET_LOGD("SceneAdapterImpl::SetSceneObj");
382     sceneWidgetObj_ = pt;
383 }
384 
CreateTextureLayer()385 std::shared_ptr<TextureLayer> SceneAdapter::CreateTextureLayer()
386 {
387     WIDGET_LOGI("SceneAdapter::CreateTextureLayer: %u", key_);
388     auto cb = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this]() {
389         textureLayer_ = std::make_shared<TextureLayer>(key_);
390         key_++;
391         return META_NS::IAny::Ptr {};
392     });
393     if (engineThread) {
394         engineThread->AddWaitableTask(cb)->Wait();
395     } else {
396         WIDGET_LOGE("ENGINE_THREAD not ready in CreateTextureLayer");
397     }
398     return textureLayer_;
399 }
400 
LoadPluginsAndInit()401 bool SceneAdapter::LoadPluginsAndInit()
402 {
403     LockCompositor(); // an APP_FREEZE here, so add lock just in case, but suspect others' error
404     WIDGET_LOGI("scene adapter loadPlugins");
405 
406     if (hapInfo_.hapPath_ == "") {
407         hapInfo_ = GetHapInfo();
408     }
409 
410     #define TO_STRING(name) #name
411     #define PLATFORM_PATH_NAME(name) TO_STRING(name)
412     CORE_NS::PlatformCreateInfo platformCreateInfo {
413         PLATFORM_PATH_NAME(PLATFORM_CORE_ROOT_PATH),
414         PLATFORM_PATH_NAME(PLATFORM_CORE_PLUGIN_PATH),
415         PLATFORM_PATH_NAME(PLATFORM_APP_ROOT_PATH),
416         PLATFORM_PATH_NAME(PLATFORM_APP_PLUGIN_PATH),
417         hapInfo_.hapPath_.c_str(),
418         hapInfo_.bundleName_.c_str(),
419         hapInfo_.moduleName_.c_str(),
420         hapInfo_.resourceManager_
421     };
422     #undef TO_STRING
423     #undef PLATFORM_PATH_NAME
424     if (!LoadPlugins(platformCreateInfo)) {
425         UnlockCompositor();
426         return false;
427     }
428 
429     if (!InitEngine(platformCreateInfo)) {
430         UnlockCompositor();
431         return false;
432     }
433 
434     CreateRenderFunction();
435     UnlockCompositor();
436     return true;
437 }
438 
OnWindowChange(const WindowChangeInfo & windowChangeInfo)439 void SceneAdapter::OnWindowChange(const WindowChangeInfo &windowChangeInfo)
440 {
441     WIDGET_LOGI("SceneAdapter::OnWindowchange");
442     auto cb = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this, &windowChangeInfo]() {
443         if (!textureLayer_) {
444             WIDGET_LOGE("textureLayer is null in OnWindowChange");
445             return META_NS::IAny::Ptr {};
446         }
447         textureLayer_->OnWindowChange(windowChangeInfo);
448         const auto& textureInfo = textureLayer_->GetTextureInfo();
449         auto& device = engineInstance_.renderContext_->GetDevice();
450         RENDER_NS::SwapchainCreateInfo swapchainCreateInfo {
451             0U,
452             RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_COLOR_BUFFER_BIT |
453             RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_DEPTH_BUFFER_BIT |
454             RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_SRGB_BIT,
455             RENDER_NS::ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
456             {
457                 reinterpret_cast<uintptr_t>(textureInfo.nativeWindow_),
458                 reinterpret_cast<uintptr_t>(static_cast<const RENDER_NS::DevicePlatformDataGLES&>(
459                     device.GetPlatformData()).display)
460             }
461         };
462         swapchainHandle_ = device.CreateSwapchainHandle(swapchainCreateInfo, swapchainHandle_, {});
463         if (auto scene = interface_pointer_cast<SCENE_NS::IScene>(sceneWidgetObj_)) {
464             auto cams = scene->GetCameras().GetResult();
465             if (!cams.empty()) {
466                 for (auto c : cams) {
467                     AttachSwapchain(interface_pointer_cast<META_NS::IObject>(c));
468                 }
469             }
470         }
471         return META_NS::IAny::Ptr {};
472     });
473 
474     if (engineThread) {
475         engineThread->AddWaitableTask(cb)->Wait();
476     } else {
477         WIDGET_LOGE("ENGINE_THREAD not ready in OnWindowChange");
478     }
479 }
480 
CreateRenderFunction()481 void SceneAdapter::CreateRenderFunction()
482 {
483     propSyncSync_ = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this]() {
484         PropSync();
485         return META_NS::IAny::Ptr {};
486     });
487     // Task used for oneshot renders
488     singleFrameAsync_ = META_NS::MakeCallback<META_NS::ITaskQueueTask>([this]() {
489         RenderFunction();
490         return 0;
491     });
492     // Task used for oneshot synchronous renders
493     singleFrameSync_ = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this]() {
494         RenderFunction();
495         return META_NS::IAny::Ptr {};
496     });
497 }
498 
DeinitRenderThread()499 void SceneAdapter::DeinitRenderThread()
500 {
501     RETURN_IF_NULL(engineThread);
502     if (renderTask) {
503         engineThread->CancelTask(renderTask);
504         renderTask = nullptr;
505     }
506     auto engine_deinit = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([]() {
507         // destroy all swapchains
508         auto &obr = META_NS::GetObjectRegistry();
509         auto doc = interface_cast<META_NS::IMetadata>(obr.GetDefaultObjectContext());
510         if (doc == nullptr) {
511             WIDGET_LOGE("nullptr from interface_cast");
512             return META_NS::IAny::Ptr {};
513         }
514         // hmm.. this is somewhat uncool
515         {
516             auto p1 = doc->GetProperty<IntfPtr>("EngineQueue");
517             doc->RemoveProperty(p1);
518             auto p2 = doc->GetProperty<IntfPtr>("AppQueue");
519             doc->RemoveProperty(p2);
520             auto p3 = doc->GetProperty<IntfPtr>("RenderContext");
521             doc->RemoveProperty(p3);
522         }
523 
524         doc->GetArrayProperty<IntfWeakPtr>("Scenes")->Reset();
525         engineInstance_.renderContext_.reset();
526         engineInstance_.engine_.reset();
527 
528         return META_NS::IAny::Ptr{};
529     });
530     engineThread->AddWaitableTask(engine_deinit)->Wait();
531     auto &tr = META_NS::GetTaskQueueRegistry();
532     tr.UnregisterTaskQueue(ENGINE_THREAD);
533     engineThread.reset();
534     tr.UnregisterTaskQueue(IO_QUEUE);
535     ioThread.reset();
536     tr.UnregisterTaskQueue(JS_RELEASE_THREAD);
537     releaseThread.reset();
538 }
539 
ShutdownPluginRegistry()540 void SceneAdapter::ShutdownPluginRegistry()
541 {
542     if (engineInstance_.libHandle_ == nullptr) {
543         return;
544     }
545     dlclose(engineInstance_.libHandle_);
546     engineInstance_.libHandle_ = nullptr;
547 
548     CORE_NS::GetPluginRegister = nullptr;
549     CORE_NS::CreatePluginRegistry = nullptr;
550     CORE_NS::IsDebugBuild = nullptr;
551     CORE_NS::GetVersion = nullptr;
552 }
553 
PropSync()554 void SceneAdapter::PropSync()
555 {
556     auto scene = interface_pointer_cast<SCENE_NS::IScene>(sceneWidgetObj_);
557     if (!scene) {
558         return;
559     }
560     auto internal = scene->GetInternalScene();
561     if (!internal) {
562         return;
563     }
564     internal->SyncProperties();
565 }
566 
RenderFunction()567 void SceneAdapter::RenderFunction()
568 {
569     WIDGET_SCOPED_TRACE("SceneAdapter::RenderFunction");
570     auto rc = engineInstance_.renderContext_;
571     RETURN_IF_NULL(rc);
572     RETURN_IF_NULL(sceneWidgetObj_);
573     auto scene = interface_pointer_cast<SCENE_NS::IScene>(sceneWidgetObj_);
574     RETURN_IF_NULL(scene);
575     if (!bitmap_) {
576         auto cams = scene->GetCameras().GetResult();
577         if (!cams.empty()) {
578             for (auto c : cams) {
579                 AttachSwapchain(interface_pointer_cast<META_NS::IObject>(c));
580             }
581         }
582     }
583     scene->GetInternalScene()->Update(false);
584     bool receiveBuffer = receiveBuffer_;
585     receiveBuffer_ = false;
586 
587     auto& renderFrameUtil = rc->GetRenderUtil().GetRenderFrameUtil();
588     auto backendType = rc->GetDevice().GetBackendType();
589     if (receiveBuffer) {
590         if (sfBufferInfo_.acquireFence_) {
591             int32_t ret = sfBufferInfo_.acquireFence_->Wait(TIME_OUT_MILLISECONDS);
592             if (sfBufferInfo_.acquireFence_->Get() >= 0 && ret < 0) {
593                 WIDGET_LOGE("wait fence error: %d", ret);
594             }
595             sfBufferInfo_.acquireFence_ = nullptr;
596         }
597         if (backendType == RENDER_NS::DeviceBackendType::VULKAN) {
598             // NOTE: vulkan not implemented yet
599             WIDGET_LOGD("vulkan fence");
600         } else if (backendType == RENDER_NS::DeviceBackendType::OPENGLES) {
601             RENDER_NS::IRenderFrameUtil::SignalData signalData;
602             signalData.signaled = false;
603             signalData.signalResourceType = RENDER_NS::IRenderFrameUtil::SignalResourceType::GPU_FENCE;
604             signalData.handle = bufferFenceHandle_;
605             renderFrameUtil.AddGpuSignal(signalData);
606         }
607     }
608     rc->GetRenderer().RenderDeferredFrame();
609     if (receiveBuffer) {
610         auto addedSD = renderFrameUtil.GetFrameGpuSignalData();
611         for (const auto& ref : addedSD) {
612             if (ref.handle.GetHandle().id == bufferFenceHandle_.GetHandle().id) {
613                 int32_t fenceFileDesc = CreateFenceFD(ref, rc->GetDevice());
614                 sfBufferInfo_.fn_(fenceFileDesc);
615                 break;
616             }
617         }
618     }
619 }
620 
CreateFenceFD(const RENDER_NS::IRenderFrameUtil::SignalData & signalData,RENDER_NS::IDevice & device)621 int32_t SceneAdapter::CreateFenceFD(
622     const RENDER_NS::IRenderFrameUtil::SignalData &signalData, RENDER_NS::IDevice &device)
623 {
624     int32_t fenceFileDesc = -1;
625     auto backendType = device.GetBackendType();
626     if (backendType == RENDER_NS::DeviceBackendType::VULKAN) {
627         // NOTE: vulkan not implemented yet
628         WIDGET_LOGD("vulkan fence");
629     } else if (backendType == RENDER_NS::DeviceBackendType::OPENGLES) {
630         const auto disp = static_cast<const RENDER_NS::DevicePlatformDataGLES &>(device.GetPlatformData()).display;
631         EGLSyncKHR sync = reinterpret_cast<EGLSyncKHR>(static_cast<uintptr_t>(signalData.gpuSignalResourceHandle));
632         if (sync == EGL_NO_SYNC_KHR) {
633             WIDGET_LOGE("invalid EGLSync from signal data");
634             return fenceFileDesc;
635         }
636         fenceFileDesc = eglDupNativeFenceFDANDROID(disp, sync);
637         if (fenceFileDesc == -1) {
638             WIDGET_LOGE("eglDupNativeFence fail");
639         }
640     } else {
641         WIDGET_LOGE("no supported backend");
642     }
643     return fenceFileDesc;
644 }
645 
RenderFrame(bool needsSyncPaint)646 void SceneAdapter::RenderFrame(bool needsSyncPaint)
647 {
648     if (!engineThread) {
649         WIDGET_LOGE("no engineThread for Render");
650         return;
651     }
652     if (renderTask) {
653         engineThread->CancelTask(renderTask);
654         renderTask = nullptr;
655     }
656 
657     if (!singleFrameAsync_ || !singleFrameSync_ || !propSyncSync_) {
658         CreateRenderFunction();
659     }
660 
661     if (propSyncSync_) {
662         WIDGET_SCOPED_TRACE("SceneAdapter::propSyncSync_");
663         engineThread->AddWaitableTask(propSyncSync_)->Wait();
664     }
665 
666     if (!needsSyncPaint && singleFrameAsync_) {
667         renderTask = engineThread->AddTask(singleFrameAsync_);
668     } else if (singleFrameSync_) {
669         engineThread->AddWaitableTask(singleFrameSync_)->Wait();
670     } else {
671         WIDGET_LOGE("No render function available.");
672     }
673 }
674 
NeedsRepaint()675 bool SceneAdapter::NeedsRepaint()
676 {
677     return needsRepaint_;
678 }
679 
SetNeedsRepaint(bool needsRepaint)680 void SceneAdapter::SetNeedsRepaint(bool needsRepaint)
681 {
682     needsRepaint_ = needsRepaint;
683 }
684 
Deinit()685 void SceneAdapter::Deinit()
686 {
687     RETURN_IF_NULL(engineThread);
688     WIDGET_LOGI("SceneAdapter::Deinit");
689     auto func = META_NS::MakeCallback<META_NS::ITaskQueueWaitableTask>([this]() {
690         if (bitmap_) {
691             auto scene = interface_pointer_cast<SCENE_NS::IScene>(sceneWidgetObj_);
692             if (!scene) {
693                 return META_NS::IAny::Ptr {};
694             }
695             if (auto i = interface_cast<SCENE_NS::IRenderResource>(bitmap_)) {
696                 i->SetRenderHandle(scene->GetInternalScene(), swapchainHandle_);
697             }
698         }
699         if (swapchainHandle_) {
700             auto& device = engineInstance_.renderContext_->GetDevice();
701             device.DestroySwapchain(swapchainHandle_);
702         }
703         swapchainHandle_ = {};
704         return META_NS::IAny::Ptr {};
705     });
706     engineThread->AddWaitableTask(func)->Wait();
707 
708     sceneWidgetObj_.reset();
709     singleFrameAsync_.reset();
710     singleFrameSync_.reset();
711     propSyncSync_.reset();
712     needsRepaint_ = false;
713 }
714 
AttachSwapchain(META_NS::IObject::Ptr cameraObj)715 void SceneAdapter::AttachSwapchain(META_NS::IObject::Ptr cameraObj)
716 {
717     WIDGET_LOGI("attach swapchain");
718     if (!swapchainHandle_) {
719         return;
720     }
721     auto node = interface_cast<SCENE_NS::INode>(cameraObj);
722     if (node == nullptr) {
723         WIDGET_LOGE("cast cameraObj failed in AttachSwapchain.");
724         return;
725     }
726     auto scene = node->GetScene();
727     auto camera = interface_pointer_cast<SCENE_NS::ICamera>(cameraObj);
728     if (!camera->IsActive()) {
729         return;
730     }
731 
732     bitmap_ = META_NS::GetObjectRegistry().Create<SCENE_NS::IRenderTarget>(SCENE_NS::ClassId::Bitmap);
733     if (auto i = interface_cast<SCENE_NS::IRenderResource>(bitmap_)) {
734         i->SetRenderHandle(scene->GetInternalScene(), swapchainHandle_);
735     }
736     camera->SetRenderTarget(bitmap_);
737 }
738 
739 namespace {
CreateOESTextureHandle(CORE_NS::IEcs::Ptr ecs,BASE_NS::shared_ptr<RENDER_NS::IRenderContext> renderContext,const SurfaceBufferInfo & surfaceBufferInfo)740 RENDER_NS::RenderHandleReference CreateOESTextureHandle(CORE_NS::IEcs::Ptr ecs,
741     BASE_NS::shared_ptr<RENDER_NS::IRenderContext> renderContext, const SurfaceBufferInfo &surfaceBufferInfo)
742 {
743     if (!ecs || !renderContext) {
744         WIDGET_LOGE("null ecs or renderContext");
745         return {};
746     }
747     auto surfaceBuffer = surfaceBufferInfo.sfBuffer_;
748     if (!surfaceBuffer) {
749         WIDGET_LOGE("surface buffer null");
750         return {};
751     }
752     auto nativeBuffer = surfaceBuffer->SurfaceBufferToNativeBuffer();
753     if (!nativeBuffer) {
754         WIDGET_LOGE("surface buffer to native buffer fail");
755         return {};
756     }
757 
758     std::shared_ptr<RENDER_NS::BackendSpecificImageDesc> data = nullptr;
759     auto backendType = renderContext->GetDevice().GetBackendType();
760     if (backendType == RENDER_NS::DeviceBackendType::VULKAN) {
761         // NOTE: vulkan not implemented yet
762         data = std::make_shared<RENDER_NS::ImageDescVk>();
763         auto vkData = std::static_pointer_cast<RENDER_NS::ImageDescVk>(data);
764         vkData->platformHwBuffer = reinterpret_cast<uintptr_t>(nativeBuffer);
765     } else if (backendType == RENDER_NS::DeviceBackendType::OPENGLES) {
766         data = std::make_shared<RENDER_NS::ImageDescGLES>();
767         auto glesData = std::static_pointer_cast<RENDER_NS::ImageDescGLES>(data);
768         glesData->type = GL_TEXTURE_EXTERNAL_OES;
769         glesData->platformHwBuffer = reinterpret_cast<uintptr_t>(nativeBuffer);
770     }
771 
772     if (!data) {
773         WIDGET_LOGE("create ImageDesc based on backend fail!");
774         return {};
775     }
776 
777     auto &gpuResourceManager = renderContext->GetDevice().GetGpuResourceManager();
778     auto handle = gpuResourceManager.CreateView("AR_CAMERA_PREVIEW", {}, *data);
779 
780     return handle;
781 }
782 }  // namespace
783 
InitEnvironmentResource(const uint32_t bufferSize)784 void SceneAdapter::InitEnvironmentResource(const uint32_t bufferSize)
785 {
786     WIDGET_LOGI("Init resource for camera view");
787     auto scene = interface_pointer_cast<SCENE_NS::IScene>(sceneWidgetObj_);
788     RETURN_IF_NULL(scene);
789     auto internalScene = scene->GetInternalScene();
790     RETURN_IF_NULL(internalScene);
791     auto ecs = internalScene->GetEcsContext().GetNativeEcs();
792     RETURN_IF_NULL(ecs);
793     auto renderContext = engineInstance_.renderContext_;
794     RETURN_IF_NULL(renderContext);
795 
796     bufferFenceHandle_ = RENDER_NS::RenderHandleReference{{static_cast<uint64_t>(key_) + BUFFER_FENCE_HANDLE_BASE}, {}};
797 
798     auto envManager = CORE_NS::GetManager<CORE3D_NS::IEnvironmentComponentManager>(*ecs);
799     RETURN_IF_NULL(envManager);
800     const auto &shaderMgr = renderContext->GetDevice().GetShaderManager();
801     auto &entityManager = (*ecs).GetEntityManager();
802     auto renderHandleManager = CORE_NS::GetManager<CORE3D_NS::IRenderHandleComponentManager>(*ecs);
803     RETURN_IF_NULL(renderHandleManager);
804     auto uriManager = CORE_NS::GetManager<CORE3D_NS::IUriComponentManager>(*ecs);
805     RETURN_IF_NULL(uriManager);
806 
807     CORE_NS::EntityReference shaderEF = entityManager.CreateReferenceCounted();
808     renderHandleManager->Create(shaderEF);
809     BASE_NS::string_view shaderUri = "campreviewshaders://shader/camera_stream.shader";
810     renderContext->GetDevice().GetShaderManager().LoadShaderFile(shaderUri.data());
811     if (auto renderEntityHandle = renderHandleManager->Write(shaderEF)) {
812         renderEntityHandle->reference = shaderMgr.GetShaderHandle(shaderUri);
813     }
814     uriManager->Create(shaderEF);
815     if (auto uriHandle = uriManager->Write(shaderEF)) {
816         uriHandle->uri = shaderUri;
817     }
818 
819     RENDER_NS::GpuBufferDesc envBufferDesc{
820         RENDER_NS::CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT | RENDER_NS::CORE_BUFFER_USAGE_TRANSFER_DST_BIT,
821         RENDER_NS::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | RENDER_NS::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT,
822         RENDER_NS::CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
823         bufferSize};
824     BASE_NS::array_view<const uint8_t> transData(
825         reinterpret_cast<const uint8_t *>(sfBufferInfo_.transformMatrix_.data()), bufferSize);
826     camTransBufferHandle_ =
827         renderContext->GetDevice().GetGpuResourceManager().Create(ENV_PROPERTIES_BUFFER_NAME, envBufferDesc, transData);
828     CORE_NS::EntityReference transBufferEF = entityManager.CreateReferenceCounted();
829     renderHandleManager->Create(transBufferEF);
830     if (auto renderEntityHandle = renderHandleManager->Write(transBufferEF)) {
831         renderEntityHandle->reference = camTransBufferHandle_;
832     }
833 
834     CORE_NS::EntityReference transBufferEF2 = entityManager.CreateReferenceCounted();
835     renderHandleManager->Create(transBufferEF2);
836     if (auto renderEntityHandle = renderHandleManager->Write(transBufferEF2)) {
837         renderEntityHandle->reference = camTransBufferHandle_;
838     }
839 
840     CORE_NS::EntityReference transBufferEF3 = entityManager.CreateReferenceCounted();
841     renderHandleManager->Create(transBufferEF3);
842     if (auto renderEntityHandle = renderHandleManager->Write(transBufferEF3)) {
843         renderEntityHandle->reference = camTransBufferHandle_;
844     }
845 
846     camImageEF_ = entityManager.CreateReferenceCounted();
847     renderHandleManager->Create(camImageEF_);
848 
849     if (auto rc = scene->RenderConfiguration()->GetValue()) {
850         if (auto env = rc->Environment()->GetValue()) {
851             CORE_NS::Entity environmentEntity = interface_pointer_cast<SCENE_NS::IEcsObjectAccess>(env)->
852                 GetEcsObject()->GetEntity();
853             if (auto envDataHandle = envManager->Write(environmentEntity)) {
854                 CORE3D_NS::EnvironmentComponent &envComponent = *envDataHandle;
855                 envComponent.background = CORE3D_NS::EnvironmentComponent::Background::IMAGE;
856                 envComponent.shader = shaderEF;
857                 envComponent.customResources.push_back({camImageEF_});
858                 envComponent.customResources.push_back({transBufferEF});
859                 envComponent.customResources.push_back({transBufferEF2});
860                 envComponent.customResources.push_back({transBufferEF3});
861             }
862         }
863     }
864     if (!renderDataStoreDefaultStaging_) {
865         renderDataStoreDefaultStaging_ = BASE_NS::refcnt_ptr<RENDER_NS::IRenderDataStoreDefaultStaging>(
866             static_cast<RENDER_NS::IRenderDataStoreDefaultStaging *>(
867             renderContext->GetRenderDataStoreManager().GetRenderDataStore(RENDER_DATA_STORE_DEFAULT_STAGING).get()));
868         RETURN_IF_NULL(renderDataStoreDefaultStaging_);
869     }
870 }
871 
UpdateSurfaceBuffer()872 void SceneAdapter::UpdateSurfaceBuffer()
873 {
874     auto scene = interface_pointer_cast<SCENE_NS::IScene>(sceneWidgetObj_);
875     RETURN_IF_NULL(scene);
876     auto internalScene = scene->GetInternalScene();
877     RETURN_IF_NULL(internalScene);
878     auto ecs = internalScene->GetEcsContext().GetNativeEcs();
879     RETURN_IF_NULL(ecs);
880     auto renderContext = engineInstance_.renderContext_;
881     RETURN_IF_NULL(renderContext);
882 
883     auto viewHandle = CreateOESTextureHandle(ecs, renderContext, sfBufferInfo_);
884     RETURN_IF_NULL(viewHandle);
885 
886     const uint32_t bufferSize = sfBufferInfo_.transformMatrix_.size() * FLOAT_TO_BYTE;
887     if (bufferSize < TRANSFORM_MATRIX_SIZE * FLOAT_TO_BYTE) {
888         WIDGET_LOGE("transform matrix size:%d not 4x4", bufferSize / FLOAT_TO_BYTE);
889         const float *arr = BASE_NS::Math::IDENTITY_4X4.data;
890         sfBufferInfo_.transformMatrix_.assign(arr, arr + TRANSFORM_MATRIX_SIZE);
891     } else if (bufferSize > TRANSFORM_MATRIX_SIZE * FLOAT_TO_BYTE) {
892         WIDGET_LOGE("transform matrix size:%d not 4x4", bufferSize / FLOAT_TO_BYTE);
893     }
894 
895     if (!initCamRNG_) {
896         InitEnvironmentResource(bufferSize);
897         initCamRNG_ = true;
898     }
899 
900     if (auto renderHandleManager = CORE_NS::GetManager<CORE3D_NS::IRenderHandleComponentManager>(*ecs)) {
901         if (auto camImageRenderHandle = renderHandleManager->Write(camImageEF_)) {
902             camImageRenderHandle->reference = viewHandle;
903         }
904     }
905 
906     if (camTransBufferHandle_ && renderDataStoreDefaultStaging_) {
907         BASE_NS::array_view<const uint8_t> transData(
908             reinterpret_cast<const uint8_t *>(sfBufferInfo_.transformMatrix_.data()), bufferSize);
909         const RENDER_NS::BufferCopy bufferCopy{0, 0, bufferSize};
910         renderDataStoreDefaultStaging_->CopyDataToBufferOnCpu(transData, camTransBufferHandle_, bufferCopy);
911     }
912 }
913 
AcquireImage(const SurfaceBufferInfo & bufferInfo)914 void SceneAdapter::AcquireImage(const SurfaceBufferInfo &bufferInfo)
915 {
916     RETURN_IF_NULL(engineThread);
917     engineThread->AddTask(META_NS::MakeCallback<META_NS::ITaskQueueTask>([this, bufferInfo]() {
918         sfBufferInfo_ = bufferInfo;
919         receiveBuffer_ = true;
920         UpdateSurfaceBuffer();
921         return false;
922     }));
923 }
924 }  // namespace OHOS::Render3D
925