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 "test_base.h"
17 
18 #include <fcntl.h>
19 #include <memory>
20 #include <multimedia/image_framework/image/pixelmap_native.h>
21 #include <multimedia/image_framework/image/image_packer_native.h>
22 #include <native_drawing/drawing_brush.h>
23 #include <native_drawing/drawing_color.h>
24 #include <native_drawing/drawing_filter.h>
25 #include <native_drawing/drawing_image.h>
26 #include <native_drawing/drawing_mask_filter.h>
27 #include <native_drawing/drawing_matrix.h>
28 #include <native_drawing/drawing_path.h>
29 #include <native_drawing/drawing_path_effect.h>
30 #include <native_drawing/drawing_pen.h>
31 #include <native_drawing/drawing_point.h>
32 #include <native_drawing/drawing_rect.h>
33 #include <native_drawing/drawing_round_rect.h>
34 #include <native_drawing/drawing_sampling_options.h>
35 #include <native_drawing/drawing_shader_effect.h>
36 #include <sstream>
37 #include <string>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <sys/time.h>
41 #include <sys/timerfd.h>
42 #include <unistd.h>
43 #include <unordered_map>
44 #include "common/log_common.h"
45 
46 const int SECOND_TO_NANO = 1000000000;
47 
SetFileName(std::string fileName)48 void TestBase::SetFileName(std::string fileName)
49 {
50     fileName_ = fileName;
51 }
52 
SetTestCount(uint32_t testCount)53 void TestBase::SetTestCount(uint32_t testCount)
54 {
55     testCount_ = testCount;
56 }
57 
GetBitmap()58 OH_Drawing_Bitmap* TestBase::GetBitmap()
59 {
60     return bitmap_;
61 }
62 
GetTime()63 uint32_t TestBase::GetTime()
64 {
65     return usedTime_;
66 }
67 
ClipCanvasToDrawSize(OH_Drawing_Canvas * canvas)68 void TestBase::ClipCanvasToDrawSize(OH_Drawing_Canvas *canvas)
69 {
70     OH_Drawing_Rect *rect = OH_Drawing_RectCreate(0, 0, bitmapWidth_, bitmapHeight_);
71     OH_Drawing_CanvasClipRect(canvas, rect, OH_Drawing_CanvasClipOp::INTERSECT, false);
72     OH_Drawing_RectDestroy(rect);
73 }
74 
TestFunctionCpu(napi_env env)75 void TestBase::TestFunctionCpu(napi_env env)
76 {
77     CreateBitmapCanvas();
78     OnTestFunction(bitmapCanvas_);
79     BitmapCanvasToFile();
80 }
81 
TestFunctionGpu(napi_env env)82 void TestBase::TestFunctionGpu(napi_env env)
83 {
84     CreateGpuCanvas();
85     OnTestFunction(gpuCanvas_);
86     GpuCanvasToFile(env, true);
87     Destroy();
88 }
89 
TestStabilityCpu()90 void TestBase::TestStabilityCpu()
91 {
92     CreateBitmapCanvas();
93     OnTestStability(bitmapCanvas_);
94     BitmapCanvasToFile();
95 }
96 
TestFunctionGpu(OH_Drawing_Canvas * canvas)97 void TestBase::TestFunctionGpu(OH_Drawing_Canvas *canvas) { OnTestFunction(canvas); }
98 
LogStart()99 unsigned long long TestBase::LogStart()
100 {
101     unsigned long long start = 0;
102     struct timespec tv {};
103     if (clock_gettime(CLOCK_BOOTTIME, &tv) >= 0) {
104         start = tv.tv_sec * SECOND_TO_NANO + tv.tv_nsec;
105     }
106     return start;
107 }
108 
LogEnd(unsigned long long start)109 void TestBase::LogEnd(unsigned long long start)
110 {
111     unsigned long long end = 0;
112     struct timespec tv {};
113     if (clock_gettime(CLOCK_BOOTTIME, &tv) >= 0) {
114         end = tv.tv_sec * SECOND_TO_NANO + tv.tv_nsec;
115     }
116     // LOGE is to avoid log loss
117     DRAWING_LOGE("DrawingApiTest TotalApiCallCount: [%{public}u]", testCount_);
118     usedTime_ = end - start;
119     DRAWING_LOGE("DrawingApiTest TotalApiCallTime: [%{public}u]", usedTime_);
120 }
121 
TestPerformanceGpu(OH_Drawing_Canvas * canvas)122 void TestBase::TestPerformanceGpu(OH_Drawing_Canvas *canvas)
123 {
124     StyleSettings(canvas, styleType_);
125     auto start = LogStart();
126     OnTestPerformance(canvas);
127     LogEnd(start);
128     StyleSettingsDestroy(canvas);
129 }
130 
TestPerformanceCpu(napi_env env)131 void TestBase::TestPerformanceCpu(napi_env env)
132 {
133     CreateBitmapCanvas();
134     StyleSettings(bitmapCanvas_, styleType_);
135     auto start = LogStart();
136 
137     OnTestPerformance(bitmapCanvas_);
138 
139     LogEnd(start);
140     StyleSettingsDestroy(bitmapCanvas_);
141 }
142 
TestPerformanceGpu(napi_env env)143 void TestBase::TestPerformanceGpu(napi_env env)
144 {
145     CreateGpuCanvas();
146     StyleSettings(gpuCanvas_, styleType_);
147     auto start = LogStart();
148 
149     OnTestPerformance(gpuCanvas_);
150 
151     LogEnd(start);
152     GpuCanvasToFile(env, false);
153     StyleSettingsDestroy(gpuCanvas_);
154     Destroy();
155 }
156 
CreateBitmapCanvas()157 void TestBase::CreateBitmapCanvas()
158 {
159     // 创建一个bitmap对象
160     if (bitmap_) {
161         OH_Drawing_BitmapDestroy(bitmap_);
162     }
163     bitmap_ = OH_Drawing_BitmapCreate();
164     // 定义bitmap的像素格式
165     OH_Drawing_BitmapFormat cFormat{COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_PREMUL};
166     // 构造对应格式的bitmap
167     OH_Drawing_BitmapBuild(bitmap_, bitmapWidth_, bitmapHeight_, &cFormat);
168 
169     // 创建一个canvas对象
170     if (bitmapCanvas_) {
171         OH_Drawing_CanvasDestroy(bitmapCanvas_);
172     }
173     bitmapCanvas_ = OH_Drawing_CanvasCreate();
174     // 将画布与bitmap绑定,画布画的内容会输出到绑定的bitmap内存中
175     OH_Drawing_CanvasBind(bitmapCanvas_, bitmap_);
176     // 使用白色清除画布内容
177     OH_Drawing_CanvasClear(bitmapCanvas_, OH_Drawing_ColorSetArgb(backgroundA_,
178         backgroundR_, backgroundG_, backgroundB_));
179 }
180 
CreateGpuCanvas()181 void TestBase::CreateGpuCanvas()
182 {
183     OH_Drawing_GpuContextOptions options{false};
184     imageInfo_ = {static_cast<int32_t>(bitmapWidth_), static_cast<int32_t>(bitmapHeight_),
185         COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_PREMUL};
186     gpuContext_ = OH_Drawing_GpuContextCreateFromGL(options);
187     surface_ = OH_Drawing_SurfaceCreateFromGpuContext(gpuContext_, true, imageInfo_);
188     gpuCanvas_ = OH_Drawing_SurfaceGetCanvas(surface_);
189     OH_Drawing_CanvasClear(gpuCanvas_, OH_Drawing_ColorSetArgb(backgroundA_, backgroundR_, backgroundG_, backgroundB_));
190 }
191 
BitmapCanvasToFile()192 void TestBase::BitmapCanvasToFile()
193 {
194     DRAWING_LOGE("BitmapCanvasToFile");
195     //创建pixmap
196     OH_Pixelmap_InitializationOptions *createOps = nullptr;
197     auto ret = OH_PixelmapInitializationOptions_Create(&createOps);
198     if (ret != IMAGE_SUCCESS || !createOps) {
199         DRAWING_LOGE("BitmapCanvasToFile OH_PixelmapInitializationOptions_Create failed %{public}d", ret);
200         return;
201     }
202 
203     OH_PixelmapInitializationOptions_SetWidth(createOps, bitmapWidth_);
204     OH_PixelmapInitializationOptions_SetHeight(createOps, bitmapHeight_);
205     OH_PixelmapInitializationOptions_SetPixelFormat(createOps, 3); // 3 is RGBA fromat
206     OH_PixelmapInitializationOptions_SetSrcPixelFormat(createOps, 3); // 3 is RGBA fromat
207     OH_PixelmapInitializationOptions_SetAlphaType(createOps, 2); // 2 is ALPHA_FORMAT_PREMUL
208 
209     size_t bufferSize = bitmapWidth_ * bitmapHeight_ * 4;
210     void *bitmapAddr = OH_Drawing_BitmapGetPixels(bitmap_);
211     OH_PixelmapNative *pixelMap = nullptr;
212     ret = OH_PixelmapNative_CreatePixelmap((uint8_t *)bitmapAddr, bufferSize, createOps, &pixelMap);
213     if (ret != IMAGE_SUCCESS || pixelMap == nullptr) {
214         DRAWING_LOGE(" failed to OH_PixelMap_CreatePixelMap width = %{public}u, height = %{public}u",
215             bitmapWidth_, bitmapHeight_);
216         OH_PixelmapInitializationOptions_Release(createOps);
217         return;
218     }
219 
220     Pixmap2RawFile(bitmapAddr, bufferSize);
221     Pixmap2ImageFile(pixelMap);
222 
223     OH_PixelmapNative_Release(pixelMap);
224     OH_PixelmapInitializationOptions_Release(createOps);
225 }
226 
GpuCanvasToFile(napi_env env,bool saveFile)227 void TestBase::GpuCanvasToFile(napi_env env, bool saveFile)
228 {
229     DRAWING_LOGI("GpuCanvasToFile");
230     //创建pixmap
231     OH_Pixelmap_InitializationOptions *createOps = nullptr;
232     auto ret = OH_PixelmapInitializationOptions_Create(&createOps);
233     if (ret != IMAGE_SUCCESS || !createOps) {
234         DRAWING_LOGE("GpuCanvasToFile OH_PixelmapInitializationOptions_Create failed %{public}d", ret);
235         return;
236     }
237 
238     OH_PixelmapInitializationOptions_SetWidth(createOps, bitmapWidth_);
239     OH_PixelmapInitializationOptions_SetHeight(createOps, bitmapHeight_);
240     OH_PixelmapInitializationOptions_SetPixelFormat(createOps, 3);  // 3 is RGBA fromat
241     OH_PixelmapInitializationOptions_SetSrcPixelFormat(createOps, 3); // 3 is RGBA fromat
242     OH_PixelmapInitializationOptions_SetAlphaType(createOps, 2); // 2 is ALPHA_FORMAT_PREMUL
243 
244     size_t bufferSize = bitmapWidth_ * bitmapHeight_ * 4;
245     if (dstPixels_) {
246         free(dstPixels_);
247         dstPixels_ = nullptr;
248     }
249     dstPixels_ = malloc(bitmapWidth_ * bitmapHeight_ * 4); // 4 for rgba
250     if (dstPixels_ == nullptr) {
251         DRAWING_LOGE("dstPixels_ malloc failed");
252         OH_PixelmapInitializationOptions_Release(createOps);
253         return;
254     }
255     bool output = OH_Drawing_CanvasReadPixels(gpuCanvas_, &imageInfo_, dstPixels_, 4 * bitmapWidth_, 0, 0);
256     if (!output) {
257         DRAWING_LOGE("read pixels failed");
258         OH_PixelmapInitializationOptions_Release(createOps);
259         return;
260     }
261     if (bitmap_) {
262         OH_Drawing_BitmapDestroy(bitmap_);
263     }
264     bitmap_ = OH_Drawing_BitmapCreateFromPixels(&imageInfo_, dstPixels_, 4 * bitmapWidth_); // 4 for rgba
265 
266     OH_PixelmapNative *pixelMap = nullptr;
267     ret = OH_PixelmapNative_CreatePixelmap((uint8_t *)dstPixels_, bufferSize, createOps, &pixelMap);
268     if (ret != IMAGE_SUCCESS || pixelMap == nullptr) {
269         DRAWING_LOGE("failed to CreatePixelMap width = %{public}u, height = %{public}u", bitmapWidth_, bitmapHeight_);
270         return;
271     }
272 
273     if (saveFile) {
274         Pixmap2RawFile(dstPixels_, bufferSize);
275         Pixmap2ImageFile(pixelMap);
276     }
277 }
278 
Pixmap2RawFile(void * pixelmap,uint32_t pixelMapSize)279 void TestBase::Pixmap2RawFile(void *pixelmap, uint32_t pixelMapSize)
280 {
281     // 打开需要输出的文件(请确保应用有权限访问这个路径)
282     std::string path = "/data/storage/el2/base/files/" + fileName_ + ".dat";
283     auto err = remove(path.c_str());
284     if (err) {
285         DRAWING_LOGE("failed to remove path: %{public}s", path.c_str());
286     }
287     int fd = open(path.c_str(), O_RDWR | O_CREAT);
288     if (fd <= 0) {
289         DRAWING_LOGE("failed to open fd = %{public}d path = %{public}s", fd, path.c_str());
290         return;
291     }
292 
293     auto result = write(fd, pixelmap, pixelMapSize);
294     if (result != pixelMapSize) {
295         DRAWING_LOGE("failed to Pixmap2RawFile");
296     }
297     // 关闭输出文件
298     close(fd);
299 }
300 
Pixmap2ImageFile(OH_PixelmapNative * pixelMap)301 void TestBase::Pixmap2ImageFile(OH_PixelmapNative* pixelMap)
302 {
303     OH_ImagePackerNative *packer = nullptr;
304     auto result = OH_ImagePackerNative_Create(&packer);
305     if (result != IMAGE_SUCCESS || !packer) {
306         DRAWING_LOGE("failed to OH_ImagePackerNative_Create");
307         return;
308     }
309 
310     OH_PackingOptions *opts = nullptr;
311     result = OH_PackingOptions_Create(&opts);
312     if (result != IMAGE_SUCCESS || !opts) {
313         DRAWING_LOGE("failed to OH_PackingOptions_Create");
314         return;
315     }
316 
317     char format[] = "image/png";
318     Image_MimeType imageMimeType { format, strlen(format) };
319     OH_PackingOptions_SetMimeType(opts, &imageMimeType);
320     uint32_t quality = 100;
321     OH_PackingOptions_SetQuality(opts, quality);
322 
323     // 打开需要输出的文件(请确保应用有权限访问这个路径)
324     std::string path = "/data/storage/el2/base/files/" + fileName_ + ".png";
325     auto err = remove(path.c_str());
326     if (err) {
327         DRAWING_LOGE("failed to remove path: %{public}s", path.c_str());
328     }
329     int fd = open(path.c_str(), O_RDWR | O_CREAT);
330     if (fd <= 0) {
331         DRAWING_LOGE("failed to open fd = %{public}d path = %{public}s", fd, path.c_str());
332         OH_PackingOptions_Release(opts);
333         OH_ImagePackerNative_Release(packer);
334         return;
335     }
336 
337     // 开始对输入source进行编码过程,返回result为 IMAGE_RESULT_SUCCESS则编码成功
338     result = OH_ImagePackerNative_PackToFileFromPixelmap(packer, opts, pixelMap, fd);
339     if (result != IMAGE_SUCCESS) {
340         DRAWING_LOGE("failed to OH_ImagePackerNative_PackToFileFromImageSource");
341         close(fd);
342         OH_PackingOptions_Release(opts);
343         OH_ImagePackerNative_Release(packer);
344         return;
345     }
346 
347     // 关闭输出文件
348     close(fd);
349     OH_PackingOptions_Release(opts);
350     OH_ImagePackerNative_Release(packer);
351 }
352 
Destroy()353 void TestBase::Destroy()
354 {
355     if (surface_) {
356         OH_Drawing_SurfaceDestroy(surface_);
357         surface_ = nullptr;
358     }
359     if (gpuContext_) {
360         OH_Drawing_GpuContextDestroy(gpuContext_);
361         gpuContext_ = nullptr;
362     }
363 }
364 
StyleSettings(OH_Drawing_Canvas * canvas,int32_t type)365 void TestBase::StyleSettings(OH_Drawing_Canvas* canvas, int32_t type)
366 {
367     if (canvas == nullptr) {
368         return;
369     }
370     StyleSettingsDestroy(canvas);
371     if (type == DRAW_STYLE_COMPLEX) {
372         styleBrush_ = OH_Drawing_BrushCreate();
373         OH_Drawing_BrushSetColor(styleBrush_, 0xFFFF0000);
374         OH_Drawing_CanvasAttachBrush(canvas, styleBrush_);
375     }
376 }
377 
StyleSettingsDestroy(OH_Drawing_Canvas * canvas)378 void TestBase::StyleSettingsDestroy(OH_Drawing_Canvas *canvas)
379 {
380     if (canvas != nullptr) {
381         OH_Drawing_CanvasDetachPen(canvas);
382         OH_Drawing_CanvasDetachBrush(canvas);
383     }
384     if (stylePen_ != nullptr) {
385         OH_Drawing_PenDestroy(stylePen_);
386         stylePen_ = nullptr;
387     }
388     if (styleBrush_ != nullptr) {
389         OH_Drawing_BrushDestroy(styleBrush_);
390         styleBrush_ = nullptr;
391     }
392     if (styleMask_ != nullptr) {
393         OH_Drawing_MaskFilterDestroy(styleMask_);
394         styleMask_ = nullptr;
395     }
396     if (styleFilter_ != nullptr) {
397         OH_Drawing_FilterDestroy(styleFilter_);
398         styleFilter_ = nullptr;
399     }
400     if (styleCenter_ != nullptr) {
401         OH_Drawing_PointDestroy(styleCenter_);
402         styleCenter_ = nullptr;
403     }
404     if (styleEffect_ != nullptr) {
405         OH_Drawing_ShaderEffectDestroy(styleEffect_);
406         styleEffect_ = nullptr;
407     }
408     if (stylePathEffect_ != nullptr) {
409         OH_Drawing_PathEffectDestroy(stylePathEffect_);
410         stylePathEffect_ = nullptr;
411     }
412 }
413 
GetBitmapWidth()414 uint32_t TestBase::GetBitmapWidth()
415 {
416     return bitmapWidth_;
417 }
418 
GetBitmapHeight()419 uint32_t TestBase::GetBitmapHeight()
420 {
421     return bitmapHeight_;
422 }