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 #include "drawing_demo.h"
16
17 #include <sstream>
18
19 #include "accesstoken_kit.h"
20 #include "nativetoken_kit.h"
21 #include "token_setproc.h"
22 #include "display_manager.h"
23 #include "test_case_factory.h"
24 #include "test_case/test_common.h"
25
26 using namespace OHOS::Rosen;
27
28 namespace OHOS {
29 namespace Rosen {
DrawingDemo(int argc, char* argv[])30 DrawingDemo::DrawingDemo(int argc, char* argv[])
31 {
32 argc_ = argc;
33 for (int i = 0; i < argc_; i++) {
34 std::string str = argv[i];
35 argv_.emplace_back(str);
36 }
37 };
38
~DrawingDemo()39 DrawingDemo::~DrawingDemo()
40 {
41 if (window_) {
42 window_->Hide();
43 window_->Destroy();
44 }
45 };
46
Test(TestDisplayCanvas* canvas)47 int DrawingDemo::Test(TestDisplayCanvas* canvas)
48 {
49 TestCommon::Log("eg: drawing_demo function [cpu | gpu] {caseName?} {displayTime?}");
50 TestCommon::Log("eg: drawing_demo performance [cpu | gpu] caseName count {displayTime?}");
51 if (argc_ <= INDEX_DRAWING_TYPE) {
52 return RET_PARAM_ERR;
53 }
54
55 testType_ = argv_[INDEX_TEST_TYPE];
56 drawingType_ = argv_[INDEX_DRAWING_TYPE];
57 if (testType_ == "function") {
58 if (drawingType_ == "cpu") {
59 return TestFunction(FUNCTION_CPU);
60 } else if (drawingType_ == "gpu") {
61 return TestFunction(FUNCTION_GPU_UPSCREEN);
62 }
63 } else if (testType_ == "performance") {
64 if (drawingType_ == "cpu") {
65 return TestPerformance(canvas, PERFORMANCE_CPU);
66 } else if (drawingType_ == "gpu") {
67 return TestPerformance(canvas, PERFORMANCE_GPU_UPSCREEN);
68 }
69 }
70 return RET_PARAM_ERR;
71 }
72
InitWindow()73 int DrawingDemo::InitWindow()
74 {
75 rsUiDirector_ = RSUIDirector::Create();
76 if (rsUiDirector_ == nullptr) {
77 TestCommon::Log("Failed to create rsUiDirector_");
78 return RET_FAILED;
79 }
80 rsUiDirector_->Init();
81 RSTransaction::FlushImplicitTransaction();
82 sleep(1);
83 auto surfaceNode = window_->GetSurfaceNode();
84 rsUiDirector_->SetRSSurfaceNode(surfaceNode);
85
86 rootNode_ = RSRootNode::Create();
87 if (rootNode_ == nullptr) {
88 TestCommon::Log("Failed to create rootNode");
89 return RET_FAILED;
90 }
91 rootNode_->SetBounds(0, 0, rect_.width_, rect_.height_);
92 rootNode_->SetFrame(0, 0, rect_.width_, rect_.height_);
93 rootNode_->SetBackgroundColor(Drawing::Color::COLOR_WHITE);
94 rsUiDirector_->SetRoot(rootNode_->GetId());
95
96 canvasNode_ = RSCanvasNode::Create();
97 if (canvasNode_ == nullptr) {
98 TestCommon::Log("Failed to create canvasNode");
99 return RET_FAILED;
100 }
101 canvasNode_->SetFrame(0, 0, rect_.width_, rect_.height_);
102 rootNode_->AddChild(canvasNode_, -1);
103 rsUiDirector_->SendMessages();
104 sleep(1);
105 return RET_OK;
106 }
107
InitNativeTokenInfo()108 void InitNativeTokenInfo()
109 {
110 uint64_t tokenId;
111 const char *perms[1];
112 perms[0] = "ohos.permission.SYSTEM_FLOAT_WINDOW";
113 NativeTokenInfoParams infoInstance = {
114 .dcapsNum = 0,
115 .permsNum = 1,
116 .aclsNum = 0,
117 .dcaps = NULL,
118 .perms = perms,
119 .acls = NULL,
120 .processName = "drawing_demo",
121 .aplStr = "system_basic",
122 };
123 tokenId = GetAccessTokenId(&infoInstance);
124 SetSelfTokenID(tokenId);
125 Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
126 }
127
CreateWindow()128 int DrawingDemo::CreateWindow()
129 {
130 InitNativeTokenInfo();
131 TestCommon::Log("create window start");
132 sptr<Display> display = DisplayManager::GetInstance().GetDefaultDisplay();
133 if (display == nullptr) {
134 TestCommon::Log("Failed to get display!");
135 return RET_FAILED;
136 }
137 int32_t defaultWidth = display->GetWidth();
138 int32_t defaultHeight = display->GetHeight();
139 std::ostringstream stream;
140 stream << "display: " << defaultWidth << "*" << defaultHeight;
141 TestCommon::Log(stream.str());
142
143 std::string demoName = "drawing_demo";
144 RSSystemProperties::GetUniRenderEnabled();
145 sptr<WindowOption> option = new WindowOption();
146 option->SetWindowType(WindowType::WINDOW_TYPE_FLOAT);
147 option->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
148 option->SetWindowRect({ 0, 0, defaultWidth, defaultHeight });
149
150 int count = 0;
151 do {
152 if (window_ != nullptr) {
153 window_->Hide();
154 window_->Destroy();
155 }
156 window_ = Window::Create(demoName, option);
157 if (window_ == nullptr) {
158 TestCommon::Log("Failed to create window");
159 return RET_FAILED;
160 }
161
162 window_->Show();
163 usleep(SLEEP_TIME);
164 rect_ = window_->GetRect();
165 count++;
166 } while (rect_.width_ == 0 && rect_.height_ == 0 && count < MAX_TRY_NUMBER);
167
168 if (rect_.width_ == 0 || rect_.height_ == 0) {
169 TestCommon::Log("Failed to create window, rect is 0!");
170 return RET_FAILED;
171 }
172
173 int ret = InitWindow();
174 if (ret != RET_OK) {
175 return ret;
176 }
177 stream.str("");
178 stream << "create window success: " << rect_.width_ << " * " << rect_.height_;
179 TestCommon::Log(stream.str());
180 return RET_OK;
181 }
182
GetFunctionalParam(std::unordered_map<std::string, std::function<std::shared_ptr<TestBase>()>>& map)183 int DrawingDemo::GetFunctionalParam(std::unordered_map<std::string, std::function<std::shared_ptr<TestBase>()>>& map)
184 {
185 // drawing_demo functional {cpu | gpu} {caseName?} {displayTime?}
186 if (argc_ <= INDEX_CASE_NAME) {
187 caseName_ = ALL_TAST_CASE;
188 return RET_OK;
189 }
190
191 caseName_ = argv_[INDEX_CASE_NAME];
192 if (map.find(caseName_) == map.end()) {
193 TestCommon::Log("TestCase not exist, please try again. All testcase:");
194 for (auto iter : map) {
195 TestCommon::Log(iter.first);
196 }
197 return RET_PARAM_ERR;
198 }
199
200 if (argc_ > INDEX_FUNCTION_TIME) {
201 std::string displayTimeStr = argv_[INDEX_FUNCTION_TIME];
202 displayTime_ = std::stoi(displayTimeStr);
203 }
204 return RET_OK;
205 }
206
TestFunction(int type)207 int DrawingDemo::TestFunction(int type)
208 {
209 auto map = TestCaseFactory::GetFunctionCase();
210 int ret = GetFunctionalParam(map);
211 if (ret != RET_OK) {
212 return ret;
213 }
214
215 TestCommon::Log("TestFunction start!");
216 ret = CreateWindow();
217 if (ret != RET_OK) {
218 return ret;
219 }
220 for (auto iter : map) {
221 if ((caseName_ != ALL_TAST_CASE) && (caseName_ != iter.first)) {
222 continue;
223 }
224
225 auto canvas = canvasNode_->BeginRecording(rect_.width_, rect_.height_);
226 auto testCase = iter.second();
227 if (testCase == nullptr) {
228 std::ostringstream stream;
229 stream << "Failed to create testcase:" << iter.first;
230 TestCommon::Log(stream.str());
231 continue;
232 }
233
234 testCase->SetCanvas((TestDisplayCanvas*)(canvas));
235 if (type == FUNCTION_CPU) {
236 testCase->SetFileName(iter.first);
237 testCase->TestFunctionCpu();
238 } else if (type == FUNCTION_GPU_UPSCREEN) {
239 testCase->TestFunctionGpuUpScreen();
240 }
241 canvasNode_->FinishRecording();
242 rsUiDirector_->SendMessages();
243 if (type == FUNCTION_GPU_UPSCREEN) {
244 sleep(2); // Wait for 2 seconds to make the screen display normal
245 (void)TestCommon::PackingPixmap(window_->Snapshot(), iter.first);
246 }
247 }
248
249 int time = (caseName_ != ALL_TAST_CASE ? displayTime_ : 1);
250 std::ostringstream stream;
251 stream << "wait: " << time << "s";
252 TestCommon::Log(stream.str());
253 sleep(time);
254 TestCommon::Log("TestFunction end!");
255 return RET_OK;
256 }
257
GetPerformanceParam(std::shared_ptr<TestBase>& testCase)258 int DrawingDemo::GetPerformanceParam(std::shared_ptr<TestBase>& testCase)
259 {
260 // drawing_demo performance {cpu | gpu} caseName count {displaytime?}
261 if (argc_ <= INDEX_COUNT) {
262 return RET_PARAM_ERR;
263 }
264
265 caseName_ = argv_[INDEX_CASE_NAME];
266 auto map = TestCaseFactory::GetPerformanceCase();
267 auto iter = map.find(caseName_);
268 if (iter == map.end()) {
269 TestCommon::Log("TestCase not exist, please try again. All testcase:");
270 for (auto iter : map) {
271 TestCommon::Log(iter.first);
272 }
273 return RET_PARAM_ERR;
274 }
275 testCase = iter->second();
276 if (testCase == nullptr) {
277 TestCommon::Log("Failed to create testcase");
278 return RET_FAILED;
279 }
280
281 std::string testCountStr = argv_[INDEX_COUNT];
282 testCount_ = std::stoi(testCountStr);
283
284 if (argc_ > INDEX_PERFORMANCE_TIME) {
285 std::string displayTimeStr = argv_[INDEX_PERFORMANCE_TIME];
286 displayTime_ = std::stoi(displayTimeStr);
287 }
288 return RET_OK;
289 }
290
TestPerformance(TestDisplayCanvas* canvasExt, int type)291 int DrawingDemo::TestPerformance(TestDisplayCanvas* canvasExt, int type)
292 {
293 std::shared_ptr<TestBase> testCase = nullptr;
294 int ret = GetPerformanceParam(testCase);
295 if (ret != RET_OK || testCase == nullptr) {
296 return ret;
297 }
298
299 TestCommon::Log("TestPerformance start!");
300 TestDisplayCanvas* canvas = nullptr;
301 if (canvasExt == nullptr) {
302 ret = CreateWindow();
303 if (ret != RET_OK) {
304 return ret;
305 }
306 canvas = reinterpret_cast<TestDisplayCanvas*>(canvasNode_->BeginRecording(rect_.width_, rect_.height_));
307 if (canvas == nullptr) {
308 TestCommon::Log("Failed to get canvas");
309 return RET_FAILED;
310 }
311 } else {
312 canvas = canvasExt;
313 }
314
315 testCase->SetCanvas((TestDisplayCanvas*)(canvas));
316 testCase->SetTestCount(testCount_);
317
318 if (type == PERFORMANCE_CPU) {
319 testCase->TestPerformanceCpu();
320 } else if (type == PERFORMANCE_GPU_UPSCREEN) {
321 testCase->TestPerformanceGpuUpScreen();
322 }
323
324 if (canvasExt == nullptr) {
325 canvasNode_->FinishRecording();
326 rsUiDirector_->SendMessages();
327
328 std::ostringstream stream;
329 stream << "wait: " << displayTime_ << "s";
330 TestCommon::Log(stream.str());
331 sleep(displayTime_);
332 }
333
334 TestCommon::Log("TestPerformance end!");
335 return RET_OK;
336 }
337 } // namespace Rosen
338 } // namespace OHOS
339
main(int argc, char* argv[])340 int main(int argc, char* argv[])
341 {
342 std::shared_ptr<DrawingDemo> drawingDemo = std::make_shared<DrawingDemo>(argc, argv);
343 if (drawingDemo == nullptr) {
344 TestCommon::Log("Failed to create DrawingDemo");
345 return 0;
346 }
347 int ret = drawingDemo->Test(nullptr);
348 if (ret == RET_PARAM_ERR) {
349 TestCommon::Log("Invalid parameter, please confirm");
350 }
351 return ret;
352 }
353
354 #ifdef __cplusplus
355 extern "C" {
356 #endif
DrawingTest(void* canvas, int argc, char* argv[])357 int DrawingTest(void* canvas, int argc, char* argv[])
358 {
359 if (canvas == nullptr) {
360 TestCommon::Log("canvas is nullptr");
361 return 0;
362 }
363 std::shared_ptr<DrawingDemo> drawingDemo = std::make_shared<DrawingDemo>(argc, argv);
364 if (drawingDemo == nullptr) {
365 TestCommon::Log("Failed to create DrawingDemo");
366 return 0;
367 }
368 int ret = drawingDemo->Test((TestDisplayCanvas*)(canvas));
369 if (ret == RET_PARAM_ERR) {
370 TestCommon::Log("Invalid parameter, please confirm");
371 }
372 return ret;
373 }
374 #ifdef __cplusplus
375 }
376 #endif