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