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 "plugin_render.h"
17 #include "logger_common.h"
18 #include <string>
19
20 std::unordered_map<std::string, PluginRender *> PluginRender::instance_;
21 OH_NativeXComponent_Callback PluginRender::callback_;
22 bool PluginRender::isTriangleRotational_ = true;
23 std::mutex PluginRender::mutex_;
24 std::condition_variable PluginRender::con_;
25
GetXComponentId(OH_NativeXComponent * component)26 static std::string GetXComponentId(OH_NativeXComponent *component)
27 {
28 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
29 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
30 int32_t ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
31 if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
32 return std::string();
33 }
34 return std::string(idStr);
35 }
36
37 // Called when surface is created. CB means callback.
OnSurfaceCreatedCB(OH_NativeXComponent * component,void * window)38 void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
39 {
40 std::string id = GetXComponentId(component);
41 auto render = PluginRender::GetInstance(id);
42 render->OnSurfaceCreated(component, window);
43 }
44
45 // Called when surface is changed. CB means callback.
OnSurfaceChangedCB(OH_NativeXComponent * component,void * window)46 void OnSurfaceChangedCB(OH_NativeXComponent *component, void *window)
47 {
48 std::string id = GetXComponentId(component);
49 auto render = PluginRender::GetInstance(id);
50 render->OnSurfaceChanged(component, window);
51 }
52
53 // Called when surface is destroyed. CB means callback.
OnSurfaceDestroyedCB(OH_NativeXComponent * component,void * window)54 void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
55 {
56 std::string id = GetXComponentId(component);
57 auto render = PluginRender::GetInstance(id);
58 render->OnSurfaceDestroyed(component, window);
59 }
60
61 // Called when touch event is triggered. CB means callback.
DispatchTouchEventCB(OH_NativeXComponent * component,void * window)62 void DispatchTouchEventCB(OH_NativeXComponent *component, void *window)
63 {
64 std::string id = GetXComponentId(component);
65 auto render = PluginRender::GetInstance(id);
66 render->DispatchTouchEvent(component, window);
67 }
68
69 /* ------------------------------------------------------------------------------ */
70
PluginRender(std::string & id)71 PluginRender::PluginRender(std::string &id) : id_(id), component_(nullptr)
72 {
73 auto renderCallback = PluginRender::GetNXComponentCallback();
74 renderCallback->OnSurfaceCreated = OnSurfaceCreatedCB;
75 renderCallback->OnSurfaceChanged = OnSurfaceChangedCB;
76 renderCallback->OnSurfaceDestroyed = OnSurfaceDestroyedCB;
77 renderCallback->DispatchTouchEvent = DispatchTouchEventCB;
78 }
79
~PluginRender()80 PluginRender::~PluginRender()
81 {
82 delete instance_[id_];
83 instance_.erase(id_);
84 }
85
GetInstance(std::string & id)86 PluginRender *PluginRender::GetInstance(std::string &id)
87 {
88 if (instance_.find(id) == instance_.end()) {
89 PluginRender *instance = new PluginRender(id);
90 instance_[id] = instance;
91 }
92 return instance_[id];
93 }
94
SetNativeXComponent(OH_NativeXComponent * component)95 void PluginRender::SetNativeXComponent(OH_NativeXComponent *component)
96 {
97 component_ = component;
98 OH_NativeXComponent_RegisterCallback(component_, &PluginRender::callback_);
99 }
100
101 // Change the status of the triangle (rotational or still).
NapiStopMovingOrRestart(napi_env env,napi_callback_info info)102 napi_value PluginRender::NapiStopMovingOrRestart(napi_env env, napi_callback_info info)
103 {
104 LOGI("Call NapiStopMovingOrRestart!");
105 std::unique_lock<std::mutex> locker(mutex_);
106 isTriangleRotational_ = !isTriangleRotational_;
107 con_.notify_all();
108 return nullptr;
109 }
110
111 // export nativeFuc "stopOrStart" to js/ts
Export(napi_env env,napi_value exports)112 napi_value PluginRender::Export(napi_env env, napi_value exports)
113 {
114 napi_property_descriptor desc[] = {
115 { "stopOrStart", nullptr, PluginRender::NapiStopMovingOrRestart, nullptr, nullptr, nullptr,
116 napi_default, nullptr}
117 };
118 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
119 return exports;
120 }
121
GetNXComponentCallback()122 OH_NativeXComponent_Callback *PluginRender::GetNXComponentCallback()
123 {
124 return &PluginRender::callback_;
125 }
126
RenderThread()127 void PluginRender::RenderThread()
128 {
129 while (vulkanExample_ != nullptr && vulkanExample_->IsInited()) {
130 std::unique_lock<std::mutex> locker(mutex_);
131 if (isTriangleRotational_) {
132 vulkanExample_->RenderLoop();
133 } else {
134 con_.wait(locker);
135 }
136 }
137 }
138
139 // Init Vulkan backend when surface is created.
OnSurfaceCreated(OH_NativeXComponent * component,void * window)140 void PluginRender::OnSurfaceCreated(OH_NativeXComponent *component, void *window)
141 {
142 int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
143 if (vulkanExample_ == nullptr) {
144 vulkanExample_ = std::make_unique<vkExample::VulkanExample>();
145 vulkanExample_->SetupWindow(static_cast<OHNativeWindow *>(window));
146 if (!vulkanExample_->InitVulkan()) {
147 LOGE("PluginRender::OnSurfaceCreated vulkanExample initVulkan failed!");
148 return;
149 }
150 vulkanExample_->SetUp();
151 renderThread_ = std::thread(std::bind(&PluginRender::RenderThread, this));
152 }
153 }
154
OnSurfaceChanged(OH_NativeXComponent * component,void * window)155 void PluginRender::OnSurfaceChanged(OH_NativeXComponent *component, void *window)
156 {
157 int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
158 if (vulkanExample_ == nullptr) {
159 OnSurfaceCreated(component, window);
160 } else {
161 vulkanExample_->SetRecreateSwapChain();
162 }
163 LOGD("PluginRender::OnSurfaceChanged ret is %{public}d, w:%{public}lu, d:%{public}lu", ret, width_, height_);
164 }
165
OnSurfaceDestroyed(OH_NativeXComponent * component,void * window)166 void PluginRender::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window)
167 {
168 LOGD("PluginRender::OnSurfaceDestroyed is called!");
169 }
170
DispatchTouchEvent(OH_NativeXComponent * component,void * window)171 void PluginRender::DispatchTouchEvent(OH_NativeXComponent *component, void *window)
172 {
173 int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_);
174 LOGD("PluginRender::DispatchTouchEvent is called!");
175 }
176