• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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