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