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