• 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 
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