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 "pipeline/rs_canvas_drawing_render_node.h"
17
18 #include <memory>
19
20 #include "include/core/SkCanvas.h"
21 #include "src/image/SkImage_Base.h"
22 #ifdef NEW_SKIA
23 #include "include/gpu/GrBackendSurface.h"
24 #include "include/gpu/GrDirectContext.h"
25 #endif
26
27 #include "rs_trace.h"
28
29 #include "common/rs_background_thread.h"
30 #include "common/rs_common_def.h"
31 #include "common/rs_obj_abs_geometry.h"
32 #include "common/rs_optional_trace.h"
33 #include "params/rs_canvas_drawing_render_params.h"
34 #include "pipeline/rs_context.h"
35 #include "pipeline/rs_paint_filter_canvas.h"
36 #include "pipeline/rs_recording_canvas.h"
37 #include "pipeline/rs_task_dispatcher.h"
38 #include "pipeline/rs_uni_render_judgement.h"
39 #include "pipeline/sk_resource_manager.h"
40 #include "platform/common/rs_log.h"
41 #include "property/rs_properties_painter.h"
42 #include "visitor/rs_node_visitor.h"
43
44 namespace OHOS {
45 namespace Rosen {
46 static std::mutex drawingMutex_;
47 namespace {
48 constexpr uint32_t DRAWCMDLIST_COUNT_LIMIT = 300;
49 }
RSCanvasDrawingRenderNode(NodeId id,const std::weak_ptr<RSContext> & context,bool isTextureExportNode)50 RSCanvasDrawingRenderNode::RSCanvasDrawingRenderNode(
51 NodeId id, const std::weak_ptr<RSContext>& context, bool isTextureExportNode)
52 : RSCanvasRenderNode(id, context, isTextureExportNode)
53 {
54 MemorySnapshot::Instance().AddCpuMemory(ExtractPid(id), sizeof(*this) - sizeof(RSCanvasRenderNode));
55 }
56
~RSCanvasDrawingRenderNode()57 RSCanvasDrawingRenderNode::~RSCanvasDrawingRenderNode()
58 {
59 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
60 if (preThreadInfo_.second && surface_) {
61 preThreadInfo_.second(std::move(surface_));
62 }
63 #endif
64 MemorySnapshot::Instance().RemoveCpuMemory(ExtractPid(GetId()), sizeof(*this) - sizeof(RSCanvasRenderNode));
65 }
66
InitRenderContent()67 void RSCanvasDrawingRenderNode::InitRenderContent()
68 {
69 drawingNodeRenderID = UNI_RENDER_THREAD_INDEX;
70 }
71
72 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
ResetSurfaceWithTexture(int width,int height,RSPaintFilterCanvas & canvas)73 bool RSCanvasDrawingRenderNode::ResetSurfaceWithTexture(int width, int height, RSPaintFilterCanvas& canvas)
74 {
75 if (canvas_ == nullptr) {
76 RS_LOGE("canvas_ is nullptr");
77 return false;
78 }
79 auto preMatrix = canvas_->GetTotalMatrix();
80 auto preSurface = surface_;
81 if (!ResetSurface(width, height, canvas)) {
82 return false;
83 }
84 auto image = preSurface->GetImageSnapshot();
85 if (!image) {
86 return false;
87 }
88 Drawing::TextureOrigin origin = RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL
89 ? Drawing::TextureOrigin::BOTTOM_LEFT : Drawing::TextureOrigin::TOP_LEFT;
90 auto sharedBackendTexture = image->GetBackendTexture(false, &origin);
91 if (!sharedBackendTexture.IsValid()) {
92 RS_LOGE("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture sharedBackendTexture is nullptr");
93 return false;
94 }
95 Drawing::BitmapFormat bitmapFormat = { image->GetColorType(), image->GetAlphaType() };
96 auto sharedTexture = std::make_shared<Drawing::Image>();
97 auto context = canvas.GetGPUContext();
98 if (!context || !sharedTexture->BuildFromTexture(*context, sharedBackendTexture.GetTextureInfo(),
99 origin, bitmapFormat, nullptr, SKResourceManager::DeleteSharedTextureContext,
100 new SharedTextureContext(image))) {
101 RS_LOGE("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture sharedTexture is nullptr");
102 return false;
103 }
104 if (RSSystemProperties::GetRecordingEnabled()) {
105 if (sharedTexture->IsTextureBacked()) {
106 RS_LOGI("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture sharedTexture from texture to raster image");
107 sharedTexture = sharedTexture->MakeRasterImage();
108 if (!sharedTexture) {
109 RS_LOGE("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture: MakeRasterImage failed");
110 return false;
111 }
112 }
113 }
114 canvas_->DrawImage(*sharedTexture, 0.f, 0.f, Drawing::SamplingOptions());
115 if (preThreadInfo_.second && preSurface) {
116 preThreadInfo_.second(std::move(preSurface));
117 }
118 preThreadInfo_ = curThreadInfo_;
119 canvas_->SetMatrix(preMatrix);
120 canvas_->Flush();
121 return true;
122 }
123 #endif
124
ProcessRenderContents(RSPaintFilterCanvas & canvas)125 void RSCanvasDrawingRenderNode::ProcessRenderContents(RSPaintFilterCanvas& canvas)
126 {
127 int width = 0;
128 int height = 0;
129 std::lock_guard<std::mutex> lockTask(taskMutex_);
130 if (!GetSizeFromDrawCmdModifiers(width, height)) {
131 return;
132 }
133
134 if (IsNeedResetSurface()) {
135 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
136 if (preThreadInfo_.second && surface_) {
137 preThreadInfo_.second(std::move(surface_));
138 }
139 preThreadInfo_ = curThreadInfo_;
140 #endif
141 if (!ResetSurface(width, height, canvas)) {
142 return;
143 }
144 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
145 } else if ((isGpuSurface_) && (preThreadInfo_.first != curThreadInfo_.first)) {
146 if (!ResetSurfaceWithTexture(width, height, canvas)) {
147 return;
148 }
149 }
150 #else
151 }
152 #endif
153 if (!surface_) {
154 return;
155 }
156
157 RSModifierContext context = { GetMutableRenderProperties(), canvas_.get() };
158 ApplyDrawCmdModifier(context, RSModifierType::CONTENT_STYLE);
159 isNeedProcess_ = false;
160
161 Rosen::Drawing::Matrix mat;
162 if (RSPropertiesPainter::GetGravityMatrix(
163 GetRenderProperties().GetFrameGravity(), GetRenderProperties().GetFrameRect(), width, height, mat)) {
164 canvas.ConcatMatrix(mat);
165 }
166 if (!recordingCanvas_) {
167 image_ = surface_->GetImageSnapshot();
168 if (image_) {
169 SKResourceManager::Instance().HoldResource(image_);
170 }
171 } else {
172 auto cmds = recordingCanvas_->GetDrawCmdList();
173 if (cmds && !cmds->IsEmpty()) {
174 recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
175 canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
176 }
177 }
178 std::lock_guard<std::mutex> lock(imageMutex_);
179 if (!image_) {
180 return;
181 }
182 auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
183 Drawing::Paint paint;
184 paint.SetStyle(Drawing::Paint::PaintStyle::PAINT_FILL);
185 canvas.AttachPaint(paint);
186 if (canvas.GetRecordingState()) {
187 auto cpuImage = image_->MakeRasterImage();
188 if (!cpuImage) {
189 RS_LOGE("RSCanvasDrawingRenderNode::ProcessRenderContents: MakeRasterImage failed");
190 canvas.DetachPaint();
191 return;
192 }
193 canvas.DrawImage(*cpuImage, 0.f, 0.f, samplingOptions);
194 } else {
195 canvas.DrawImage(*image_, 0.f, 0.f, samplingOptions);
196 }
197 canvas.DetachPaint();
198 }
199
IsNeedProcess() const200 bool RSCanvasDrawingRenderNode::IsNeedProcess() const
201 {
202 if (!renderDrawable_) {
203 return false;
204 }
205 return renderDrawable_->IsNeedDraw();
206 }
207
ContentStyleSlotUpdate()208 void RSCanvasDrawingRenderNode::ContentStyleSlotUpdate()
209 {
210 // update content_style when node not on tree, need check (waitSync_ false, not on tree, never on tree
211 // not texture exportnode, unirender mode)
212 // if canvas drawing node never on tree, should not update, it will lost renderParams->localDrawRect_
213 #ifdef RS_ENABLE_GPU
214 if (IsWaitSync() || IsOnTheTree() || isNeverOnTree_ || !stagingRenderParams_ ||
215 !RSUniRenderJudgement::IsUniRender() || GetIsTextureExportNode()) {
216 return;
217 }
218 #else
219 if (IsWaitSync() || IsOnTheTree() || isNeverOnTree_ || !stagingRenderParams_ ||
220 !RSUniRenderJudgement::IsUniRender() || GetIsTextureExportNode()) {
221 return;
222 }
223 #endif
224
225 if (!dirtyTypes_.test(static_cast<size_t>(RSModifierType::CONTENT_STYLE))) {
226 return;
227 }
228 #ifdef RS_ENABLE_GPU
229 auto surfaceParams = GetStagingRenderParams()->GetCanvasDrawingSurfaceParams();
230 if (surfaceParams.width == 0 || surfaceParams.height == 0) {
231 RS_LOGE("RSCanvasDrawingRenderNode::ContentStyleSlotUpdate Area Size Error, NodeId[%{public}" PRIu64 "]"
232 "width[%{public}d], height[%{public}d]", GetId(), surfaceParams.width, surfaceParams.height);
233 return;
234 }
235 #endif
236
237 //only update content_style dirtyType
238 auto savedirtyTypes = dirtyTypes_;
239 dirtyTypes_.reset();
240 dirtyTypes_.set(static_cast<int>(RSModifierType::CONTENT_STYLE), true);
241 isPostPlaybacked_ = true;
242
243 UpdateDrawableVecV2();
244
245 if (!IsWaitSync()) {
246 RS_LOGE("RSCanvasDrawingRenderNode::ContentStyleSlotUpdate NodeId[%{public}" PRIu64
247 "] UpdateDrawableVecV2 failed, dirtySlots empty", GetId());
248 return;
249 }
250
251 RS_LOGI("RSCanvasDrawingRenderNode::ContentStyleSlotUpdate NodeId[%{public}" PRIu64 "]", GetId());
252 RS_OPTIONAL_TRACE_NAME_FMT("canvas drawing node[%llu] ContentStyleSlotUpdate", GetId());
253
254 // clear content_style drawcmdlist
255 std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
256 auto contentCmdList = drawCmdLists_.find(RSModifierType::CONTENT_STYLE);
257 if (contentCmdList != drawCmdLists_.end()) {
258 contentCmdList->second.clear();
259 }
260 savedirtyTypes.set(static_cast<int>(RSModifierType::CONTENT_STYLE), false);
261 dirtyTypes_ = savedirtyTypes;
262
263 AddToPendingSyncList();
264 }
265
SetNeedProcess(bool needProcess)266 void RSCanvasDrawingRenderNode::SetNeedProcess(bool needProcess)
267 {
268 if (!stagingRenderParams_) {
269 return;
270 }
271 #ifdef RS_ENABLE_GPU
272 stagingRenderParams_->SetNeedSync(needProcess);
273 isNeedProcess_ = needProcess;
274 #else
275 isNeedProcess_ = false;
276 #endif
277 }
278
PlaybackInCorrespondThread()279 void RSCanvasDrawingRenderNode::PlaybackInCorrespondThread()
280 {
281 auto nodeId = GetId();
282 auto ctx = GetContext().lock();
283 if (ctx == nullptr) {
284 return;
285 }
286 auto task = [nodeId, ctx, this]() {
287 std::lock_guard<std::mutex> lockTask(taskMutex_);
288 auto node = ctx->GetNodeMap().GetRenderNode<RSCanvasDrawingRenderNode>(nodeId);
289 if (!node || !surface_ || !canvas_) {
290 return;
291 }
292 RSModifierContext context = { GetMutableRenderProperties(), canvas_.get() };
293 ApplyDrawCmdModifier(context, RSModifierType::CONTENT_STYLE);
294 isNeedProcess_ = false;
295 };
296 RSTaskDispatcher::GetInstance().PostTask(threadId_, task, false);
297 }
298
ResetSurface(int width,int height,RSPaintFilterCanvas & canvas)299 bool RSCanvasDrawingRenderNode::ResetSurface(int width, int height, RSPaintFilterCanvas& canvas)
300 {
301 Drawing::ImageInfo info =
302 Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
303
304 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
305 #if (defined(ROSEN_IOS))
306 surface_ = Drawing::Surface::MakeRaster(info);
307 #else
308 auto gpuContext = canvas.GetGPUContext();
309 isGpuSurface_ = true;
310 if (gpuContext == nullptr) {
311 RS_LOGD("RSCanvasDrawingRenderNode::ResetSurface: gpuContext is nullptr");
312 isGpuSurface_ = false;
313 surface_ = Drawing::Surface::MakeRaster(info);
314 } else {
315 surface_ = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, info);
316 if (!surface_) {
317 isGpuSurface_ = false;
318 surface_ = Drawing::Surface::MakeRaster(info);
319 RS_LOGW("RSCanvasDrawingRenderNode::ResetSurface [%{public}d, %{public}d] %{public}" PRIu64 "",
320 width, height, GetId());
321 if (!surface_) {
322 RS_LOGE("RSCanvasDrawingRenderNode::ResetSurface surface is nullptr");
323 return false;
324 }
325 recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
326 canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
327 return true;
328 }
329 }
330 #endif
331 #else
332 surface_ = Drawing::Surface::MakeRaster(info);
333 #endif
334 if (!surface_) {
335 RS_LOGE("RSCanvasDrawingRenderNode::ResetSurface surface is nullptr");
336 return false;
337 }
338 canvas_ = std::make_unique<RSPaintFilterCanvas>(surface_.get());
339 return true;
340 }
341
ApplyDrawCmdModifier(RSModifierContext & context,RSModifierType type)342 void RSCanvasDrawingRenderNode::ApplyDrawCmdModifier(RSModifierContext& context, RSModifierType type)
343 {
344 std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
345 auto it = drawCmdLists_.find(type);
346 if (it == drawCmdLists_.end() || it->second.empty()) {
347 return;
348 }
349 for (const auto& drawCmdList : it->second) {
350 drawCmdList->Playback(*context.canvas_);
351 drawCmdList->ClearOp();
352 }
353 context.canvas_->Flush();
354 it->second.clear();
355 }
356
GetTid() const357 uint32_t RSCanvasDrawingRenderNode::GetTid() const
358 {
359 if (UNI_RENDER_THREAD_INDEX == drawingNodeRenderID) {
360 return drawingNodeRenderID;
361 }
362 return curThreadInfo_.first;
363 }
364
GetBitmap()365 Drawing::Bitmap RSCanvasDrawingRenderNode::GetBitmap()
366 {
367 return GetBitmap(UNI_MAIN_THREAD_INDEX);
368 }
369
WriteSkImageToPixelmap(std::shared_ptr<Drawing::Image> image,Drawing::ImageInfo info,std::shared_ptr<Media::PixelMap> pixelmap,const Drawing::Rect * rect)370 bool WriteSkImageToPixelmap(std::shared_ptr<Drawing::Image> image, Drawing::ImageInfo info,
371 std::shared_ptr<Media::PixelMap> pixelmap, const Drawing::Rect* rect)
372 {
373 return image->ReadPixels(
374 info, pixelmap->GetWritablePixels(), pixelmap->GetRowStride(), rect->GetLeft(), rect->GetTop());
375 }
376
GetImage(const uint64_t tid)377 std::shared_ptr<Drawing::Image> RSCanvasDrawingRenderNode::GetImage(const uint64_t tid)
378 {
379 if (GetTid() != tid) {
380 RS_LOGE("RSCanvasDrawingRenderNode::GetImage: image_ used by multi threads");
381 return nullptr;
382 }
383 if (!image_) {
384 RS_LOGE("RSCanvasDrawingRenderNode::GetImage: image_ is nullptr");
385 }
386 return image_;
387 }
388
GetBitmap(const uint64_t tid)389 Drawing::Bitmap RSCanvasDrawingRenderNode::GetBitmap(const uint64_t tid)
390 {
391 Drawing::Bitmap bitmap;
392 std::lock_guard<std::mutex> lock(drawingMutex_);
393 if (!image_) {
394 RS_LOGE("RSCanvasDrawingRenderNode::GetBitmap: image_ is nullptr");
395 return bitmap;
396 }
397 if (GetTid() != tid) {
398 RS_LOGE("RSCanvasDrawingRenderNode::GetBitmap: image_ used by multi threads");
399 return bitmap;
400 }
401 if (!image_->AsLegacyBitmap(bitmap)) {
402 RS_LOGE("RSCanvasDrawingRenderNode::GetBitmap: asLegacyBitmap failed");
403 }
404 return bitmap;
405 }
406
GetPixelmap(std::shared_ptr<Media::PixelMap> pixelmap,const Drawing::Rect * rect,const uint64_t tid,std::shared_ptr<Drawing::DrawCmdList> drawCmdList)407 bool RSCanvasDrawingRenderNode::GetPixelmap(std::shared_ptr<Media::PixelMap> pixelmap, const Drawing::Rect* rect,
408 const uint64_t tid, std::shared_ptr<Drawing::DrawCmdList> drawCmdList)
409 {
410 std::lock_guard<std::mutex> lock(drawingMutex_);
411 if (!pixelmap || !rect) {
412 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: pixelmap is nullptr");
413 return false;
414 }
415
416 if (!surface_) {
417 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: surface is nullptr");
418 return false;
419 }
420
421 auto image = surface_->GetImageSnapshot();
422 if (image == nullptr) {
423 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: GetImageSnapshot failed");
424 return false;
425 }
426
427 if (GetTid() != tid) {
428 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: surface used by multi threads");
429 return false;
430 }
431
432 Drawing::ImageInfo info = Drawing::ImageInfo { pixelmap->GetWidth(), pixelmap->GetHeight(),
433 Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
434 if (!drawCmdList) {
435 if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
436 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
437 return false;
438 }
439 return true;
440 }
441 std::shared_ptr<Drawing::Surface> surface;
442 std::unique_ptr<RSPaintFilterCanvas> canvas;
443 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
444 if (!canvas_) {
445 return false;
446 }
447 auto gpuContext = canvas_->GetGPUContext();
448 if (gpuContext == nullptr) {
449 if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
450 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
451 }
452 return false;
453 } else {
454 Drawing::ImageInfo newInfo = Drawing::ImageInfo{ image->GetWidth(), image->GetHeight(),
455 Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
456 surface = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, newInfo);
457 if (!surface) {
458 if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
459 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
460 }
461 return false;
462 }
463 canvas = std::make_unique<RSPaintFilterCanvas>(surface.get());
464 }
465 #else
466 if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
467 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
468 }
469 return false;
470 #endif
471 canvas->DrawImage(*image, 0, 0, Drawing::SamplingOptions());
472 drawCmdList->Playback(*canvas, rect);
473 auto pixelmapImage = surface->GetImageSnapshot();
474 if (!pixelmapImage) {
475 return false;
476 }
477 if (!WriteSkImageToPixelmap(pixelmapImage, info, pixelmap, rect)) {
478 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
479 return false;
480 }
481 return true;
482 }
483
GetSizeFromDrawCmdModifiers(int & width,int & height)484 bool RSCanvasDrawingRenderNode::GetSizeFromDrawCmdModifiers(int& width, int& height)
485 {
486 auto it = GetDrawCmdModifiers().find(RSModifierType::CONTENT_STYLE);
487 if (it == GetDrawCmdModifiers().end() || it->second.empty()) {
488 return false;
489 }
490 for (const auto& modifier : it->second) {
491 auto prop = modifier->GetProperty();
492 if (auto cmd = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(prop)->Get()) {
493 width = std::max(width, cmd->GetWidth());
494 height = std::max(height, cmd->GetHeight());
495 }
496 }
497 if (width <= 0 || height <= 0) {
498 RS_LOGE("RSCanvasDrawingRenderNode::GetSizeFromDrawCmdModifiers: The width or height of the canvas is less "
499 "than or equal to 0");
500 return false;
501 }
502 return true;
503 }
504
IsNeedResetSurface() const505 bool RSCanvasDrawingRenderNode::IsNeedResetSurface() const
506 {
507 if (!surface_ || !surface_->GetCanvas()) {
508 return true;
509 }
510 return false;
511 }
512
InitRenderParams()513 void RSCanvasDrawingRenderNode::InitRenderParams()
514 {
515 #ifdef RS_ENABLE_GPU
516 stagingRenderParams_ = std::make_unique<RSCanvasDrawingRenderParams>(GetId());
517 DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(shared_from_this());
518 if (renderDrawable_ == nullptr) {
519 RS_LOGE("RSCanvasDrawingRenderNode::InitRenderParams failed");
520 return;
521 }
522 #endif
523 }
524
CheckDrawCmdListSize(RSModifierType type,size_t originCmdListSize)525 void RSCanvasDrawingRenderNode::CheckDrawCmdListSize(RSModifierType type, size_t originCmdListSize)
526 {
527 bool overflow = drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT;
528 if (overflow) {
529 RS_OPTIONAL_TRACE_NAME_FMT("AddDitryType id:[%llu] StateOnTheTree[%d] ModifierType[%d] ModifierCmdSize[%d]"
530 "originCmdListSize[%d], CmdCount[%d]", GetId(), IsOnTheTree(), type, drawCmdLists_[type].size(),
531 originCmdListSize, cmdCount_);
532 if (overflow != lastOverflowStatus_) {
533 RS_LOGE("AddDirtyType Out of Cmdlist Limit, This Node[%{public}" PRIu64 "] with Modifier[%{public}hd]"
534 " have drawcmdlist:%{public}zu, StateOnTheTree[%{public}d], originCmdListSize[%{public}zu],"
535 " CmdCount:[%{public}d]", GetId(), type, drawCmdLists_[type].size(), IsOnTheTree(),
536 originCmdListSize, cmdCount_);
537 }
538 // If such nodes are not drawn, The drawcmdlists don't clearOp during recording, As a result, there are
539 // too many drawOp, so we need to add the limit of drawcmdlists.
540 while ((GetOldDirtyInSurface().IsEmpty() || !IsDirty() || renderDrawable_) &&
541 drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT) {
542 drawCmdLists_[type].pop_front();
543 }
544 if (drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT) {
545 RS_LOGE("AddDirtyType Cmdlist Protect Error, This Node[%{public}" PRIu64 "] with Modifier[%{public}hd]"
546 " have drawcmdlist:%{public}zu, StateOnTheTree[%{public}d], originCmdListSize[%{public}zu],"
547 " CmdCount:[%{public}d]", GetId(), type, drawCmdLists_[type].size(), IsOnTheTree(),
548 originCmdListSize, cmdCount_);
549 }
550 }
551 lastOverflowStatus_ = overflow;
552 }
553
AddDirtyType(RSModifierType modifierType)554 void RSCanvasDrawingRenderNode::AddDirtyType(RSModifierType modifierType)
555 {
556 dirtyTypes_.set(static_cast<int>(modifierType), true);
557 if (modifierType != RSModifierType::CONTENT_STYLE) {
558 return;
559 }
560 std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
561 const auto itr = GetDrawCmdModifiers().find(modifierType);
562 if (itr == GetDrawCmdModifiers().end()) {
563 return;
564 }
565
566 size_t originCmdListSize = drawCmdLists_[modifierType].size();
567 for (const auto& modifier : itr->second) {
568 if (modifier == nullptr) {
569 continue;
570 }
571 auto prop = modifier->GetProperty();
572 if (prop == nullptr) {
573 continue;
574 }
575 auto cmd = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(prop)->Get();
576 if (cmd == nullptr) {
577 continue;
578 }
579
580 cmd->SetCanvasDrawingOpLimitEnable(true);
581 drawCmdLists_[modifierType].emplace_back(cmd);
582 ++cmdCount_;
583 SetNeedProcess(true);
584 }
585 CheckDrawCmdListSize(modifierType, originCmdListSize);
586 }
587
ClearOp()588 void RSCanvasDrawingRenderNode::ClearOp()
589 {
590 std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
591 drawCmdLists_.clear();
592 }
593
ResetSurface(int width,int height)594 void RSCanvasDrawingRenderNode::ResetSurface(int width, int height)
595 {
596 std::lock_guard<std::mutex> lockTask(taskMutex_);
597 cmdCount_ = 0;
598 if (preThreadInfo_.second && surface_) {
599 preThreadInfo_.second(std::move(surface_));
600 }
601 surface_ = nullptr;
602 recordingCanvas_ = nullptr;
603 #ifdef RS_ENABLE_GPU
604 stagingRenderParams_->SetCanvasDrawingSurfaceChanged(true);
605 stagingRenderParams_->SetCanvasDrawingSurfaceParams(width, height);
606 #endif
607 }
608
GetDrawCmdLists() const609 const std::map<RSModifierType, std::list<Drawing::DrawCmdListPtr>>& RSCanvasDrawingRenderNode::GetDrawCmdLists() const
610 {
611 return drawCmdLists_;
612 }
613
ClearResource()614 void RSCanvasDrawingRenderNode::ClearResource()
615 {
616 if (RSUniRenderJudgement::IsUniRender() && !GetIsTextureExportNode()) {
617 std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
618 drawCmdLists_.clear();
619 }
620 }
621
ClearNeverOnTree()622 void RSCanvasDrawingRenderNode::ClearNeverOnTree()
623 {
624 isNeverOnTree_ = false;
625 }
626
CheckCanvasDrawingPostPlaybacked()627 void RSCanvasDrawingRenderNode::CheckCanvasDrawingPostPlaybacked()
628 {
629 if (isPostPlaybacked_) {
630 RS_OPTIONAL_TRACE_NAME_FMT("canvas drawing node [%" PRIu64 "] CheckCanvasDrawingPostPlaybacked", GetId());
631 // add empty drawop, only used in unirender mode
632 dirtyTypes_.set(static_cast<int>(RSModifierType::CONTENT_STYLE), true);
633 auto contentCmdList = drawCmdLists_.find(RSModifierType::CONTENT_STYLE);
634 if (contentCmdList != drawCmdLists_.end()) {
635 auto cmd = std::make_shared<Drawing::DrawCmdList>();
636 contentCmdList->second.emplace_back(cmd);
637 }
638 isPostPlaybacked_ = false;
639 }
640 }
641
GetIsPostPlaybacked()642 bool RSCanvasDrawingRenderNode::GetIsPostPlaybacked()
643 {
644 return isPostPlaybacked_;
645 }
646
647 } // namespace Rosen
648 } // namespace OHOS