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