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 <cstdint>
17 #include <string>
18 #include <js_native_api.h>
19 #include <js_native_api_types.h>
20 #include <hilog/log.h>
21
22 #include "plugin_render.h"
23 #include "common.h"
24
25 namespace OHOS {
26 std::unordered_map<std::string, PluginRender *> PluginRender::instance_;
27 OH_NativeXComponent_Callback PluginRender::callback_;
28
OnSurfaceCreatedCB(OH_NativeXComponent * component,void * window)29 void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
30 {
31 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceCreatedCB");
32 if ((component == nullptr) || (window == nullptr)) {
33 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
34 "OnSurfaceCreatedCB: component or window is null");
35 return;
36 }
37
38 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
39 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
40 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
41 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
42 "OnSurfaceCreatedCB: Unable to get XComponent id");
43 return;
44 }
45
46 std::string id(idStr);
47 auto render = PluginRender::GetInstance(id);
48 uint64_t width;
49 uint64_t height;
50 int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
51 if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) {
52 render->eglcore_->EglContextInit(window, width, height);
53 }
54 }
55
OnSurfaceDestroyedCB(OH_NativeXComponent * component,void * window)56 void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
57 {
58 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "Callback", "OnSurfaceDestroyedCB");
59 if ((component == nullptr) || (window == nullptr)) {
60 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
61 "OnSurfaceDestroyedCB: component or window is null");
62 return;
63 }
64
65 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = { '\0' };
66 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
67 if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
68 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback",
69 "OnSurfaceDestroyedCB: Unable to get XComponent id");
70 return;
71 }
72
73 std::string id(idStr);
74 PluginRender::Release(id);
75 }
76
PluginRender(const std::string & id)77 PluginRender::PluginRender(const std::string &id)
78 {
79 this->id_ = id;
80 this->eglcore_ = new EGLCore();
81 OH_NativeXComponent_Callback *renderCallback = &PluginRender::callback_;
82 renderCallback->OnSurfaceCreated = OnSurfaceCreatedCB;
83 renderCallback->OnSurfaceDestroyed = OnSurfaceDestroyedCB;
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 return instance;
92 } else {
93 return instance_[id];
94 }
95 }
96
97 // NAPI registration method type napi_callback. If no value is returned, nullptr is returned.
NapiDrawRectangle(napi_env env,napi_callback_info info)98 napi_value PluginRender::NapiDrawRectangle(napi_env env, napi_callback_info info)
99 {
100 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle");
101 if ((env == nullptr) || (info == nullptr)) {
102 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle: env or info is null");
103 return nullptr;
104 }
105
106 napi_value thisArg;
107 if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
108 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle: napi_get_cb_info fail");
109 return nullptr;
110 }
111
112 napi_value exportInstance;
113 if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
114 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender",
115 "NapiDrawRectangle: napi_get_named_property fail");
116 return nullptr;
117 }
118
119 OH_NativeXComponent *nativeXComponent = nullptr;
120 if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
121 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "NapiDrawRectangle: napi_unwrap fail");
122 return nullptr;
123 }
124
125 char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
126 uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
127 if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
128 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender",
129 "NapiDrawRectangle: Unable to get XComponent id");
130 return nullptr;
131 }
132
133 std::string id(idStr);
134 PluginRender *render = PluginRender::GetInstance(id);
135 if (render) {
136 render->eglcore_->Draw();
137 OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PluginRender", "render->eglcore_->Draw() executed");
138 }
139 return nullptr;
140 }
141
Export(napi_env env,napi_value exports)142 void PluginRender::Export(napi_env env, napi_value exports)
143 {
144 if ((env == nullptr) || (exports == nullptr)) {
145 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: env or exports is null");
146 return;
147 }
148
149 napi_property_descriptor desc[] = {
150 { "drawRectangle", nullptr, PluginRender::NapiDrawRectangle, nullptr, nullptr, nullptr, napi_default, nullptr }
151 };
152 if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
153 OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "PluginRender", "Export: napi_define_properties failed");
154 }
155 }
156
Release(std::string & id)157 void PluginRender::Release(std::string &id)
158 {
159 PluginRender *render = PluginRender::GetInstance(id);
160 if (render != nullptr) {
161 render->eglcore_->Release();
162 delete render->eglcore_;
163 render->eglcore_ = nullptr;
164 delete render;
165 render = nullptr;
166 instance_.erase(instance_.find(id));
167 }
168 }
169 } // namespace OHOS