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 "common/log_common.h"
17 #include <bits/alltypes.h>
18 #include <chrono>
19 #include <fcntl.h>
20 #include <memory>
21 #include <native_drawing/drawing_font_collection.h>
22 #include <native_drawing/drawing_text_typography.h>
23 #include <native_buffer/native_buffer.h>
24 #include <sstream>
25 #include <string>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <unordered_map>
30 #include "my_xcomponent.h"
31 #include "plugin/plugin_manager.h"
32 #include "testcasefactory.h"
33 #include "test_common.h"
34 #include <iostream>
35 #include <thread>
36 
37 static std::unordered_map<std::string, MyXComponent *> g_instance;
38 
getConfig(int version,EGLDisplay eglDisplay)39 EGLConfig getConfig(int version, EGLDisplay eglDisplay)
40 {
41     int attribList[] = {EGL_SURFACE_TYPE,
42                         EGL_WINDOW_BIT,
43                         EGL_RED_SIZE,
44                         8,
45                         EGL_GREEN_SIZE,
46                         8,
47                         EGL_BLUE_SIZE,
48                         8,
49                         EGL_ALPHA_SIZE,
50                         8,
51                         EGL_RENDERABLE_TYPE,
52                         EGL_OPENGL_ES2_BIT,
53                         EGL_NONE};
54     EGLConfig configs = NULL;
55     int configsNum;
56 
57     if (!eglChooseConfig(eglDisplay, attribList, &configs, 1, &configsNum)) {
58         DRAWING_LOGE("eglChooseConfig ERROR");
59         return NULL;
60     }
61 
62     return configs;
63 }
64 
OnSurfaceCreatedCB(OH_NativeXComponent * component,void * window)65 static void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
66 {
67     DRAWING_LOGI("OnSurfaceCreatedCB");
68     if ((component == nullptr) || (window == nullptr)) {
69         DRAWING_LOGE("OnSurfaceCreatedCB: component or window is null");
70         return;
71     }
72     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
73     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
74     if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
75         DRAWING_LOGE("OnSurfaceCreatedCB: Unable to get XComponent id");
76         return;
77     }
78     std::string id(idStr);
79     auto render = MyXComponent::GetOrCreateInstance(id);
80     if (render == nullptr) {
81         DRAWING_LOGE("OnSurfaceCreatedCB: Failed to get instance");
82         return;
83     }
84     OHNativeWindow *nativeWindow = static_cast<OHNativeWindow *>(window);
85     render->SetNativeWindow(nativeWindow);
86 
87     uint64_t width;
88     uint64_t height;
89     int32_t status = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
90     if ((status == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) {
91         render->SetSceenHeight(height);
92         render->SetScreenWidth(width);
93     }
94 }
95 
OnSurfaceDestroyedCB(OH_NativeXComponent * component,void * window)96 static void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
97 {
98     DRAWING_LOGI("OnSurfaceDestroyedCB");
99     if ((component == nullptr) || (window == nullptr)) {
100         DRAWING_LOGE("OnSurfaceDestroyedCB: component or window is null");
101         return;
102     }
103     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
104     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
105     if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
106         DRAWING_LOGE("OnSurfaceDestroyedCB: Unable to get XComponent id");
107         return;
108     }
109     std::string id(idStr);
110     MyXComponent::Release(id);
111 }
112 
113 // 通过callback获取到宽高信息
SetScreenWidth(uint64_t width)114 void MyXComponent::SetScreenWidth(uint64_t width)
115 {
116     screenWidth_ = width;
117 }
118 
119 // 通过callback获取到宽高信息
SetSceenHeight(uint64_t height)120 void MyXComponent::SetSceenHeight(uint64_t height)
121 {
122     screenHeight_ = height;
123 }
124 
125 // 通过callback获取到window
SetNativeWindow(OHNativeWindow * nativeWindow)126 void MyXComponent::SetNativeWindow(OHNativeWindow *nativeWindow)
127 {
128     nativeWindow_ = nativeWindow;
129 }
130 
131 //获取屏幕xcomponent的绘制canvas
InitScreenCanvas()132 void MyXComponent::InitScreenCanvas()
133 {
134     if (nativeWindow_ == nullptr) {
135         DRAWING_LOGE("nativeWindow_ is nullptr");
136         return;
137     }
138     // 这里的nativeWindow是从上一步骤中的回调函数中获得的
139     int32_t usage = NATIVEBUFFER_USAGE_CPU_READ | NATIVEBUFFER_USAGE_CPU_WRITE | NATIVEBUFFER_USAGE_MEM_DMA;
140     int ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage);
141     if (ret != 0) {
142         DRAWING_LOGE("failed to OH_NativeWindow_NativeWindowHandleOpt");
143         return;
144     }
145     // 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 OHNativeWindowBuffer 实例
146     ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer_, &fenceFd_);
147     if (ret != 0) {
148         DRAWING_LOGE("failed to NativeWindowRequestBuffer");
149         return;
150     }
151     DRAWING_LOGI("request buffer ret = %{public}d", ret);
152     // 通过 OH_NativeWindow_GetBufferHandleFromNative 获取 buffer 的 handle
153     bufferHandle_ = OH_NativeWindow_GetBufferHandleFromNative(buffer_);
154     // 使用系统mmap接口拿到bufferHandle的内存虚拟地址
155     mappedAddr_ = static_cast<uint32_t *>(
156         mmap(bufferHandle_->virAddr, bufferHandle_->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle_->fd, 0));
157     if (mappedAddr_ == MAP_FAILED) {
158         DRAWING_LOGE("mmap failed");
159         return;
160     }
161 
162     if (screenCanvas_) {
163         OH_Drawing_CanvasDestroy(screenCanvas_);
164         screenCanvas_ = nullptr;
165     }
166     if (screenBitmap_) {
167         OH_Drawing_BitmapDestroy(screenBitmap_);
168         screenBitmap_ = nullptr;
169     }
170     screenImageInfo_ = {static_cast<int32_t>(screenWidth_), static_cast<int32_t>(screenHeight_),
171         COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_OPAQUE};
172     screenBitmap_ = OH_Drawing_BitmapCreateFromPixels(&screenImageInfo_, mappedAddr_, bufferHandle_->stride);
173     screenCanvas_ = OH_Drawing_CanvasCreate();
174     OH_Drawing_CanvasBind(screenCanvas_, screenBitmap_);
175     OH_Drawing_CanvasClear(screenCanvas_, OH_Drawing_ColorSetArgb(0x00, 0x00, 0x00, 0x00));
176 }
177 
BitmapToScreenCanvas(OH_Drawing_Bitmap * bitmap)178 void MyXComponent::BitmapToScreenCanvas(OH_Drawing_Bitmap* bitmap)
179 {
180     if (screenCanvas_ == nullptr || bitmap == nullptr) {
181         return;
182     }
183     OH_Drawing_CanvasDrawBitmap(screenCanvas_, bitmap, 0, 0);
184     FlushScreen();
185 
186     int result = munmap(mappedAddr_, bufferHandle_->size);
187     if (result == -1) {
188         DRAWING_LOGE("munmap failed!");
189     }
190     mappedAddr_ = nullptr;
191 }
192 
FlushScreen()193 void MyXComponent::FlushScreen()
194 {
195     if (nativeWindow_ != nullptr && buffer_ != nullptr) {
196         // 设置刷新区域,如果Region中的Rect为nullptr,或者rectNumber为0,则认为OHNativeWindowBuffer全部有内容更改。
197         Region region {nullptr, 0};
198         // 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
199         OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow_, buffer_, fenceFd_, region);
200     }
201 }
202 
InitializeEglContext()203 int32_t MyXComponent::InitializeEglContext()
204 {
205     mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
206     if (mEGLDisplay == EGL_NO_DISPLAY) {
207         DRAWING_LOGE("unable to get EGL display.");
208         return -1;
209     }
210 
211     EGLint eglMajVers;
212     EGLint eglMinVers;
213     if (!eglInitialize(mEGLDisplay, &eglMajVers, &eglMinVers)) {
214         mEGLDisplay = EGL_NO_DISPLAY;
215         DRAWING_LOGE("unable to initialize display");
216         return -1;
217     }
218 
219     int version = 3;
220     mEGLConfig = getConfig(version, mEGLDisplay);
221     if (mEGLConfig == nullptr) {
222         DRAWING_LOGE("GLContextInit config ERROR");
223         return -1;
224     }
225 
226     /* Create EGLContext from */
227     int attribList[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; // 2 size
228 
229     mEGLContext = eglCreateContext(mEGLDisplay, mEGLConfig, EGL_NO_CONTEXT, attribList);
230 
231     EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
232     mEGLSurface = eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, attribs);
233     if (!eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
234         DRAWING_LOGE("eglMakeCurrent error = %{public}d", eglGetError());
235         return -1;
236     }
237 
238     DRAWING_LOGI("Init success.");
239     return 0;
240 }
241 
DeInitializeEglContext()242 void MyXComponent::DeInitializeEglContext()
243 {
244     EGLBoolean ret = eglDestroySurface(mEGLDisplay, mEGLSurface);
245     if (!ret) {
246         DRAWING_LOGW("eglDestroySurface failure.");
247     }
248 
249     ret = eglDestroyContext(mEGLDisplay, mEGLContext);
250     if (!ret) {
251         DRAWING_LOGW("eglDestroyContext failure.");
252     }
253 
254     ret = eglTerminate(mEGLDisplay);
255     if (!ret) {
256         DRAWING_LOGW("eglTerminate failure.");
257     }
258 
259     mEGLSurface = NULL;
260     mEGLContext = NULL;
261     mEGLDisplay = NULL;
262 }
263 
TestPerformanceCpu(napi_env env,std::string caseName)264 void MyXComponent::TestPerformanceCpu(napi_env env, std::string caseName)
265 {
266     auto testCase = TestCaseFactory::GetPerformanceCpuCase(caseName);
267     if (testCase == nullptr) {
268         FlushScreen();
269         DRAWING_LOGE("failed to get testcase");
270         return;
271     }
272     testCase->SetTestCount(testCount_);
273     testCase->TestPerformanceCpu(env);
274     usedTime_ = testCase->GetTime();
275     BitmapToScreenCanvas(testCase->GetBitmap());
276 }
277 
TestPerformanceGpu(napi_env env,std::string caseName)278 void MyXComponent::TestPerformanceGpu(napi_env env, std::string caseName)
279 {
280     auto testCase = TestCaseFactory::GetPerformanceCpuCase(caseName);
281     if (testCase == nullptr) {
282         FlushScreen();
283         DRAWING_LOGE("failed to get testcase");
284         return;
285     }
286     testCase->SetTestCount(testCount_);
287     testCase->TestPerformanceGpu(env);
288     usedTime_ = testCase->GetTime();
289     BitmapToScreenCanvas(testCase->GetBitmap());
290 }
291 
TestFunctionCpu(napi_env env,std::string caseName)292 void MyXComponent::TestFunctionCpu(napi_env env, std::string caseName)
293 {
294     auto testCase = TestCaseFactory::GetFunctionCpuCase(caseName);
295     if (testCase == nullptr) {
296         FlushScreen();
297         DRAWING_LOGE("failed to get testcase");
298         return;
299     }
300     testCase->SetFileName(caseName);
301     testCase->TestFunctionCpu(env);
302     BitmapToScreenCanvas(testCase->GetBitmap());
303 }
304 
TestStabilityCpuInner(std::string caseName)305 void MyXComponent::TestStabilityCpuInner(std::string caseName)
306 {
307     if (caseName == "All") {
308         for (auto map: TestCaseFactory::GetStabilityCpuCaseAll()) {
309             auto testCase = map.second();
310             testCase->SetTestCount(testCount_);
311             testCase->SetFileName(map.first);
312             testCase->TestStabilityCpu();
313             BitmapToScreenCanvas(testCase->GetBitmap());
314         }
315         DRAWING_LOGI("TestStabilityCpuAll end");
316     } else {
317         auto testCase = TestCaseFactory::GetStabilityCpuCase(caseName);
318         if (testCase == nullptr) {
319             FlushScreen();
320             DRAWING_LOGE("failed to get testcase");
321             return;
322         }
323         testCase->SetTestCount(testCount_);
324         testCase->SetFileName(caseName);
325         testCase->TestStabilityCpu();
326         BitmapToScreenCanvas(testCase->GetBitmap());
327         DRAWING_LOGI("TestStabilityCpu end");
328     }
329 }
330 
TestStabilityCpu(napi_env env,std::string caseName)331 void MyXComponent::TestStabilityCpu(napi_env env, std::string caseName)
332 {
333     std::thread threadObj(std::bind(&MyXComponent::TestStabilityCpuInner, this, std::string(caseName)));
334     threadObj.detach();
335 }
336 
TestFunctionGpu(napi_env env,std::string caseName)337 void MyXComponent::TestFunctionGpu(napi_env env, std::string caseName)
338 {
339     auto testCase = TestCaseFactory::GetFunctionCpuCase(caseName);
340     if (testCase == nullptr) {
341         FlushScreen();
342         DRAWING_LOGE("failed to get testcase");
343         return;
344     }
345     testCase->SetFileName(caseName);
346     testCase->TestFunctionGpu(env);
347     BitmapToScreenCanvas(testCase->GetBitmap());
348 }
349 
SetTestCount(uint32_t testCount)350 void MyXComponent::SetTestCount(uint32_t testCount)
351 {
352     testCount_ = testCount;
353 }
354 
NapiSetTestCount(napi_env env,napi_callback_info info)355 napi_value MyXComponent::NapiSetTestCount(napi_env env, napi_callback_info info)
356 {
357     DRAWING_LOGI("NapiSetTestCount");
358     if ((env == nullptr) || (info == nullptr)) {
359         DRAWING_LOGE("NapiDrawPattern: env or info is null");
360         return nullptr;
361     }
362 
363     napi_value thisArg;
364     size_t argc = 1;
365     napi_value argv[1] = {nullptr};
366     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
367         DRAWING_LOGE("NapiDrawPattern: napi_get_cb_info fail");
368         return nullptr;
369     }
370     uint32_t testCount;
371     if (!ConvertIntFromJsValue(env, argv[0], testCount)) {
372         DRAWING_LOGE("NapiDrawPattern: get caseName fail");
373         return nullptr;
374     }
375     DRAWING_LOGI("testCount = %{public}u", testCount);
376 
377     napi_value exportInstance;
378     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
379         DRAWING_LOGE("NapiDrawPattern: napi_get_named_property fail");
380         return nullptr;
381     }
382 
383     OH_NativeXComponent *nativeXComponent = nullptr;
384     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
385         DRAWING_LOGE("NapiDrawPattern: napi_unwrap fail");
386         return nullptr;
387     }
388 
389     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
390     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
391     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
392         DRAWING_LOGE("NapiDrawPattern: Unable to get XComponent id");
393         return nullptr;
394     }
395     DRAWING_LOGI("ID = %{public}s", idStr);
396     std::string id(idStr);
397     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
398     if (render != nullptr) {
399         render->SetTestCount(testCount);
400     } else {
401         DRAWING_LOGE("render is nullptr");
402     }
403     return nullptr;
404 }
405 
GetTime()406 uint32_t MyXComponent::GetTime()
407 {
408     return usedTime_;
409 }
410 
NapiGetTime(napi_env env,napi_callback_info info)411 napi_value MyXComponent::NapiGetTime(napi_env env, napi_callback_info info)
412 {
413     DRAWING_LOGI("MyXComponent NapiGetTime");
414     if ((env == nullptr) || (info == nullptr)) {
415         DRAWING_LOGE("NapiDrawPattern: env or info is null");
416         return nullptr;
417     }
418 
419     napi_value thisArg;
420     size_t argc = 1;
421     napi_value argv[1] = {nullptr};
422     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
423         DRAWING_LOGE("NapiDrawPattern: napi_get_cb_info fail");
424         return nullptr;
425     }
426 
427     napi_value exportInstance;
428     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
429         DRAWING_LOGE("NapiDrawPattern: napi_get_named_property fail");
430         return nullptr;
431     }
432 
433     OH_NativeXComponent *nativeXComponent = nullptr;
434     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
435         DRAWING_LOGE("NapiDrawPattern: napi_unwrap fail");
436         return nullptr;
437     }
438 
439     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
440     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
441     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
442         DRAWING_LOGE("NapiDrawPattern: Unable to get XComponent id");
443         return nullptr;
444     }
445     DRAWING_LOGI("ID = %{public}s", idStr);
446     std::string id(idStr);
447     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
448     if (render != nullptr) {
449         DRAWING_LOGE("DrawingTest render->GetTime");
450         napi_value value = nullptr;
451         (void)napi_create_int32(env, render->GetTime(), &value);
452         return value;
453     } else {
454         DRAWING_LOGE("DrawingTest render is nullptr");
455     }
456     return nullptr;
457 }
458 
GetTestNames()459 std::string MyXComponent::GetTestNames()
460 {
461     std::string str = "";
462     for (auto map: TestCaseFactory::GetFunctionCpuCaseAll()) {
463         if (str == "") {
464             str += map.first;
465         } else {
466             str += "," + map.first;
467         }
468     }
469     return str;
470 }
471 
NapiGetTestNames(napi_env env,napi_callback_info info)472 napi_value MyXComponent::NapiGetTestNames(napi_env env, napi_callback_info info)
473 {
474     DRAWING_LOGI("MyXComponent NapiGetTestNames");
475     if ((env == nullptr) || (info == nullptr)) {
476         DRAWING_LOGE("NapiGetTestNames: env or info is null");
477         return nullptr;
478     }
479 
480     napi_value thisArg;
481     size_t argc = 1;
482     napi_value argv[1] = {nullptr};
483     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
484         DRAWING_LOGE("NapiGetTestNames: napi_get_cb_info fail");
485         return nullptr;
486     }
487 
488     napi_value exportInstance;
489     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
490         DRAWING_LOGE("NapiGetTestNames: napi_get_named_property fail");
491         return nullptr;
492     }
493 
494     OH_NativeXComponent *nativeXComponent = nullptr;
495     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
496         DRAWING_LOGE("NapiGetTestNames: napi_unwrap fail");
497         return nullptr;
498     }
499 
500     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
501     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
502     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
503         DRAWING_LOGE("NapiGetTestNames: Unable to get XComponent id");
504         return nullptr;
505     }
506     DRAWING_LOGI("ID = %{public}s", idStr);
507     std::string id(idStr);
508     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
509     if (render != nullptr) {
510         napi_value value = nullptr;
511         std::string str = render->GetTestNames();
512         (void)napi_create_string_utf8(env, str.c_str(), str.length(), &value);
513         return value;
514     } else {
515         DRAWING_LOGE("NapiGetTestNames: render is nullptr");
516     }
517     return nullptr;
518 }
519 
NapiFunctionCpu(napi_env env,napi_callback_info info)520 napi_value MyXComponent::NapiFunctionCpu(napi_env env, napi_callback_info info)
521 {
522     DRAWING_LOGI("NapiFunctionCpu");
523     if ((env == nullptr) || (info == nullptr)) {
524         DRAWING_LOGE("NapiFunctionCpu: env or info is null");
525         return nullptr;
526     }
527 
528     napi_value thisArg;
529     size_t argc = 1;
530     napi_value argv[1] = {nullptr};
531     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
532         DRAWING_LOGE("NapiFunctionCpu: napi_get_cb_info fail");
533         return nullptr;
534     }
535     std::string caseName = "";
536     if (!ConvertStringFromJsValue(env, argv[0], caseName)) {
537         DRAWING_LOGE("NapiFunctionCpu: get caseName fail");
538         return nullptr;
539     }
540     DRAWING_LOGI("caseName = %{public}s", caseName.c_str());
541 
542     napi_value exportInstance;
543     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
544         DRAWING_LOGE("NapiFunctionCpu: napi_get_named_property fail");
545         return nullptr;
546     }
547 
548     OH_NativeXComponent *nativeXComponent = nullptr;
549     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
550         DRAWING_LOGE("NapiFunctionCpu: napi_unwrap fail");
551         return nullptr;
552     }
553 
554     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
555     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
556     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
557         DRAWING_LOGE("NapiFunctionCpu: Unable to get XComponent id");
558         return nullptr;
559     }
560     DRAWING_LOGI("NapiFunctionCpu ID = %{public}s", idStr);
561     std::string id(idStr);
562     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
563     if (render != nullptr) {
564         render->InitScreenCanvas();
565         render->TestFunctionCpu(env, caseName);
566     } else {
567         DRAWING_LOGE("NapiFunctionCpu: render is nullptr");
568     }
569     return nullptr;
570 }
571 
NapiStabilityCpu(napi_env env,napi_callback_info info)572 napi_value MyXComponent::NapiStabilityCpu(napi_env env, napi_callback_info info)
573 {
574     DRAWING_LOGI("NapiStabilityCpu");
575     if ((env == nullptr) || (info == nullptr)) {
576         DRAWING_LOGE("NapiStabilityCpu: env or info is null");
577         return nullptr;
578     }
579 
580     napi_value thisArg;
581     size_t argc = 1;
582     napi_value argv[1] = {nullptr};
583     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
584         DRAWING_LOGE("NapiStabilityCpu: napi_get_cb_info fail");
585         return nullptr;
586     }
587     std::string caseName = "";
588     if (!ConvertStringFromJsValue(env, argv[0], caseName)) {
589         DRAWING_LOGE("NapiStabilityCpu: get caseName fail");
590         return nullptr;
591     }
592     DRAWING_LOGI("caseName = %{public}s", caseName.c_str());
593 
594     napi_value exportInstance;
595     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
596         DRAWING_LOGE("NapiStabilityCpu: napi_get_named_property fail");
597         return nullptr;
598     }
599 
600     OH_NativeXComponent *nativeXComponent = nullptr;
601     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
602         DRAWING_LOGE("NapiStabilityCpu: napi_unwrap fail");
603         return nullptr;
604     }
605 
606     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
607     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
608     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
609         DRAWING_LOGE("NapiStabilityCpu: Unable to get XComponent id");
610         return nullptr;
611     }
612     DRAWING_LOGI("NapiStabilityCpu ID = %{public}s", idStr);
613     std::string id(idStr);
614     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
615     if (render != nullptr) {
616         render->InitScreenCanvas();
617         render->TestStabilityCpu(env, caseName);
618     } else {
619         DRAWING_LOGE("NapiStabilityCpu: render is nullptr");
620     }
621     return nullptr;
622 }
623 
NapiFunctionGpu(napi_env env,napi_callback_info info)624 napi_value MyXComponent::NapiFunctionGpu(napi_env env, napi_callback_info info)
625 {
626     DRAWING_LOGI("NapiFunctionGpu");
627     if ((env == nullptr) || (info == nullptr)) {
628         DRAWING_LOGE("NapiFunctionGpu: env or info is null");
629         return nullptr;
630     }
631 
632     napi_value thisArg;
633     size_t argc = 1;
634     napi_value argv[1] = {nullptr};
635     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
636         DRAWING_LOGE("NapiFunctionGpu: napi_get_cb_info fail");
637         return nullptr;
638     }
639     std::string caseName = "";
640     if (!ConvertStringFromJsValue(env, argv[0], caseName)) {
641         DRAWING_LOGE("NapiFunctionGpu: get caseName fail");
642         return nullptr;
643     }
644     DRAWING_LOGI("caseName = %{public}s", caseName.c_str());
645 
646     napi_value exportInstance;
647     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
648         DRAWING_LOGE("NapiFunctionGpu: napi_get_named_property fail");
649         return nullptr;
650     }
651 
652     OH_NativeXComponent *nativeXComponent = nullptr;
653     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
654         DRAWING_LOGE("NapiFunctionGpu: napi_unwrap fail");
655         return nullptr;
656     }
657 
658     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
659     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
660     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
661         DRAWING_LOGE("NapiFunctionGpu: Unable to get XComponent id");
662         return nullptr;
663     }
664     DRAWING_LOGI("NapiFunctionGpu ID = %{public}s", idStr);
665     std::string id(idStr);
666     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
667     if (render != nullptr) {
668         render->InitScreenCanvas();
669         render->InitializeEglContext();
670         render->TestFunctionGpu(env, caseName);
671         render->DeInitializeEglContext();
672     } else {
673         DRAWING_LOGE("NapiFunctionGpu: render is nullptr");
674     }
675     return nullptr;
676 }
677 
NapiPerformanceCpu(napi_env env,napi_callback_info info)678 napi_value MyXComponent::NapiPerformanceCpu(napi_env env, napi_callback_info info)
679 {
680     DRAWING_LOGI("NapiPerformanceCpu");
681     if ((env == nullptr) || (info == nullptr)) {
682         DRAWING_LOGE("NapiDrawPattern: env or info is null");
683         return nullptr;
684     }
685 
686     napi_value thisArg;
687     size_t argc = 1;
688     napi_value argv[1] = {nullptr};
689     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
690         DRAWING_LOGE("NapiDrawPattern: napi_get_cb_info fail");
691         return nullptr;
692     }
693     std::string caseName = "";
694     if (!ConvertStringFromJsValue(env, argv[0], caseName)) {
695         DRAWING_LOGE("NapiDrawPattern: get caseName fail");
696         return nullptr;
697     }
698     DRAWING_LOGI("caseName = %{public}s", caseName.c_str());
699 
700     napi_value exportInstance;
701     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
702         DRAWING_LOGE("NapiDrawPattern: napi_get_named_property fail");
703         return nullptr;
704     }
705 
706     OH_NativeXComponent *nativeXComponent = nullptr;
707     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
708         DRAWING_LOGE("NapiDrawPattern: napi_unwrap fail");
709         return nullptr;
710     }
711 
712     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
713     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
714     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
715         DRAWING_LOGE("NapiDrawPattern: Unable to get XComponent id");
716         return nullptr;
717     }
718     DRAWING_LOGI("ID = %{public}s", idStr);
719     std::string id(idStr);
720     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
721     if (render != nullptr) {
722         render->InitScreenCanvas();
723         render->TestPerformanceCpu(env, caseName);
724     } else {
725         DRAWING_LOGE("render is nullptr");
726     }
727 
728     return nullptr;
729 }
730 
NapiPerformanceGpu(napi_env env,napi_callback_info info)731 napi_value MyXComponent::NapiPerformanceGpu(napi_env env, napi_callback_info info)
732 {
733     DRAWING_LOGI("NapiPerformanceGpu");
734     if ((env == nullptr) || (info == nullptr)) {
735         DRAWING_LOGE("NapiDrawPattern: env or info is null");
736         return nullptr;
737     }
738 
739     napi_value thisArg;
740     size_t argc = 1;
741     napi_value argv[1] = {nullptr};
742     if (napi_get_cb_info(env, info, &argc, argv, &thisArg, nullptr) != napi_ok) {
743         DRAWING_LOGE("NapiDrawPattern: napi_get_cb_info fail");
744         return nullptr;
745     }
746     std::string caseName = "";
747     if (!ConvertStringFromJsValue(env, argv[0], caseName)) {
748         DRAWING_LOGE("NapiDrawPattern: get caseName fail");
749         return nullptr;
750     }
751 
752     napi_value exportInstance;
753     if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
754         DRAWING_LOGE("NapiDrawPattern: napi_get_named_property fail");
755         return nullptr;
756     }
757 
758     OH_NativeXComponent *nativeXComponent = nullptr;
759     if (napi_unwrap(env, exportInstance, reinterpret_cast<void **>(&nativeXComponent)) != napi_ok) {
760         DRAWING_LOGE("NapiDrawPattern: napi_unwrap fail");
761         return nullptr;
762     }
763 
764     char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
765     uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
766     if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
767         DRAWING_LOGE("NapiDrawPattern: Unable to get XComponent id");
768         return nullptr;
769     }
770     std::string id(idStr);
771     MyXComponent *render = MyXComponent().GetOrCreateInstance(id);
772     if (render != nullptr) {
773         render->InitScreenCanvas();
774         render->InitializeEglContext();
775         render->TestPerformanceGpu(env, caseName);
776         render->DeInitializeEglContext();
777     } else {
778         DRAWING_LOGE("render is nullptr");
779     }
780     DRAWING_LOGI("DrawingTest NapiPerformanceGpu, ID = %{public}s, caseName = %{public}s", idStr, caseName.c_str());
781 
782     return nullptr;
783 }
784 
~MyXComponent()785 MyXComponent::~MyXComponent()
786 {
787     if (screenCanvas_) {
788         OH_Drawing_CanvasDestroy(screenCanvas_);
789         screenCanvas_ = nullptr;
790     }
791     if (screenBitmap_) {
792         OH_Drawing_BitmapDestroy(screenBitmap_);
793         screenBitmap_ = nullptr;
794     }
795 
796     if (mappedAddr_ != nullptr && bufferHandle_ != nullptr) {
797         int result = munmap(mappedAddr_, bufferHandle_->size);
798         if (result == -1) {
799             DRAWING_LOGE("munmap failed!");
800         }
801     }
802     buffer_ = nullptr;
803     bufferHandle_ = nullptr;
804     nativeWindow_ = nullptr;
805     mappedAddr_ = nullptr;
806 }
807 
Release(std::string & id)808 void MyXComponent::Release(std::string &id)
809 {
810     PluginManager::GetInstance()->ReleaseRender(id);
811     auto map = g_instance.find(id);
812     if (map == g_instance.end()) {
813         return;
814     }
815     MyXComponent *render = g_instance[id];
816     if (render != nullptr) {
817         g_instance.erase(map);
818         delete render;
819         render = nullptr;
820     }
821 }
822 
Export(napi_env env,napi_value exports)823 void MyXComponent::Export(napi_env env, napi_value exports)
824 {
825     DRAWING_LOGI("MyXComponent napi init");
826     if ((env == nullptr) || (exports == nullptr)) {
827         DRAWING_LOGE("Export: env or exports is null");
828         return;
829     }
830 
831     napi_property_descriptor desc[] = {
832         {"setTestCount", nullptr, MyXComponent::NapiSetTestCount, nullptr, nullptr, nullptr, napi_default, nullptr},
833         {"getTime", nullptr, MyXComponent::NapiGetTime, nullptr, nullptr, nullptr, napi_default, nullptr},
834         {"getTestNames", nullptr, MyXComponent::NapiGetTestNames, nullptr, nullptr, nullptr, napi_default, nullptr},
835         {"testFunctionCpu", nullptr, MyXComponent::NapiFunctionCpu, nullptr, nullptr, nullptr, napi_default, nullptr},
836         {"testFunctionGpu", nullptr, MyXComponent::NapiFunctionGpu, nullptr, nullptr, nullptr, napi_default, nullptr},
837         {"testPerformanceCpu", nullptr, MyXComponent::NapiPerformanceCpu,
838             nullptr, nullptr, nullptr, napi_default, nullptr},
839         {"testPerformanceGpu", nullptr, MyXComponent::NapiPerformanceGpu,
840             nullptr, nullptr, nullptr, napi_default, nullptr},
841         {"testStabilityCpu", nullptr, MyXComponent::NapiStabilityCpu, nullptr, nullptr, nullptr, napi_default, nullptr},
842     };
843     if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
844         DRAWING_LOGE("Export: napi_define_properties failed");
845     }
846 }
847 
RegisterCallback(OH_NativeXComponent * nativeXComponent)848 void MyXComponent::RegisterCallback(OH_NativeXComponent *nativeXComponent)
849 {
850     DRAWING_LOGI("register callback");
851     renderCallback_.OnSurfaceCreated = OnSurfaceCreatedCB;
852     renderCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
853     // Callback must be initialized
854     renderCallback_.DispatchTouchEvent = nullptr;
855     renderCallback_.OnSurfaceChanged = nullptr;
856     OH_NativeXComponent_RegisterCallback(nativeXComponent, &renderCallback_);
857 }
858 
GetOrCreateInstance(std::string & id)859 MyXComponent *MyXComponent::GetOrCreateInstance(std::string &id)
860 {
861     if (g_instance.find(id) == g_instance.end()) {
862         MyXComponent *render = new MyXComponent(id);
863         g_instance[id] = render;
864         return render;
865     } else {
866         return g_instance[id];
867     }
868 }
869