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 "params/rs_canvas_drawing_render_params.h"
33 #include "pipeline/rs_context.h"
34 #include "pipeline/rs_paint_filter_canvas.h"
35 #include "pipeline/rs_recording_canvas.h"
36 #include "pipeline/rs_task_dispatcher.h"
37 #include "pipeline/sk_resource_manager.h"
38 #include "platform/common/rs_log.h"
39 #include "property/rs_properties_painter.h"
40 #include "visitor/rs_node_visitor.h"
41 
42 namespace OHOS {
43 namespace Rosen {
44 static std::mutex drawingMutex_;
45 namespace {
46 constexpr uint32_t DRAWCMDLIST_COUNT_LIMIT = 50;
47 constexpr uint32_t DRAWCMDLIST_OPSIZE_COUNT_LIMIT = 50000;
48 }
RSCanvasDrawingRenderNode(NodeId id,const std::weak_ptr<RSContext> & context,bool isTextureExportNode)49 RSCanvasDrawingRenderNode::RSCanvasDrawingRenderNode(
50     NodeId id, const std::weak_ptr<RSContext>& context, bool isTextureExportNode)
51     : RSCanvasRenderNode(id, context, isTextureExportNode)
52 {}
53 
~RSCanvasDrawingRenderNode()54 RSCanvasDrawingRenderNode::~RSCanvasDrawingRenderNode()
55 {
56 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
57     if (preThreadInfo_.second && surface_) {
58         preThreadInfo_.second(std::move(surface_));
59     }
60 #endif
61 }
62 
InitRenderContent()63 void RSCanvasDrawingRenderNode::InitRenderContent()
64 {
65     drawingNodeRenderID = UNI_RENDER_THREAD_INDEX;
66 }
67 
68 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
ResetSurfaceWithTexture(int width,int height,RSPaintFilterCanvas & canvas)69 bool RSCanvasDrawingRenderNode::ResetSurfaceWithTexture(int width, int height, RSPaintFilterCanvas& canvas)
70 {
71     if (canvas_ == nullptr) {
72         RS_LOGE("canvas_ is nullptr");
73         return false;
74     }
75     auto preMatrix = canvas_->GetTotalMatrix();
76     auto preSurface = surface_;
77     if (!ResetSurface(width, height, canvas)) {
78         return false;
79     }
80     auto image = preSurface->GetImageSnapshot();
81     if (!image) {
82         return false;
83     }
84     Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
85     auto sharedBackendTexture = image->GetBackendTexture(false, &origin);
86     if (!sharedBackendTexture.IsValid()) {
87         RS_LOGE("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture sharedBackendTexture is nullptr");
88         return false;
89     }
90 
91     Drawing::BitmapFormat bitmapFormat = { image->GetColorType(), image->GetAlphaType() };
92     auto sharedTexture = std::make_shared<Drawing::Image>();
93     auto context = canvas.GetGPUContext();
94     if (!context || !sharedTexture->BuildFromTexture(*context, sharedBackendTexture.GetTextureInfo(),
95         origin, bitmapFormat, nullptr, SKResourceManager::DeleteSharedTextureContext,
96         new SharedTextureContext(image))) {
97         RS_LOGE("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture sharedTexture is nullptr");
98         return false;
99     }
100     if (RSSystemProperties::GetRecordingEnabled()) {
101         if (sharedTexture->IsTextureBacked()) {
102             RS_LOGI("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture sharedTexture from texture to raster image");
103             sharedTexture = sharedTexture->MakeRasterImage();
104             if (!sharedTexture) {
105                 RS_LOGE("RSCanvasDrawingRenderNode::ResetSurfaceWithTexture: MakeRasterImage failed");
106                 return false;
107             }
108         }
109     }
110     canvas_->DrawImage(*sharedTexture, 0.f, 0.f, Drawing::SamplingOptions());
111     if (preThreadInfo_.second && preSurface) {
112         preThreadInfo_.second(std::move(preSurface));
113     }
114     preThreadInfo_ = curThreadInfo_;
115     canvas_->SetMatrix(preMatrix);
116     canvas_->Flush();
117     return true;
118 }
119 #endif
120 
ProcessRenderContents(RSPaintFilterCanvas & canvas)121 void RSCanvasDrawingRenderNode::ProcessRenderContents(RSPaintFilterCanvas& canvas)
122 {
123     int width = 0;
124     int height = 0;
125     std::lock_guard<std::mutex> lockTask(taskMutex_);
126     if (!GetSizeFromDrawCmdModifiers(width, height)) {
127         return;
128     }
129 
130     if (IsNeedResetSurface()) {
131 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
132         if (preThreadInfo_.second && surface_) {
133             preThreadInfo_.second(std::move(surface_));
134         }
135         preThreadInfo_ = curThreadInfo_;
136 #endif
137         if (!ResetSurface(width, height, canvas)) {
138             return;
139         }
140 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
141     } else if ((isGpuSurface_) && (preThreadInfo_.first != curThreadInfo_.first)) {
142         if (!ResetSurfaceWithTexture(width, height, canvas)) {
143             return;
144         }
145     }
146 #else
147     }
148 #endif
149     if (!surface_) {
150         return;
151     }
152 
153     RSModifierContext context = { GetMutableRenderProperties(), canvas_.get() };
154     ApplyDrawCmdModifier(context, RSModifierType::CONTENT_STYLE);
155     isNeedProcess_ = false;
156 
157     Rosen::Drawing::Matrix mat;
158     if (RSPropertiesPainter::GetGravityMatrix(
159             GetRenderProperties().GetFrameGravity(), GetRenderProperties().GetFrameRect(), width, height, mat)) {
160         canvas.ConcatMatrix(mat);
161     }
162     if (!recordingCanvas_) {
163         image_ = surface_->GetImageSnapshot();
164         if (image_) {
165             SKResourceManager::Instance().HoldResource(image_);
166         }
167     } else {
168         auto cmds = recordingCanvas_->GetDrawCmdList();
169         if (cmds && !cmds->IsEmpty()) {
170             recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
171             canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
172         }
173     }
174     std::lock_guard<std::mutex> lock(imageMutex_);
175     if (!image_) {
176         return;
177     }
178     auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::LINEAR);
179     Drawing::Paint paint;
180     paint.SetStyle(Drawing::Paint::PaintStyle::PAINT_FILL);
181     canvas.AttachPaint(paint);
182     if (canvas.GetRecordingState()) {
183         auto cpuImage = image_->MakeRasterImage();
184         if (!cpuImage) {
185             RS_LOGE("RSCanvasDrawingRenderNode::ProcessRenderContents: MakeRasterImage failed");
186             canvas.DetachPaint();
187             return;
188         }
189         canvas.DrawImage(*cpuImage, 0.f, 0.f, samplingOptions);
190     } else {
191         canvas.DrawImage(*image_, 0.f, 0.f, samplingOptions);
192     }
193     canvas.DetachPaint();
194 }
195 
IsNeedProcess() const196 bool RSCanvasDrawingRenderNode::IsNeedProcess() const
197 {
198     if (!renderDrawable_ || !(renderDrawable_->GetRenderParams())) {
199         return false;
200     }
201     return renderDrawable_->GetRenderParams()->IsNeedProcess();
202 }
203 
SetNeedProcess(bool needProcess)204 void RSCanvasDrawingRenderNode::SetNeedProcess(bool needProcess)
205 {
206     auto stagingCanvasDrawingParams = static_cast<RSCanvasDrawingRenderParams*>(stagingRenderParams_.get());
207     if (stagingCanvasDrawingParams) {
208         stagingCanvasDrawingParams->SetNeedProcess(needProcess);
209         if (stagingRenderParams_->NeedSync()) {
210             AddToPendingSyncList();
211         }
212     }
213     isNeedProcess_ = needProcess;
214 }
215 
PlaybackInCorrespondThread()216 void RSCanvasDrawingRenderNode::PlaybackInCorrespondThread()
217 {
218     auto nodeId = GetId();
219     auto ctx = GetContext().lock();
220     if (ctx == nullptr) {
221         return;
222     }
223     auto task = [nodeId, ctx, this]() {
224         std::lock_guard<std::mutex> lockTask(taskMutex_);
225         auto node = ctx->GetNodeMap().GetRenderNode<RSCanvasDrawingRenderNode>(nodeId);
226         if (!node || !surface_ || !canvas_) {
227             return;
228         }
229         RSModifierContext context = { GetMutableRenderProperties(), canvas_.get() };
230         ApplyDrawCmdModifier(context, RSModifierType::CONTENT_STYLE);
231         isNeedProcess_ = false;
232     };
233     RSTaskDispatcher::GetInstance().PostTask(threadId_, task, false);
234 }
235 
ResetSurface(int width,int height,RSPaintFilterCanvas & canvas)236 bool RSCanvasDrawingRenderNode::ResetSurface(int width, int height, RSPaintFilterCanvas& canvas)
237 {
238     Drawing::ImageInfo info =
239         Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
240 
241 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
242 #if (defined(ROSEN_IOS))
243     surface_ = Drawing::Surface::MakeRaster(info);
244 #else
245     auto gpuContext = canvas.GetGPUContext();
246     isGpuSurface_ = true;
247     if (gpuContext == nullptr) {
248         RS_LOGD("RSCanvasDrawingRenderNode::ResetSurface: gpuContext is nullptr");
249         isGpuSurface_ = false;
250         surface_ = Drawing::Surface::MakeRaster(info);
251     } else {
252         surface_ = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, info);
253         if (!surface_) {
254             isGpuSurface_ = false;
255             surface_ = Drawing::Surface::MakeRaster(info);
256             RS_LOGW("RSCanvasDrawingRenderNode::ResetSurface [%{public}d, %{public}d] %{public}" PRIu64 "",
257                 width, height, GetId());
258             if (!surface_) {
259                 RS_LOGE("RSCanvasDrawingRenderNode::ResetSurface surface is nullptr");
260                 return false;
261             }
262             recordingCanvas_ = std::make_shared<ExtendRecordingCanvas>(width, height, false);
263             canvas_ = std::make_unique<RSPaintFilterCanvas>(recordingCanvas_.get());
264             return true;
265         }
266     }
267 #endif
268 #else
269     surface_ = Drawing::Surface::MakeRaster(info);
270 #endif
271     if (!surface_) {
272         RS_LOGE("RSCanvasDrawingRenderNode::ResetSurface surface is nullptr");
273         return false;
274     }
275     canvas_ = std::make_unique<RSPaintFilterCanvas>(surface_.get());
276     return true;
277 }
278 
ApplyDrawCmdModifier(RSModifierContext & context,RSModifierType type)279 void RSCanvasDrawingRenderNode::ApplyDrawCmdModifier(RSModifierContext& context, RSModifierType type)
280 {
281     std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
282     auto it = drawCmdLists_.find(type);
283     if (it == drawCmdLists_.end() || it->second.empty()) {
284         return;
285     }
286     for (const auto& drawCmdList : it->second) {
287         drawCmdList->Playback(*context.canvas_);
288         drawCmdList->ClearOp();
289     }
290     context.canvas_->Flush();
291     it->second.clear();
292 }
293 
GetTid() const294 uint32_t RSCanvasDrawingRenderNode::GetTid() const
295 {
296     if (UNI_RENDER_THREAD_INDEX == drawingNodeRenderID) {
297         return drawingNodeRenderID;
298     }
299     return curThreadInfo_.first;
300 }
301 
GetBitmap()302 Drawing::Bitmap RSCanvasDrawingRenderNode::GetBitmap()
303 {
304     return GetBitmap(UNI_MAIN_THREAD_INDEX);
305 }
306 
WriteSkImageToPixelmap(std::shared_ptr<Drawing::Image> image,Drawing::ImageInfo info,std::shared_ptr<Media::PixelMap> pixelmap,const Drawing::Rect * rect)307 bool WriteSkImageToPixelmap(std::shared_ptr<Drawing::Image> image, Drawing::ImageInfo info,
308     std::shared_ptr<Media::PixelMap> pixelmap, const Drawing::Rect* rect)
309 {
310     return image->ReadPixels(
311         info, pixelmap->GetWritablePixels(), pixelmap->GetRowStride(), rect->GetLeft(), rect->GetTop());
312 }
313 
GetImage(const uint64_t tid)314 std::shared_ptr<Drawing::Image> RSCanvasDrawingRenderNode::GetImage(const uint64_t tid)
315 {
316     if (GetTid() != tid) {
317         RS_LOGE("RSCanvasDrawingRenderNode::GetImage: image_ used by multi threads");
318         return nullptr;
319     }
320     if (!image_) {
321         RS_LOGE("RSCanvasDrawingRenderNode::GetImage: image_ is nullptr");
322     }
323     return image_;
324 }
325 
GetBitmap(const uint64_t tid)326 Drawing::Bitmap RSCanvasDrawingRenderNode::GetBitmap(const uint64_t tid)
327 {
328     Drawing::Bitmap bitmap;
329     std::lock_guard<std::mutex> lock(drawingMutex_);
330     if (!image_) {
331         RS_LOGE("RSCanvasDrawingRenderNode::GetBitmap: image_ is nullptr");
332         return bitmap;
333     }
334     if (GetTid() != tid) {
335         RS_LOGE("RSCanvasDrawingRenderNode::GetBitmap: image_ used by multi threads");
336         return bitmap;
337     }
338     if (!image_->AsLegacyBitmap(bitmap)) {
339         RS_LOGE("RSCanvasDrawingRenderNode::GetBitmap: asLegacyBitmap failed");
340     }
341     return bitmap;
342 }
343 
GetPixelmap(std::shared_ptr<Media::PixelMap> pixelmap,const Drawing::Rect * rect,const uint64_t tid,std::shared_ptr<Drawing::DrawCmdList> drawCmdList)344 bool RSCanvasDrawingRenderNode::GetPixelmap(std::shared_ptr<Media::PixelMap> pixelmap, const Drawing::Rect* rect,
345     const uint64_t tid, std::shared_ptr<Drawing::DrawCmdList> drawCmdList)
346 {
347     std::lock_guard<std::mutex> lock(drawingMutex_);
348     if (!pixelmap || !rect) {
349         RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: pixelmap is nullptr");
350         return false;
351     }
352 
353     if (!surface_) {
354         RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: surface is nullptr");
355         return false;
356     }
357 
358     auto image = surface_->GetImageSnapshot();
359     if (image == nullptr) {
360         RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: GetImageSnapshot failed");
361         return false;
362     }
363 
364     if (GetTid() != tid) {
365         RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: surface used by multi threads");
366         return false;
367     }
368 
369     Drawing::ImageInfo info = Drawing::ImageInfo { pixelmap->GetWidth(), pixelmap->GetHeight(),
370         Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
371     if (!drawCmdList) {
372         if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
373             RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
374             return false;
375         }
376         return true;
377     }
378     std::shared_ptr<Drawing::Surface> surface;
379     std::unique_ptr<RSPaintFilterCanvas> canvas;
380 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
381     if (!canvas_) {
382         return false;
383     }
384     auto gpuContext = canvas_->GetGPUContext();
385     if (gpuContext == nullptr) {
386         if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
387             RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
388         }
389         return false;
390     } else {
391         Drawing::ImageInfo newInfo = Drawing::ImageInfo{ image->GetWidth(), image->GetHeight(),
392             Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
393         surface = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, newInfo);
394         if (!surface) {
395             if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
396                 RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
397             }
398             return false;
399         }
400         canvas = std::make_unique<RSPaintFilterCanvas>(surface.get());
401     }
402 #else
403     if (!WriteSkImageToPixelmap(image, info, pixelmap, rect)) {
404         RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
405     }
406     return false;
407 #endif
408     canvas->DrawImage(*image, 0, 0, Drawing::SamplingOptions());
409     drawCmdList->Playback(*canvas, rect);
410     auto pixelmapImage = surface->GetImageSnapshot();
411     if (!pixelmapImage) {
412         return false;
413     }
414     if (!WriteSkImageToPixelmap(pixelmapImage, info, pixelmap, rect)) {
415         RS_LOGE("RSCanvasDrawingRenderNode::GetPixelmap: readPixels failed");
416         return false;
417     }
418     return true;
419 }
420 
GetSizeFromDrawCmdModifiers(int & width,int & height)421 bool RSCanvasDrawingRenderNode::GetSizeFromDrawCmdModifiers(int& width, int& height)
422 {
423     auto it = GetDrawCmdModifiers().find(RSModifierType::CONTENT_STYLE);
424     if (it == GetDrawCmdModifiers().end() || it->second.empty()) {
425         return false;
426     }
427     for (const auto& modifier : it->second) {
428         auto prop = modifier->GetProperty();
429         if (auto cmd = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(prop)->Get()) {
430             width = std::max(width, cmd->GetWidth());
431             height = std::max(height, cmd->GetHeight());
432         }
433     }
434     if (width <= 0 || height <= 0) {
435         RS_LOGE("RSCanvasDrawingRenderNode::GetSizeFromDrawCmdModifiers: The width or height of the canvas is less "
436                 "than or equal to 0");
437         return false;
438     }
439     return true;
440 }
441 
IsNeedResetSurface() const442 bool RSCanvasDrawingRenderNode::IsNeedResetSurface() const
443 {
444     if (!surface_ || !surface_->GetCanvas()) {
445         return true;
446     }
447     return false;
448 }
449 
InitRenderParams()450 void RSCanvasDrawingRenderNode::InitRenderParams()
451 {
452     stagingRenderParams_ = std::make_unique<RSCanvasDrawingRenderParams>(GetId());
453     DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(shared_from_this());
454     if (renderDrawable_ == nullptr) {
455         RS_LOGE("RSCanvasDrawingRenderNode::InitRenderParams failed");
456         return;
457     }
458 }
459 
AddDirtyType(RSModifierType modifierType)460 void RSCanvasDrawingRenderNode::AddDirtyType(RSModifierType modifierType)
461 {
462     dirtyTypes_.set(static_cast<int>(modifierType), true);
463     std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
464     for (auto& [type, list]: GetDrawCmdModifiers()) {
465         if (modifierType != type || list.empty()) {
466             continue;
467         }
468         for (const auto& modifier : list) {
469             if (modifier == nullptr) {
470                 continue;
471             }
472             auto prop = modifier->GetProperty();
473             if (prop == nullptr) {
474                 continue;
475             }
476             auto cmd = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>(prop)->Get();
477             if (cmd == nullptr) {
478                 continue;
479             }
480 
481             if (cmd->GetOpItemSize() > DRAWCMDLIST_OPSIZE_COUNT_LIMIT) {
482                 RS_LOGE("CanvasDrawingNode AddDirtyType NodeId[%{public}" PRIu64 "] Cmd oversize"
483                     " Add DrawOpSize [%{public}zu]", GetId(), cmd->GetOpItemSize());
484                 continue;
485             }
486 
487             //only content_style allowed multi-drawcmdlist, others modifier same as canvas_node
488             if (type != RSModifierType::CONTENT_STYLE) {
489                 drawCmdLists_[type].clear();
490             }
491             drawCmdLists_[type].emplace_back(cmd);
492             SetNeedProcess(true);
493         }
494         bool overflow = drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT;
495         if (overflow && lastOverflowStatus_ != overflow) {
496             RS_LOGE("drawcmdlist overflow, This Node[%{public}" PRIu64 "] with Modifier[%{public}hd]"
497                     " have drawcmdlist:%{public}zu", GetId(), type, drawCmdLists_[type].size());
498         }
499         lastOverflowStatus_ = overflow;
500         // If such nodes are not drawn, The drawcmdlists don't clearOp during recording, As a result, there are
501         // too many drawOp, so we need to add the limit of drawcmdlists.
502         while ((GetOldDirtyInSurface().IsEmpty() || !IsDirty() || renderDrawable_) &&
503             drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT) {
504             drawCmdLists_[type].pop_front();
505         }
506         if (drawCmdLists_[type].size() > DRAWCMDLIST_COUNT_LIMIT) {
507             RS_LOGE("drawcmdlist Error, This Node[%{public}" PRIu64 "] with Modifier[%{public}hd]"
508                     " have drawcmdlist:%{public}zu", GetId(), type, drawCmdLists_[type].size());
509         }
510     }
511 }
512 
ClearOp()513 void RSCanvasDrawingRenderNode::ClearOp()
514 {
515     std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
516     drawCmdLists_.clear();
517 }
518 
ResetSurface(int width,int height)519 void RSCanvasDrawingRenderNode::ResetSurface(int width, int height)
520 {
521     std::lock_guard<std::mutex> lockTask(taskMutex_);
522     if (preThreadInfo_.second && surface_) {
523         preThreadInfo_.second(std::move(surface_));
524     }
525     surface_ = nullptr;
526     recordingCanvas_ = nullptr;
527     stagingRenderParams_->SetCanvasDrawingSurfaceChanged(true);
528     stagingRenderParams_->SetCanvasDrawingSurfaceParams(width, height);
529 }
530 
GetDrawCmdLists() const531 const std::map<RSModifierType, std::list<Drawing::DrawCmdListPtr>>& RSCanvasDrawingRenderNode::GetDrawCmdLists() const
532 {
533     return drawCmdLists_;
534 }
535 
ClearResource()536 void RSCanvasDrawingRenderNode::ClearResource()
537 {
538     if (renderDrawable_ && renderDrawable_->IsDrawCmdListsVisited()) {
539         std::lock_guard<std::mutex> lock(drawCmdListsMutex_);
540         drawCmdLists_.clear();
541         renderDrawable_->SetDrawCmdListsVisited(false);
542     }
543 }
544 
545 } // namespace Rosen
546 } // namespace OHOS