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
16 #include "recording/draw_cmd_list.h"
17
18 #include <cstddef>
19 #include <memory>
20
21 #include "recording/draw_cmd.h"
22 #include "recording/recording_canvas.h"
23 #include "utils/log.h"
24 #include "utils/performanceCaculate.h"
25
26 namespace OHOS {
27 namespace Rosen {
28 namespace Drawing {
29
CreateFromData(const CmdListData & data,bool isCopy)30 std::shared_ptr<DrawCmdList> DrawCmdList::CreateFromData(const CmdListData& data, bool isCopy)
31 {
32 auto cmdList = std::make_shared<DrawCmdList>(DrawCmdList::UnmarshalMode::DEFERRED);
33 if (isCopy) {
34 cmdList->opAllocator_.BuildFromDataWithCopy(data.first, data.second);
35 } else {
36 cmdList->opAllocator_.BuildFromData(data.first, data.second);
37 }
38
39 int32_t* width = static_cast<int32_t*>(cmdList->opAllocator_.OffsetToAddr(0, sizeof(int32_t)));
40 int32_t* height = static_cast<int32_t*>(cmdList->opAllocator_.OffsetToAddr(sizeof(int32_t), sizeof(int32_t)));
41 if (width && height) {
42 cmdList->width_ = *width;
43 cmdList->height_ = *height;
44 } else {
45 cmdList->width_ = 0;
46 cmdList->height_ = 0;
47 }
48 return cmdList;
49 }
50
DrawCmdList(DrawCmdList::UnmarshalMode mode)51 DrawCmdList::DrawCmdList(DrawCmdList::UnmarshalMode mode) : width_(0), height_(0), mode_(mode) {}
52
DrawCmdList(int32_t width,int32_t height,DrawCmdList::UnmarshalMode mode)53 DrawCmdList::DrawCmdList(int32_t width, int32_t height, DrawCmdList::UnmarshalMode mode)
54 : width_(width), height_(height), mode_(mode)
55 {
56 opAllocator_.Add(&width_, sizeof(int32_t));
57 opAllocator_.Add(&height_, sizeof(int32_t));
58 }
59
~DrawCmdList()60 DrawCmdList::~DrawCmdList()
61 {
62 if (drawOpItems_.size() == 0 && isNeedUnmarshalOnDestruct_) {
63 UnmarshallingDrawOps();
64 }
65 ClearOp();
66 }
67
AddDrawOp(std::shared_ptr<DrawOpItem> && drawOpItem)68 bool DrawCmdList::AddDrawOp(std::shared_ptr<DrawOpItem>&& drawOpItem)
69 {
70 if (mode_ != DrawCmdList::UnmarshalMode::DEFERRED) {
71 return false;
72 }
73 std::lock_guard<std::recursive_mutex> lock(mutex_);
74 drawOpItems_.emplace_back(drawOpItem);
75 return true;
76 }
77
ClearOp()78 void DrawCmdList::ClearOp()
79 {
80 {
81 std::lock_guard<std::recursive_mutex> lock(mutex_);
82 opAllocator_.ClearData();
83 opAllocator_.Add(&width_, sizeof(int32_t));
84 opAllocator_.Add(&height_, sizeof(int32_t));
85 imageAllocator_.ClearData();
86 bitmapAllocator_.ClearData();
87 imageMap_.clear();
88 imageHandleVec_.clear();
89 drawOpItems_.clear();
90 lastOpGenSize_ = 0;
91 lastOpItemOffset_ = std::nullopt;
92 opCnt_ = 0;
93 }
94 {
95 std::lock_guard<std::mutex> lock(recordCmdMutex_);
96 recordCmdVec_.clear();
97 }
98 {
99 std::lock_guard<std::mutex> lock(imageObjectMutex_);
100 imageObjectVec_.clear();
101 }
102 {
103 std::lock_guard<std::mutex> lock(imageBaseObjMutex_);
104 imageBaseObjVec_.clear();
105 }
106 }
107
GetWidth() const108 int32_t DrawCmdList::GetWidth() const
109 {
110 return width_;
111 }
112
GetHeight() const113 int32_t DrawCmdList::GetHeight() const
114 {
115 return height_;
116 }
117
SetWidth(int32_t width)118 void DrawCmdList::SetWidth(int32_t width)
119 {
120 width_ = width;
121 }
122
SetHeight(int32_t height)123 void DrawCmdList::SetHeight(int32_t height)
124 {
125 height_ = height;
126 }
127
IsEmpty() const128 bool DrawCmdList::IsEmpty() const
129 {
130 if (mode_ == DrawCmdList::UnmarshalMode::DEFERRED) {
131 return drawOpItems_.empty();
132 }
133 size_t offset = 2 * sizeof(int32_t); // 2 is width and height.Offset of first OpItem is behind the w and h
134 if (opAllocator_.GetSize() <= offset && drawOpItems_.size() == 0) {
135 return true;
136 }
137 return false;
138 }
139
GetOpItemSize() const140 size_t DrawCmdList::GetOpItemSize() const
141 {
142 return mode_ == DrawCmdList::UnmarshalMode::DEFERRED ? drawOpItems_.size() : opCnt_;
143 }
144
GetOpsWithDesc() const145 std::string DrawCmdList::GetOpsWithDesc() const
146 {
147 std::string desc;
148 for (auto& item : drawOpItems_) {
149 if (item == nullptr) {
150 continue;
151 }
152 desc += item->GetOpDesc();
153 desc += "\n";
154 }
155 LOGD("DrawCmdList::GetOpsWithDesc %{public}s, opitem sz: %{public}zu", desc.c_str(), drawOpItems_.size());
156 return desc;
157 }
158
Dump(std::string & out)159 void DrawCmdList::Dump(std::string& out)
160 {
161 std::lock_guard<std::recursive_mutex> lock(mutex_);
162 for (auto& item : drawOpItems_) {
163 if (item == nullptr) {
164 continue;
165 }
166 item->Dump(out);
167 out += " ";
168 }
169 if (drawOpItems_.size() > 0) {
170 out.pop_back();
171 }
172 }
173
MarshallingDrawOps()174 void DrawCmdList::MarshallingDrawOps()
175 {
176 if (mode_ == DrawCmdList::UnmarshalMode::IMMEDIATE) {
177 return;
178 }
179 std::lock_guard<std::recursive_mutex> lock(mutex_);
180 if (replacedOpListForVector_.empty()) {
181 for (auto& op : drawOpItems_) {
182 if (op) {
183 op->Marshalling(*this);
184 }
185 }
186 return;
187 }
188 for (auto& [index, op] : replacedOpListForVector_) {
189 op.swap(drawOpItems_[index]);
190 }
191 std::vector<uint32_t> opIndexForCache(replacedOpListForVector_.size());
192 uint32_t opReplaceIndex = 0;
193 for (auto index = 0u; index < drawOpItems_.size(); ++index) {
194 if (drawOpItems_[index]) {
195 drawOpItems_[index]->Marshalling(*this);
196 }
197 if (index == static_cast<size_t>(replacedOpListForVector_[opReplaceIndex].first)) {
198 opIndexForCache[opReplaceIndex] = lastOpItemOffset_.value();
199 ++opReplaceIndex;
200 }
201 }
202 for (auto index = 0u; index < replacedOpListForVector_.size(); ++index) {
203 if (replacedOpListForVector_[index].second) {
204 replacedOpListForVector_[index].second->Marshalling(*this);
205 }
206 replacedOpListForBuffer_.emplace_back(opIndexForCache[index], lastOpItemOffset_.value());
207 }
208 }
209
CaculatePerformanceOpType()210 void DrawCmdList::CaculatePerformanceOpType()
211 {
212 size_t offset = offset_;
213 const int caculatePerformaceCount = 500; // 被测单接口用例至少出现500次以上
214 std::map<uint32_t, uint32_t> opTypeCountMap;
215 uint32_t count = 0;
216 do {
217 count++;
218 void* itemPtr = opAllocator_.OffsetToAddr(offset, sizeof(OpItem));
219 auto* curOpItemPtr = static_cast<OpItem*>(itemPtr);
220 if (curOpItemPtr == nullptr) {
221 break;
222 }
223 uint32_t type = curOpItemPtr->GetType();
224 if (opTypeCountMap.find(type) != opTypeCountMap.end()) {
225 if (++opTypeCountMap[type] > caculatePerformaceCount) {
226 performanceCaculateOpType_ = type;
227 DRAWING_PERFORMANCE_START_CACULATE;
228 return;
229 }
230 } else {
231 opTypeCountMap[type] = 1; // 记录出现的第1次
232 }
233 if (curOpItemPtr->GetNextOpItemOffset() < offset + sizeof(OpItem)) {
234 break;
235 }
236 offset = curOpItemPtr->GetNextOpItemOffset();
237 } while (offset != 0 && count <= MAX_OPITEMSIZE);
238 }
239
UnmarshallingDrawOps(uint32_t * opItemCount)240 void DrawCmdList::UnmarshallingDrawOps(uint32_t* opItemCount)
241 {
242 if (PerformanceCaculate::GetDrawingTestRecordingEnabled()) {
243 CaculatePerformanceOpType();
244 }
245 if (performanceCaculateOpType_ != 0) {
246 LOGI("Drawing Performance UnmarshallingDrawOps begin %{public}lld", PerformanceCaculate::GetUpTime());
247 }
248
249 if (opAllocator_.GetSize() <= offset_ || width_ <= 0 || height_ <= 0) {
250 return;
251 }
252
253 UnmarshallingPlayer player = { *this };
254 drawOpItems_.clear();
255 lastOpGenSize_ = 0;
256 uint32_t opReplaceIndex = 0;
257 size_t offset = offset_;
258 uint32_t count = 0;
259 do {
260 count++;
261 if (opItemCount && ++(*opItemCount) > MAX_OPITEMSIZE) {
262 break;
263 }
264 void* itemPtr = opAllocator_.OffsetToAddr(offset, sizeof(OpItem));
265 auto* curOpItemPtr = static_cast<OpItem*>(itemPtr);
266 if (curOpItemPtr == nullptr) {
267 LOGE("DrawCmdList::UnmarshallingOps failed, opItem is nullptr");
268 break;
269 }
270 uint32_t type = curOpItemPtr->GetType();
271 auto op = player.Unmarshalling(type, itemPtr, opAllocator_.GetSize() - offset);
272 if (!op) {
273 if (curOpItemPtr->GetNextOpItemOffset() < offset + sizeof(OpItem)) {
274 break;
275 }
276 offset = curOpItemPtr->GetNextOpItemOffset();
277 continue;
278 }
279 if (opReplaceIndex < replacedOpListForBuffer_.size() &&
280 replacedOpListForBuffer_[opReplaceIndex].first == offset) {
281 auto* replacePtr = opAllocator_.OffsetToAddr(
282 replacedOpListForBuffer_[opReplaceIndex].second, sizeof(OpItem));
283 if (replacePtr == nullptr) {
284 LOGE("DrawCmdList::Unmarshalling replace Ops failed, replace op is nullptr");
285 break;
286 }
287 auto* replaceOpItemPtr = static_cast<OpItem*>(replacePtr);
288 size_t avaliableSize = opAllocator_.GetSize() - replacedOpListForBuffer_[opReplaceIndex].second;
289 auto replaceOp = player.Unmarshalling(replaceOpItemPtr->GetType(), replacePtr, avaliableSize);
290 if (replaceOp) {
291 drawOpItems_.emplace_back(replaceOp);
292 replacedOpListForVector_.emplace_back((drawOpItems_.size() - 1), op);
293 } else {
294 drawOpItems_.emplace_back(op);
295 }
296 opReplaceIndex++;
297 } else {
298 drawOpItems_.emplace_back(op);
299 }
300 if (curOpItemPtr->GetNextOpItemOffset() < offset + sizeof(OpItem)) {
301 break;
302 }
303 offset = curOpItemPtr->GetNextOpItemOffset();
304 if (!replacedOpListForBuffer_.empty() && offset >= replacedOpListForBuffer_[0].second) {
305 LOGD("DrawCmdList::UnmarshallingOps seek end by cache textOps");
306 break;
307 }
308 } while (offset != 0 && count <= MAX_OPITEMSIZE);
309 lastOpGenSize_ = opAllocator_.GetSize();
310
311 if ((int)imageAllocator_.GetSize() > 0) {
312 imageAllocator_.ClearData();
313 }
314
315 if (performanceCaculateOpType_ != 0) {
316 LOGI("Drawing Performance UnmarshallingDrawOps end %{public}lld", PerformanceCaculate::GetUpTime());
317 }
318 }
319
Playback(Canvas & canvas,const Rect * rect)320 void DrawCmdList::Playback(Canvas& canvas, const Rect* rect)
321 {
322 if (width_ <= 0 || height_ <= 0) {
323 return;
324 }
325 if (performanceCaculateOpType_ != 0) {
326 LOGI("Drawing Performance Playback begin %{public}lld", PerformanceCaculate::GetUpTime());
327 }
328 if (canvas.GetDrawingType() == DrawingType::RECORDING) {
329 PlaybackToDrawCmdList(static_cast<RecordingCanvas&>(canvas).GetDrawCmdList());
330 return;
331 }
332 std::lock_guard<std::recursive_mutex> lock(mutex_);
333 #ifdef ROSEN_OHOS
334 // invalidate cache if high contrast flag changed
335 if (isCached_ && canvas.isHighContrastEnabled() != cachedHighContrast_) {
336 ClearCache();
337 }
338 // Generate or clear cache if cache state changed
339 if (canvas.GetCacheType() == Drawing::CacheType::ENABLED && !isCached_) {
340 GenerateCache(&canvas, rect);
341 } else if (canvas.GetCacheType() == Drawing::CacheType::DISABLED && isCached_) {
342 ClearCache();
343 }
344 #endif
345 Rect tmpRect;
346 if (rect != nullptr) {
347 tmpRect = *rect;
348 }
349 if (mode_ == DrawCmdList::UnmarshalMode::IMMEDIATE) {
350 PlaybackByBuffer(canvas, &tmpRect);
351 } else if (mode_ == DrawCmdList::UnmarshalMode::DEFERRED) {
352 PlaybackByVector(canvas, &tmpRect);
353 }
354 if (performanceCaculateOpType_ != 0) {
355 DRAWING_PERFORMANCE_STOP_CACULATE;
356 performanceCaculateOpType_ = 0;
357 LOGI("Drawing Performance Playback end %{public}lld", PerformanceCaculate::GetUpTime());
358 }
359 }
360
GenerateCache(Canvas * canvas,const Rect * rect)361 void DrawCmdList::GenerateCache(Canvas* canvas, const Rect* rect)
362 {
363 #ifdef ROSEN_OHOS
364 if (isCached_) {
365 LOGD("DrawCmdList::GenerateCache Invoke multiple times");
366 return;
367 }
368
369 std::lock_guard<std::recursive_mutex> lock(mutex_);
370 if (mode_ == DrawCmdList::UnmarshalMode::IMMEDIATE) {
371 GenerateCacheByBuffer(canvas, rect);
372 } else if (mode_ == DrawCmdList::UnmarshalMode::DEFERRED) {
373 GenerateCacheByVector(canvas, rect);
374 }
375 #endif
376 }
377
GetIsCache() const378 bool DrawCmdList::GetIsCache() const
379 {
380 return isCached_;
381 }
382
SetIsCache(bool isCached)383 void DrawCmdList::SetIsCache(bool isCached)
384 {
385 isCached_ = isCached;
386 }
387
GetCachedHighContrast() const388 bool DrawCmdList::GetCachedHighContrast() const
389 {
390 return cachedHighContrast_;
391 }
392
SetCachedHighContrast(bool cachedHighContrast)393 void DrawCmdList::SetCachedHighContrast(bool cachedHighContrast)
394 {
395 cachedHighContrast_ = cachedHighContrast;
396 }
397
GetReplacedOpList()398 std::vector<std::pair<size_t, size_t>> DrawCmdList::GetReplacedOpList()
399 {
400 return replacedOpListForBuffer_;
401 }
402
SetReplacedOpList(std::vector<std::pair<size_t,size_t>> replacedOpList)403 void DrawCmdList::SetReplacedOpList(std::vector<std::pair<size_t, size_t>> replacedOpList)
404 {
405 replacedOpListForBuffer_ = replacedOpList;
406 }
407
UpdateNodeIdToPicture(NodeId nodeId)408 void DrawCmdList::UpdateNodeIdToPicture(NodeId nodeId)
409 {
410 if (drawOpItems_.size() == 0) {
411 return;
412 }
413 for (size_t i = 0; i < drawOpItems_.size(); ++i) {
414 auto opItem = drawOpItems_[i];
415 if (!opItem) {
416 continue;
417 }
418 opItem->SetNodeId(nodeId);
419 }
420 }
421
ClearCache()422 void DrawCmdList::ClearCache()
423 {
424 #ifdef ROSEN_OHOS
425 // restore the original op
426 for (auto& [index, op] : replacedOpListForVector_) {
427 op.swap(drawOpItems_[index]);
428 }
429 replacedOpListForVector_.clear();
430 replacedOpListForBuffer_.clear();
431 isCached_ = false;
432 #endif
433 }
434
GenerateCacheByVector(Canvas * canvas,const Rect * rect)435 void DrawCmdList::GenerateCacheByVector(Canvas* canvas, const Rect* rect)
436 {
437 #ifdef ROSEN_OHOS
438 if (drawOpItems_.size() == 0) {
439 return;
440 }
441 uint32_t opSize = drawOpItems_.size();
442 for (auto index = 0u; index < opSize; ++index) {
443 std::shared_ptr<DrawOpItem> op = drawOpItems_[index];
444 if (!op || op->GetType() != DrawOpItem::TEXT_BLOB_OPITEM) {
445 continue;
446 }
447 DrawTextBlobOpItem* textBlobOp = static_cast<DrawTextBlobOpItem*>(op.get());
448 auto replaceCache = textBlobOp->GenerateCachedOpItem(canvas);
449 if (replaceCache) {
450 replacedOpListForVector_.emplace_back(index, op);
451 drawOpItems_[index] = replaceCache;
452 }
453 }
454 isCached_ = true;
455 cachedHighContrast_ = canvas && canvas->isHighContrastEnabled();
456 #endif
457 }
458
GenerateCacheByBuffer(Canvas * canvas,const Rect * rect)459 void DrawCmdList::GenerateCacheByBuffer(Canvas* canvas, const Rect* rect)
460 {
461 #ifdef ROSEN_OHOS
462 if (opAllocator_.GetSize() <= offset_) {
463 return;
464 }
465
466 size_t offset = offset_;
467 GenerateCachedOpItemPlayer player = { *this, canvas, rect };
468 uint32_t maxOffset = opAllocator_.GetSize();
469 uint32_t count = 0;
470 do {
471 count++;
472 void* itemPtr = opAllocator_.OffsetToAddr(offset, sizeof(OpItem));
473 auto* curOpItemPtr = static_cast<OpItem*>(itemPtr);
474 if (curOpItemPtr == nullptr) {
475 LOGE("DrawCmdList::GenerateCacheByBuffer failed, opItem is nullptr");
476 break;
477 }
478 size_t avaliableSize = opAllocator_.GetSize() - offset;
479 bool replaceSuccess = player.GenerateCachedOpItem(curOpItemPtr->GetType(), itemPtr, avaliableSize);
480 if (replaceSuccess) {
481 replacedOpListForBuffer_.push_back({offset, lastOpItemOffset_.value()});
482 itemPtr = opAllocator_.OffsetToAddr(offset, sizeof(OpItem));
483 curOpItemPtr = static_cast<OpItem*>(itemPtr);
484 if (curOpItemPtr == nullptr) {
485 LOGE("DrawCmdList::GenerateCache failed, opItem is nullptr");
486 break;
487 }
488 }
489 if (curOpItemPtr->GetNextOpItemOffset() < offset + sizeof(OpItem)) {
490 break;
491 }
492 offset = curOpItemPtr->GetNextOpItemOffset();
493 } while (offset != 0 && offset < maxOffset && count <= MAX_OPITEMSIZE);
494 isCached_ = true;
495 cachedHighContrast_ = canvas && canvas->isHighContrastEnabled();
496 #endif
497 }
498
PlaybackToDrawCmdList(std::shared_ptr<DrawCmdList> drawCmdList)499 void DrawCmdList::PlaybackToDrawCmdList(std::shared_ptr<DrawCmdList> drawCmdList)
500 {
501 if (!drawCmdList) {
502 return;
503 }
504 std::lock_guard<std::recursive_mutex> lock(mutex_);
505 if (mode_ == DrawCmdList::UnmarshalMode::DEFERRED) {
506 std::lock_guard<std::recursive_mutex> lock(drawCmdList->mutex_);
507 drawCmdList->drawOpItems_.insert(drawCmdList->drawOpItems_.end(), drawOpItems_.begin(), drawOpItems_.end());
508 return;
509 }
510
511 void* addr = opAllocator_.OffsetToAddr(offset_, 0);
512 if (addr == nullptr) {
513 return;
514 }
515
516 {
517 std::lock_guard<std::mutex> lock(drawCmdList->recordCmdMutex_);
518 drawCmdList->recordCmdVec_.swap(recordCmdVec_);
519 }
520 #ifdef SUPPORT_OHOS_PIXMAP
521 {
522 std::lock_guard<std::mutex> lock(drawCmdList->imageObjectMutex_);
523 drawCmdList->imageObjectVec_.swap(imageObjectVec_);
524 }
525 #endif
526 {
527 std::lock_guard<std::mutex> lock(drawCmdList->imageBaseObjMutex_);
528 drawCmdList->imageBaseObjVec_.swap(imageBaseObjVec_);
529 }
530 size_t size = opAllocator_.GetSize() - offset_;
531 auto imageData = GetAllImageData();
532 auto bitmapData = GetAllBitmapData();
533 drawCmdList->opAllocator_.Add(addr, size);
534 if (imageData.first != nullptr && imageData.second != 0) {
535 drawCmdList->AddImageData(imageData.first, imageData.second);
536 }
537
538 if (bitmapData.first != nullptr && bitmapData.second != 0) {
539 drawCmdList->AddBitmapData(bitmapData.first, bitmapData.second);
540 }
541 }
542
PlaybackByVector(Canvas & canvas,const Rect * rect)543 void DrawCmdList::PlaybackByVector(Canvas& canvas, const Rect* rect)
544 {
545 if (drawOpItems_.empty()) {
546 return;
547 }
548 for (auto op : drawOpItems_) {
549 if (op) {
550 op->Playback(&canvas, rect);
551 }
552 }
553 canvas.DetachPaint();
554 }
555
PlaybackByBuffer(Canvas & canvas,const Rect * rect)556 void DrawCmdList::PlaybackByBuffer(Canvas& canvas, const Rect* rect)
557 {
558 if (opAllocator_.GetSize() <= offset_) {
559 return;
560 }
561 size_t offset = offset_;
562 if (lastOpGenSize_ != opAllocator_.GetSize()) {
563 uint32_t count = 0;
564 UnmarshallingPlayer player = { *this };
565 drawOpItems_.clear();
566 do {
567 count++;
568 void* itemPtr = opAllocator_.OffsetToAddr(offset, sizeof(OpItem));
569 auto* curOpItemPtr = static_cast<OpItem*>(itemPtr);
570 if (curOpItemPtr == nullptr) {
571 break;
572 }
573 uint32_t type = curOpItemPtr->GetType();
574 if (auto op = player.Unmarshalling(type, itemPtr, opAllocator_.GetSize() - offset)) {
575 drawOpItems_.emplace_back(op);
576 }
577 if (curOpItemPtr->GetNextOpItemOffset() < offset + sizeof(OpItem)) {
578 break;
579 }
580 offset = curOpItemPtr->GetNextOpItemOffset();
581 } while (offset != 0 && count <= MAX_OPITEMSIZE);
582 lastOpGenSize_ = opAllocator_.GetSize();
583 }
584 for (auto op : drawOpItems_) {
585 if (op) {
586 op->Playback(&canvas, rect);
587 }
588 }
589 canvas.DetachPaint();
590 }
591
CountTextBlobNum()592 size_t DrawCmdList::CountTextBlobNum()
593 {
594 size_t textBlobCnt = 0;
595 if (mode_ == DrawCmdList::UnmarshalMode::IMMEDIATE) {
596 size_t offset = offset_;
597 size_t maxOffset = opAllocator_.GetSize();
598 uint32_t count = 0;
599 do {
600 count++;
601 void* itemPtr = opAllocator_.OffsetToAddr(offset, sizeof(OpItem));
602 auto* curOpItemPtr = static_cast<OpItem*>(itemPtr);
603 if (curOpItemPtr == nullptr) {
604 break;
605 }
606 uint32_t type = curOpItemPtr->GetType();
607 if (type == DrawOpItem::TEXT_BLOB_OPITEM) {
608 textBlobCnt++;
609 }
610 if (curOpItemPtr->GetNextOpItemOffset() < offset + sizeof(OpItem)) {
611 break;
612 }
613 offset = curOpItemPtr->GetNextOpItemOffset();
614 } while (offset != 0 && offset < maxOffset && count <= MAX_OPITEMSIZE);
615 }
616 return textBlobCnt;
617 }
618
Purge()619 void DrawCmdList::Purge()
620 {
621 std::lock_guard<std::recursive_mutex> lock(mutex_);
622 for (auto op : drawOpItems_) {
623 if (!op) {
624 continue;
625 }
626 auto type = op->GetType();
627 if (type == DrawOpItem::PIXELMAP_RECT_OPITEM ||
628 type == DrawOpItem::PIXELMAP_WITH_PARM_OPITEM) {
629 op->Purge();
630 }
631 }
632 }
633
SetIsNeedUnmarshalOnDestruct(bool isNeedUnmarshalOnDestruct)634 void DrawCmdList::SetIsNeedUnmarshalOnDestruct(bool isNeedUnmarshalOnDestruct)
635 {
636 isNeedUnmarshalOnDestruct_ = isNeedUnmarshalOnDestruct;
637 }
638 } // namespace Drawing
639 } // namespace Rosen
640 } // namespace OHOS
641