1 /*
2 * Copyright (c) 2023 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_playback.h"
16 #include <sstream>
17 #include <fcntl.h>
18 #include <unique_fd.h>
19
20 namespace OHOS {
21 namespace Rosen {
DrawingDCL(int32_t argc,char * argv[])22 DrawingDCL::DrawingDCL(int32_t argc, char* argv[])
23 {
24 DCLCommand dclCommand = DCLCommand(argc, argv);
25 UpdateParametersFromDCLCommand(dclCommand);
26 skiaRecording.InitConfigsFromParam();
27 }
28
~DrawingDCL()29 DrawingDCL::~DrawingDCL()
30 {
31 std::cout << "~DrawingDCL" << std::endl;
32 delete dcl_;
33 }
34
PrintDurationTime(const std::string & description,std::chrono::time_point<std::chrono::system_clock> start)35 void DrawingDCL::PrintDurationTime(const std::string & description,
36 std::chrono::time_point<std::chrono::system_clock> start)
37 {
38 auto end = std::chrono::system_clock::now();
39 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds> (end - start);
40 const double convertToMs = 1000000.0;
41 std::cout << description << duration.count() / convertToMs << "ms" << std::endl;
42 }
43
IterateFrame(int & curLoop,int & frame)44 bool DrawingDCL::IterateFrame(int &curLoop, int &frame)
45 {
46 ++frame;
47 if (frame > endFrame_) {
48 frame = beginFrame_;
49 if (++curLoop == loop_) {
50 return false;
51 }
52 }
53 return true;
54 }
55
PlayBackByFrame(SkCanvas * skiaCanvas,bool isDumpPictures)56 bool DrawingDCL::PlayBackByFrame(SkCanvas* skiaCanvas, bool isDumpPictures)
57 {
58 //read DrawCmdList from file
59 if (skiaCanvas == nullptr) {
60 return false;
61 }
62 auto start = std::chrono::system_clock::now();
63 static int frame = beginFrame_;
64 static int curLoop = 0;
65 std::string dclFile = inputFilePath_ + "frame" + std::to_string(frame) + ".drawing";
66 std::cout << "PlayBackByFrame dclFile:" << dclFile << std::endl;
67
68 if (LoadDrawCmdList(dclFile) < 0) {
69 std::cout << "failed to loadDrawCmdList" << std::endl;
70 IterateFrame(curLoop, frame);
71 return false;
72 }
73 PrintDurationTime("Load DrawCmdList file time is ", start);
74 start = std::chrono::system_clock::now();
75 dcl_->Playback(*skiaCanvas);
76 PrintDurationTime("The frame PlayBack time is ", start);
77
78 return IterateFrame(curLoop, frame);
79 }
80
PlayBackByOpItem(SkCanvas * skiaCanvas,bool isMoreOps)81 bool DrawingDCL::PlayBackByOpItem(SkCanvas* skiaCanvas, bool isMoreOps)
82 {
83 if (skiaCanvas == nullptr) {
84 return false;
85 }
86 auto start = std::chrono::system_clock::now();
87 // read drawCmdList from file
88 std::string dclFile = inputFilePath_ + "frameByOpItem.drawing";
89 std::cout << "PlayBackFrame dclFile:" << dclFile << std::endl;
90
91 if (LoadDrawCmdList(dclFile) < 0) {
92 std::cout << "failed to loadDrawCmdList" << std::endl;
93 return false;
94 }
95 PrintDurationTime("Load DrawCmdList file time is ", start);
96 // Playback
97 static double opitemId = 0;
98 double oldOpId = opitemId;
99 if (!isMoreOps) {
100 opitemId -= opItemStep_;
101 if (opitemId < 0) {
102 opitemId = 0;
103 }
104 std::cout<< "This is already the first OpItem." << std::endl;
105 } else {
106 opitemId += opItemStep_;
107 }
108 std::cout << "play back to opitemId = " << static_cast<int>(opitemId) << std::endl;
109 if (opitemId < dcl_->GetSize()) {
110 std::cout << dcl_->PlayBackForRecord(*skiaCanvas, 0, static_cast<int>(opitemId), static_cast<int>(oldOpId))
111 << std::endl;
112 } else {
113 std::cout << dcl_->PlayBackForRecord(*skiaCanvas, 0, dcl_->GetSize(), static_cast<int>(oldOpId)) << std::endl;
114 opitemId = 0;
115 return false;
116 }
117 return true;
118 }
119
GetDirectionAndStep(std::string command,bool & isMoreOps)120 bool DrawingDCL::GetDirectionAndStep(std::string command, bool &isMoreOps)
121 {
122 if (command.empty()) {
123 return true;
124 }
125 std::vector<std::string> words;
126 std::stringstream ss(command);
127 std::string word;
128 while (ss >> word) {
129 words.emplace_back(word);
130 }
131 const size_t twoParam = 2;
132 if (words.size() != twoParam) {
133 std::cout << "Wrong Parameter!" << std::endl;
134 return false;
135 }
136 if (std::strcmp(words[0].c_str(), "l") == 0 || std::strcmp(words[0].c_str(), "L") == 0) {
137 isMoreOps = false;
138 } else if (std::strcmp(words[0].c_str(), "m") == 0 || std::strcmp(words[0].c_str(), "M") == 0) {
139 isMoreOps = true;
140 } else {
141 std::cout << "Wrong Direction!" << std::endl;
142 return false;
143 }
144 // check if the input for step is valid
145 int dotPostion = -1;
146 for (size_t i = 0; i < words[1].size(); ++i) {
147 if (words[1][i] == '.' && dotPostion == -1) {
148 dotPostion = i;
149 } else if (words[1][i] >= '0' && words[1][i] <= '9') {
150 continue;
151 } else {
152 std::cout << "Please enter right step!" << std::endl;
153 return false;
154 }
155 }
156 opItemStep_ = std::stod(words[1]);
157 return true;
158 }
159
UpdateParametersFromDCLCommand(const DCLCommand & dclCommand)160 void DrawingDCL::UpdateParametersFromDCLCommand(const DCLCommand &dclCommand)
161 {
162 iterateType = dclCommand.iterateType_;
163 beginFrame_ = dclCommand.beginFrame_;
164 endFrame_ = dclCommand.endFrame_;
165 loop_ = dclCommand.loop_;
166 opItemStep_ = dclCommand.opItemStep_;
167 inputFilePath_ = dclCommand.inputFilePath_;
168 outputFilePath_ = dclCommand.outputFilePath_;
169 }
170
UpdateParameters(bool notNeeded)171 void DrawingDCL::UpdateParameters(bool notNeeded)
172 {
173 if (notNeeded) {
174 return;
175 }
176 std::cout << "Please re-enter the parameters" << std::endl;
177 std::string line;
178 getline(std::cin, line);
179 if (line.empty()) {
180 return;
181 }
182 DCLCommand dclCommand = DCLCommand(line);
183 UpdateParametersFromDCLCommand(dclCommand);
184 }
185
Test(SkCanvas * canvas,int width,int height)186 void DrawingDCL::Test(SkCanvas* canvas, int width, int height)
187 {
188 std::cout << "DrawingDCL::Test+" << std::endl;
189 if (skiaRecording.GetCaptureEnabled()) {
190 canvas = skiaRecording.BeginCapture(canvas, width, height);
191 }
192 auto start = std::chrono::system_clock::now();
193 switch (iterateType) {
194 case IterateType::ITERATE_FRAME:
195 UpdateParameters(PlayBackByFrame(canvas));
196 break;
197 case IterateType::ITERATE_OPITEM:
198 UpdateParameters(PlayBackByOpItem(canvas));
199 break;
200 case IterateType::ITERATE_OPITEM_MANUALLY: {
201 static bool isMoreOps = true;
202 std::string opActionsStr = isMoreOps ? "more" : "less";
203 std::cout << "Do you want to execute " << opItemStep_ << " OpItems " << opActionsStr << " ?\n"
204 "To Modify, enter the action (More or less) and step size, for example, \"M 2\". \n"
205 " Press Enter to continue." << std::endl;
206 std::string line;
207 do {
208 getline(std::cin, line);
209 } while (!GetDirectionAndStep(line, isMoreOps));
210 UpdateParameters(PlayBackByOpItem(canvas, isMoreOps));
211 break;
212 }
213 case IterateType::OTHER:
214 std::cout << "Unknown iteratetype, please reenter parameters!" << std::endl;
215 break;
216 default:
217 std::cout << "Wrong iteratetype!" << std::endl;
218 break;
219 }
220 PrintDurationTime("This frame draw time is: ", start);
221 if (skiaRecording.GetCaptureEnabled()) {
222 skiaRecording.EndCapture();
223 }
224 std::cout << "DrawingDCL::Test-" << std::endl;
225 }
226
Output()227 void DrawingDCL::Output()
228 {
229 }
230
231 class MyAllocator : public DefaultAllocator {
232 public:
MyAllocator(int fd,size_t size,uint8_t * mapFile)233 MyAllocator(int fd, size_t size, uint8_t* mapFile) : fd_(fd), size_(size), mapFile_(mapFile) {}
234
~MyAllocator()235 ~MyAllocator()
236 {
237 Dealloc(mapFile_);
238 }
239
Dealloc(void * mapFile)240 void Dealloc(void *mapFile)
241 {
242 if (mapFile != mapFile_) {
243 std::cout << "MyAllocator::Dealloc data addr not match!" << std::endl;
244 }
245 if (mapFile_ != nullptr) {
246 if (::munmap(mapFile_, size_) == -1) {
247 std::cout << "munmap failed!" <<std::endl;
248 }
249 mapFile_ = nullptr;
250 }
251 if (fd_ > 0) {
252 ::close(fd_);
253 fd_ = -1;
254 }
255 }
256 private:
257 int fd_;
258 size_t size_;
259 uint8_t *mapFile_;
260 };
261
GetRealPathStr(const std::string & filePath)262 std::string DrawingDCL::GetRealPathStr(const std::string& filePath)
263 {
264 std::string realPathStr = "";
265 char actualPath[PATH_MAX + 1] = {0};
266 if (realpath(filePath.c_str(), actualPath) == nullptr) {
267 std::cout << "The path of DrawCmdList file is empty!" << std::endl;
268 return realPathStr;
269 }
270 realPathStr = actualPath;
271 return realPathStr;
272 }
273
IsValidFile(const std::string & realPathStr)274 bool DrawingDCL::IsValidFile(const std::string& realPathStr)
275 {
276 return realPathStr.find(dclFileDir_) == 0;
277 }
278
LoadDrawCmdList(const std::string & dclFile)279 int DrawingDCL::LoadDrawCmdList(const std::string& dclFile)
280 {
281 std::string realDclFilePathStr = GetRealPathStr(dclFile);
282 if (realDclFilePathStr.empty()) {
283 return -1;
284 }
285 if (!IsValidFile(realDclFilePathStr)) {
286 std::cout << "The path of DrawCmdList file is not valid!" << std::endl;
287 return -1;
288 }
289 UniqueFd fd(open(realDclFilePathStr.c_str(), O_RDONLY));
290 if (fd.Get() < 0) {
291 std::cout << "Open file failed" << dclFile.c_str() << std::endl;
292 return -1;
293 }
294 struct stat statbuf;
295 if (fstat(fd.Get(), &statbuf) < 0) {
296 return -1;
297 }
298 std::cout << "statbuf.st_size = " << statbuf.st_size << std::endl;
299
300 auto mapFile = static_cast<uint8_t *>(mmap(nullptr, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0));
301 if (mapFile == MAP_FAILED) {
302 return -1;
303 }
304 std::cout << "mapFile OK" << std::endl;
305
306 MessageParcel messageParcel(new MyAllocator(fd.Get(), statbuf.st_size, mapFile));
307 messageParcel.SetMaxCapacity(recordingParcelMaxCapcity_);
308 if (!messageParcel.ParseFrom(reinterpret_cast<uintptr_t>(mapFile), statbuf.st_size)) {
309 munmap(mapFile, statbuf.st_size);
310 return -1;
311 }
312 std::cout << "messageParcel GetDataSize() = " << messageParcel.GetDataSize() << std::endl;
313
314 dcl_ = DrawCmdList::Unmarshalling(messageParcel);
315 if (dcl_ == nullptr) {
316 std::cout << "dcl is nullptr" << std::endl;
317 munmap(mapFile, statbuf.st_size);
318 return -1;
319 }
320 std::cout << "The size of Ops is " << dcl_->GetSize() << std::endl;
321 munmap(mapFile, statbuf.st_size);
322 return 0;
323 }
324 }
325 }
326