• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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_render_thread_visitor.h"
17 
18 #include <cmath>
19 #ifndef USE_ROSEN_DRAWING
20 #include <include/core/SkColor.h>
21 #include <include/core/SkFont.h>
22 #include <include/core/SkMatrix.h>
23 #include <include/core/SkPaint.h>
24 #include <include/core/SkRect.h>
25 #else
26 #include "draw/color.h"
27 #include "drawing/engine_adapter/impl_interface/matrix_impl.h"
28 #endif
29 
30 #include "rs_trace.h"
31 
32 #include "command/rs_base_node_command.h"
33 #include "common/rs_obj_abs_geometry.h"
34 #include "common/rs_vector4.h"
35 #include "pipeline/rs_canvas_render_node.h"
36 #include "pipeline/rs_dirty_region_manager.h"
37 #include "pipeline/rs_effect_render_node.h"
38 #include "pipeline/rs_node_map.h"
39 #include "pipeline/rs_proxy_render_node.h"
40 #include "pipeline/rs_render_thread.h"
41 #include "pipeline/rs_root_render_node.h"
42 #include "pipeline/rs_surface_render_node.h"
43 #include "platform/common/rs_log.h"
44 #ifdef NEW_RENDER_CONTEXT
45 #include "rs_render_surface.h"
46 #else
47 #include "platform/drawing/rs_surface.h"
48 #endif
49 #include "transaction/rs_transaction_proxy.h"
50 #include "ui/rs_surface_extractor.h"
51 #include "ui/rs_surface_node.h"
52 
53 #ifdef ROSEN_OHOS
54 #include <frame_collector.h>
55 #include <frame_painter.h>
56 #include "platform/ohos/overdraw/rs_cpu_overdraw_canvas_listener.h"
57 #include "platform/ohos/overdraw/rs_gpu_overdraw_canvas_listener.h"
58 #include "platform/ohos/overdraw/rs_overdraw_controller.h"
59 #endif
60 
61 namespace OHOS {
62 namespace Rosen {
RSRenderThreadVisitor()63 RSRenderThreadVisitor::RSRenderThreadVisitor()
64     : curDirtyManager_(std::make_shared<RSDirtyRegionManager>()), canvas_(nullptr) {}
65 
66 RSRenderThreadVisitor::~RSRenderThreadVisitor() = default;
67 
IsValidRootRenderNode(RSRootRenderNode & node)68 bool RSRenderThreadVisitor::IsValidRootRenderNode(RSRootRenderNode& node)
69 {
70     auto ptr = RSNodeMap::Instance().GetNode<RSSurfaceNode>(node.GetRSSurfaceNodeId());
71     if (ptr == nullptr) {
72         ROSEN_LOGE("No valid RSSurfaceNode id");
73         return false;
74     }
75     if (!node.enableRender_) {
76         ROSEN_LOGD("RootNode %s: Invisible", ptr->GetName().c_str());
77         return false;
78     }
79     if (node.GetSuggestedBufferWidth() <= 0 || node.GetSuggestedBufferHeight() <= 0) {
80         ROSEN_LOGD("Root %s: Negative width or height [%f %f]", ptr->GetName().c_str(),
81             node.GetSuggestedBufferWidth(), node.GetSuggestedBufferHeight());
82         return false;
83     }
84     return true;
85 }
86 
SetPartialRenderStatus(PartialRenderType status,bool isRenderForced)87 void RSRenderThreadVisitor::SetPartialRenderStatus(PartialRenderType status, bool isRenderForced)
88 {
89     RS_TRACE_FUNC();
90     isRenderForced_ = isRenderForced;
91     dfxDirtyType_ = RSSystemProperties::GetDirtyRegionDebugType();
92     isEglSetDamageRegion_ = !isRenderForced_ && (status != PartialRenderType::DISABLED);
93     isOpDropped_ = (dfxDirtyType_ == DirtyRegionDebugType::DISABLED) && !isRenderForced_ &&
94         (status == PartialRenderType::SET_DAMAGE_AND_DROP_OP);
95     if (partialRenderStatus_ != status) {
96         ROSEN_LOGD("PartialRenderStatus: %d->%d, isRenderForced_=%d, dfxDirtyType_=%d,\
97             isEglSetDamageRegion_=%d, isOpDropped_=%d", partialRenderStatus_, status,
98             isRenderForced_, dfxDirtyType_, isEglSetDamageRegion_, isOpDropped_);
99     }
100     partialRenderStatus_ = status;
101 }
102 
PrepareChildren(RSRenderNode & node)103 void RSRenderThreadVisitor::PrepareChildren(RSRenderNode& node)
104 {
105     node.ApplyChildrenModifiers();
106     for (auto& child : node.GetSortedChildren()) {
107         child->Prepare(shared_from_this());
108     }
109 }
110 
PrepareRootRenderNode(RSRootRenderNode & node)111 void RSRenderThreadVisitor::PrepareRootRenderNode(RSRootRenderNode& node)
112 {
113     if (isIdle_) {
114         curDirtyManager_ = node.GetDirtyManager();
115         curDirtyManager_->Clear();
116         curDirtyManager_->UpdateDebugRegionTypeEnable(dfxDirtyType_);
117         // After the node calls ApplyModifiers, the modifiers assign the renderProperties to the node
118         // Otherwise node.GetSuggestedBufferHeight always less than 0, causing black screen
119         if (!IsValidRootRenderNode(node)) {
120             return;
121         }
122         dirtyFlag_ = false;
123         isIdle_ = false;
124         PrepareCanvasRenderNode(node);
125         isIdle_ = true;
126     } else {
127         PrepareCanvasRenderNode(node);
128     }
129 }
130 
ResetAndPrepareChildrenNode(RSRenderNode & node,std::shared_ptr<RSBaseRenderNode> nodeParent)131 void RSRenderThreadVisitor::ResetAndPrepareChildrenNode(RSRenderNode& node,
132     std::shared_ptr<RSBaseRenderNode> nodeParent)
133 {
134     // merge last childRect as dirty if any child has been removed
135     if (curDirtyManager_ && node.HasRemovedChild()) {
136         curDirtyManager_->MergeDirtyRect(node.GetChildrenRect());
137         node.ResetHasRemovedChild();
138     }
139     // reset childRect before prepare children
140     node.ResetChildrenRect();
141     node.UpdateChildrenOutOfRectFlag(false);
142     PrepareChildren(node);
143     // accumulate direct parent's childrenRect
144     node.UpdateParentChildrenRect(nodeParent);
145 }
146 
PrepareCanvasRenderNode(RSCanvasRenderNode & node)147 void RSRenderThreadVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode& node)
148 {
149     if (!node.ShouldPaint() || curDirtyManager_ == nullptr) {
150         return;
151     }
152     bool dirtyFlag = dirtyFlag_;
153     auto nodeParent = node.GetParent().lock();
154     dirtyFlag_ = node.Update(*curDirtyManager_, nodeParent, dirtyFlag_);
155     if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
156         curDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::CANVAS_NODE,
157             DirtyRegionType::UPDATE_DIRTY_REGION, node.GetOldDirty());
158     }
159     ResetAndPrepareChildrenNode(node, nodeParent);
160     node.UpdateEffectRegion(effectRegion_);
161     dirtyFlag_ = dirtyFlag;
162 }
163 
PrepareSurfaceRenderNode(RSSurfaceRenderNode & node)164 void RSRenderThreadVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node)
165 {
166     if (curDirtyManager_ == nullptr) {
167         return;
168     }
169     bool dirtyFlag = dirtyFlag_;
170     auto nodeParent = node.GetParent().lock();
171     // If rt buffer switches to be available
172     // set its SurfaceRenderNode's render dirty
173     if (!node.IsNotifyRTBufferAvailablePre() && node.IsNotifyRTBufferAvailable()) {
174         ROSEN_LOGD("NotifyRTBufferAvailable and set it dirty");
175         node.SetDirty();
176     }
177     dirtyFlag_ = node.Update(*curDirtyManager_, nodeParent, dirtyFlag_);
178     if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
179         curDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::SURFACE_NODE,
180             DirtyRegionType::UPDATE_DIRTY_REGION, node.GetOldDirty());
181     }
182     ResetAndPrepareChildrenNode(node, nodeParent);
183     dirtyFlag_ = dirtyFlag;
184 }
185 
PrepareEffectRenderNode(RSEffectRenderNode & node)186 void RSRenderThreadVisitor::PrepareEffectRenderNode(RSEffectRenderNode& node)
187 {
188     if (!node.ShouldPaint() || curDirtyManager_ == nullptr) {
189         return;
190     }
191     auto effectRegion = effectRegion_;
192 
193 #ifndef USE_ROSEN_DRAWING
194     effectRegion_ = SkPath();
195 #else
196     effectRegion_ = Drawing::Path();
197 #endif
198     bool dirtyFlag = dirtyFlag_;
199     auto nodeParent = node.GetParent().lock();
200     dirtyFlag_ = node.Update(*curDirtyManager_, nodeParent, dirtyFlag_);
201     ResetAndPrepareChildrenNode(node, nodeParent);
202     node.SetEffectRegion(effectRegion_);
203 
204     effectRegion_ = effectRegion;
205     dirtyFlag_ = dirtyFlag;
206 }
207 
208 #ifndef USE_ROSEN_DRAWING
DrawRectOnCanvas(const RectI & dirtyRect,const SkColor color,const SkPaint::Style fillType,float alpha,int strokeWidth)209 void RSRenderThreadVisitor::DrawRectOnCanvas(const RectI& dirtyRect, const SkColor color,
210     const SkPaint::Style fillType, float alpha, int strokeWidth)
211 #else
212 void RSRenderThreadVisitor::DrawRectOnCanvas(const RectI& dirtyRect, const Drawing::ColorQuad color,
213     RSPaintStyle fillType, float alpha, int strokeWidth)
214 #endif // USE_ROSEN_DRAWING
215 {
216     if (dirtyRect.IsEmpty()) {
217         ROSEN_LOGD("DrawRectOnCanvas dirty rect is invalid.");
218         return;
219     }
220 #ifndef USE_ROSEN_DRAWING
221     auto skRect = SkRect::MakeXYWH(dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
222     SkPaint rectPaint;
223     rectPaint.setColor(color);
224     rectPaint.setAntiAlias(true);
225     rectPaint.setAlphaf(alpha);
226     rectPaint.setStyle(fillType);
227     rectPaint.setStrokeWidth(strokeWidth);
228     if (fillType == SkPaint::kFill_Style) {
229         rectPaint.setStrokeJoin(SkPaint::kRound_Join);
230     }
231     canvas_->drawRect(skRect, rectPaint);
232 #else
233     auto drawingRect = Drawing::Rect(dirtyRect.left_, dirtyRect.top_,
234         dirtyRect.width_ + dirtyRect.left_, dirtyRect.height_ + dirtyRect.top_);
235     Drawing::Pen pen;
236     Drawing::Brush brush;
237     if (fillType == RSPaintStyle::STROKE) {
238         pen.SetColor(color);
239         pen.SetAntiAlias(true);
240         pen.SetAlphaF(alpha);
241         pen.SetWidth(strokeWidth);
242         pen.SetJoinStyle(Drawing::Pen::JoinStyle::ROUND_JOIN);
243         canvas_->AttachPen(pen);
244     } else if (fillType == RSPaintStyle::FILL) {
245         brush.SetColor(color);
246         brush.SetAntiAlias(true);
247         brush.SetAlphaF(alpha);
248         canvas_->AttachBrush(brush);
249     }
250     canvas_->DrawRect(drawingRect);
251     canvas_->DetachPen();
252     canvas_->DetachBrush();
253 #endif // USE_ROSEN_DRAWING
254 }
255 
DrawDirtyRegion()256 void RSRenderThreadVisitor::DrawDirtyRegion()
257 {
258     auto dirtyRect = RectI();
259     const float fillAlpha = 0.2;
260     const float edgeAlpha = 0.4;
261 
262     if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::MULTI_HISTORY)) {
263         dirtyRect = curDirtyManager_->GetDirtyRegion();
264         if (dirtyRect.IsEmpty()) {
265             ROSEN_LOGD("DrawDirtyRegion his dirty rect is invalid. dirtyRect = %s", dirtyRect.ToString().c_str());
266         } else {
267             ROSEN_LOGD("DrawDirtyRegion his dirty rect. dirtyRect = %s", dirtyRect.ToString().c_str());
268             // green
269 #ifndef USE_ROSEN_DRAWING
270             DrawRectOnCanvas(dirtyRect, 0x442FDD2F, SkPaint::kFill_Style, fillAlpha);
271             DrawRectOnCanvas(dirtyRect, 0xFF2FDD2F, SkPaint::kStroke_Style, edgeAlpha);
272 #else
273             DrawRectOnCanvas(dirtyRect, 0x442FDD2F, RSPaintStyle::FILL, fillAlpha);
274             DrawRectOnCanvas(dirtyRect, 0xFF2FDD2F, RSPaintStyle::STROKE, edgeAlpha);
275 #endif // USE_ROSEN_DRAWING
276         }
277     }
278 
279     if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_WHOLE)) {
280         dirtyRect = curDirtyManager_->GetLatestDirtyRegion();
281         if (dirtyRect.IsEmpty()) {
282             ROSEN_LOGD("DrawDirtyRegion current frame's dirty rect is invalid. dirtyRect = %s",
283                 dirtyRect.ToString().c_str());
284         } else {
285             ROSEN_LOGD("DrawDirtyRegion cur dirty rect. dirtyRect = %s", dirtyRect.ToString().c_str());
286             // yellow
287 #ifndef USE_ROSEN_DRAWING
288             DrawRectOnCanvas(dirtyRect, 0x88FFFF00, SkPaint::kFill_Style, fillAlpha);
289             DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, SkPaint::kStroke_Style, edgeAlpha);
290 #else
291             DrawRectOnCanvas(dirtyRect, 0x88FFFF00, RSPaintStyle::FILL, fillAlpha);
292             DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, RSPaintStyle::STROKE, edgeAlpha);
293 #endif // USE_ROSEN_DRAWING
294         }
295     }
296 
297     if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
298         const int strokeWidth = 4;
299         std::map<NodeId, RectI> dirtyRegionRects_;
300         curDirtyManager_->GetDirtyRegionInfo(dirtyRegionRects_, RSRenderNodeType::CANVAS_NODE,
301             DirtyRegionType::UPDATE_DIRTY_REGION);
302         ROSEN_LOGD("DrawDirtyRegion canvas dirtyRegionRects_ size %zu", dirtyRegionRects_.size());
303         // Draw Canvas Node
304         for (const auto& [nid, subRect] : dirtyRegionRects_) {
305             ROSEN_LOGD("DrawDirtyRegion canvas node id %" PRIu64 " is dirty. dirtyRect = %s",
306                 nid, subRect.ToString().c_str());
307 #ifndef USE_ROSEN_DRAWING
308             DrawRectOnCanvas(subRect, 0x88FF0000, SkPaint::kStroke_Style, edgeAlpha, strokeWidth);
309 #else
310             DrawRectOnCanvas(subRect, 0x88FF0000, RSPaintStyle::STROKE, edgeAlpha, strokeWidth);
311 #endif // USE_ROSEN_DRAWING
312         }
313 
314         curDirtyManager_->GetDirtyRegionInfo(dirtyRegionRects_, RSRenderNodeType::SURFACE_NODE,
315             DirtyRegionType::UPDATE_DIRTY_REGION);
316         ROSEN_LOGD("DrawDirtyRegion surface dirtyRegionRects_ size %zu", dirtyRegionRects_.size());
317         // Draw Surface Node
318         for (const auto& [nid, subRect] : dirtyRegionRects_) {
319             ROSEN_LOGD("DrawDirtyRegion surface node id %" PRIu64 " is dirty. dirtyRect = %s",
320                 nid, subRect.ToString().c_str());
321 #ifndef USE_ROSEN_DRAWING
322             DrawRectOnCanvas(subRect, 0xFFD864D8, SkPaint::kStroke_Style, edgeAlpha, strokeWidth);
323 #else
324             DrawRectOnCanvas(subRect, 0xFFD864D8, RSPaintStyle::STROKE, edgeAlpha, strokeWidth);
325 #endif // USE_ROSEN_DRAWING
326         }
327     }
328 }
329 
330 #ifdef NEW_RENDER_CONTEXT
UpdateDirtyAndSetEGLDamageRegion(std::shared_ptr<RSRenderSurface> & surface)331 void RSRenderThreadVisitor::UpdateDirtyAndSetEGLDamageRegion(std::shared_ptr<RSRenderSurface>& surface)
332 #else
333 void RSRenderThreadVisitor::UpdateDirtyAndSetEGLDamageRegion(std::unique_ptr<RSSurfaceFrame>& surfaceFrame)
334 #endif
335 {
336     RS_TRACE_BEGIN("UpdateDirtyAndSetEGLDamageRegion");
337 #ifdef RS_ENABLE_EGLQUERYSURFACE
338     if (isEglSetDamageRegion_) {
339         // get and update valid buffer age(>0) to merge history
340 #if defined(NEW_RENDER_CONTEXT)
341         if (surface == nullptr) {
342             ROSEN_LOGE("Failed to UpdateDirtyAndSetEGLDamageRegion, surface is nullptr");
343             return;
344         }
345         int32_t bufferAge = surface->GetBufferAge();
346 #else
347         int32_t bufferAge = surfaceFrame->GetBufferAge();
348 #endif
349         if (!curDirtyManager_->SetBufferAge(bufferAge)) {
350             ROSEN_LOGD("ProcessRootRenderNode SetBufferAge with invalid buffer age %d", bufferAge);
351             curDirtyManager_->ResetDirtyAsSurfaceSize();
352         }
353         curDirtyManager_->UpdateDirtyByAligned();
354         curDirtyManager_->UpdateDirty();
355         curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
356         // only set damage region if dirty region and buffer age is valid(>0)
357         if (bufferAge >= 0) {
358             // get dirty rect coordinated from upper left to lower left corner in current surface
359             RectI dirtyRectFlip = curDirtyManager_->GetRectFlipWithinSurface(curDirtyRegion_);
360             // set dirty rect as eglSurfaceFrame's damage region
361 #if defined(NEW_RENDER_CONTEXT)
362             std::vector<RectI> dirtyRects;
363             dirtyRects.push_back(dirtyRectFlip);
364             surface->SetDamageRegion(dirtyRects);
365 #else
366             surfaceFrame->SetDamageRegion(dirtyRectFlip.left_, dirtyRectFlip.top_, dirtyRectFlip.width_,
367                 dirtyRectFlip.height_);
368 #endif
369             // flip aligned rect for op drops
370             curDirtyRegion_ = curDirtyManager_->GetRectFlipWithinSurface(dirtyRectFlip);
371             ROSEN_LOGD("GetPartialRenderEnabled buffer age %d, dirtyRectFlip = [%d, %d, %d, %d], "
372                 "dirtyRectAlign = [%d, %d, %d, %d]", bufferAge,
373                 dirtyRectFlip.left_, dirtyRectFlip.top_, dirtyRectFlip.width_, dirtyRectFlip.height_,
374                 curDirtyRegion_.left_, curDirtyRegion_.top_, curDirtyRegion_.width_, curDirtyRegion_.height_);
375         }
376     } else {
377         curDirtyManager_->UpdateDirty();
378         curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
379     }
380 #else
381     curDirtyManager_->UpdateDirty();
382     curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
383 #endif
384     ROSEN_LOGD("UpdateDirtyAndSetEGLDamageRegion dirtyRect = [%d, %d, %d, %d]",
385         curDirtyRegion_.left_, curDirtyRegion_.top_, curDirtyRegion_.width_, curDirtyRegion_.height_);
386     RS_TRACE_END();
387 }
388 
ProcessChildren(RSRenderNode & node)389 void RSRenderThreadVisitor::ProcessChildren(RSRenderNode& node)
390 {
391     for (auto& child : node.GetSortedChildren()) {
392         child->Process(shared_from_this());
393     }
394 }
395 
ProcessRootRenderNode(RSRootRenderNode & node)396 void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
397 {
398     if (!isIdle_) {
399         ProcessCanvasRenderNode(node);
400         return;
401     }
402     auto ptr = RSNodeMap::Instance().GetNode<RSSurfaceNode>(node.GetRSSurfaceNodeId());
403     if (!IsValidRootRenderNode(node)) {
404         return;
405     }
406 
407     curDirtyManager_ = node.GetDirtyManager();
408 
409 #ifndef ROSEN_CROSS_PLATFORM
410     auto surfaceNodeColorSpace = ptr->GetColorSpace();
411 #endif
412 #ifdef NEW_RENDER_CONTEXT
413     std::shared_ptr<RSRenderSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(ptr);
414 #else
415     std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(ptr);
416 #endif
417     if (rsSurface == nullptr) {
418         ROSEN_LOGE("ProcessRoot %s: No RSSurface found", ptr->GetName().c_str());
419         return;
420     }
421     // Update queue size for each process loop in case it dynamically changes
422     queueSize_ = rsSurface->GetQueueSize();
423 
424 #ifndef ROSEN_CROSS_PLATFORM
425     auto rsSurfaceColorSpace = rsSurface->GetColorSpace();
426     if (surfaceNodeColorSpace != rsSurfaceColorSpace) {
427         ROSEN_LOGD("Set new colorspace %d to rsSurface", surfaceNodeColorSpace);
428         rsSurface->SetColorSpace(surfaceNodeColorSpace);
429     }
430 #endif
431 
432 #if defined(ACE_ENABLE_GL)
433 #if defined(NEW_RENDER_CONTEXT)
434     std::shared_ptr<RenderContextBase> rc = RSRenderThread::Instance().GetRenderContext();
435     std::shared_ptr<DrawingContext> dc = RSRenderThread::Instance().GetDrawingContext();
436     rsSurface->SetDrawingContext(dc);
437 #else
438     RenderContext* rc = RSRenderThread::Instance().GetRenderContext();
439 #endif
440     rsSurface->SetRenderContext(rc);
441 #endif
442     uiTimestamp_ = RSRenderThread::Instance().GetUITimestamp();
443     RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->RequestFrame");
444 #ifdef ROSEN_OHOS
445     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseStart);
446 #endif
447 
448     const auto& property = node.GetRenderProperties();
449     const float bufferWidth = node.GetSuggestedBufferWidth() * property.GetScaleX();
450     const float bufferHeight = node.GetSuggestedBufferHeight() * property.GetScaleY();
451 #ifdef ROSEN_OHOS
452     auto surfaceFrame = rsSurface->RequestFrame(bufferWidth, bufferHeight, uiTimestamp_);
453 #else
454     auto surfaceFrame = rsSurface->RequestFrame(std::round(bufferWidth), std::round(bufferHeight), uiTimestamp_);
455 #endif
456     RS_TRACE_END();
457     if (surfaceFrame == nullptr) {
458         ROSEN_LOGI("ProcessRoot %s: Request Frame Failed", ptr->GetName().c_str());
459 #ifdef ROSEN_OHOS
460         FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
461 #endif
462         return;
463     }
464 #ifndef USE_ROSEN_DRAWING
465 #ifdef NEW_RENDER_CONTEXT
466     auto skSurface = rsSurface->GetSurface();
467 #else
468     auto skSurface = surfaceFrame->GetSurface();
469 #endif
470     if (skSurface == nullptr) {
471         ROSEN_LOGE("skSurface null.");
472         return;
473     }
474     if (skSurface->getCanvas() == nullptr) {
475         ROSEN_LOGE("skSurface.getCanvas is null.");
476         return;
477     }
478 #else
479     auto surface = surfaceFrame->GetSurface();
480     if (surface == nullptr) {
481         ROSEN_LOGE("surface null.");
482         return;
483     }
484     if (surface->GetCanvas() == nullptr) {
485         ROSEN_LOGE("surface.GetCanvas is null.");
486         return;
487     }
488 #endif
489 
490 #ifdef ROSEN_OHOS
491     // if listenedCanvas is nullptr, that means disabled or listen failed
492     std::shared_ptr<RSListenedCanvas> listenedCanvas = nullptr;
493     std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
494 
495     if (RSOverdrawController::GetInstance().IsEnabled()) {
496         auto &oc = RSOverdrawController::GetInstance();
497 #ifndef USE_ROSEN_DRAWING
498         listenedCanvas = std::make_shared<RSListenedCanvas>(skSurface.get());
499 #else
500         listenedCanvas = std::make_shared<RSListenedCanvas>(*surface);
501 #endif
502         overdrawListener = oc.CreateListener<RSCPUOverdrawCanvasListener>(listenedCanvas.get());
503         if (overdrawListener == nullptr) {
504             overdrawListener = oc.CreateListener<RSGPUOverdrawCanvasListener>(listenedCanvas.get());
505         }
506 
507         if (overdrawListener != nullptr) {
508             listenedCanvas->SetListener(overdrawListener);
509         } else {
510             // create listener failed
511             listenedCanvas = nullptr;
512         }
513     }
514 
515     if (listenedCanvas != nullptr) {
516         canvas_ = listenedCanvas;
517     } else {
518 #ifndef USE_ROSEN_DRAWING
519         canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
520 #else
521         canvas_ = std::make_shared<RSPaintFilterCanvas>(surface.get());
522 #endif // USE_ROSEN_DRAWING
523     }
524 #else
525 #ifndef USE_ROSEN_DRAWING
526     canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
527 #else
528     canvas_ = std::make_shared<RSPaintFilterCanvas>(surface.get());
529 #endif // USE_ROSEN_DRAWING
530 #endif
531 
532     canvas_->SetHighContrast(RSRenderThread::Instance().isHighContrastEnabled());
533 
534     // node's surface size already check, so here we do not need to check return
535     // attention: currently surfaceW/H are float values transformed into int implicitly
536     (void)curDirtyManager_->SetSurfaceSize(bufferWidth, bufferHeight);
537     // keep non-negative rect region within surface
538     curDirtyManager_->ClipDirtyRectWithinSurface();
539     // reset matrix
540     const float rootWidth = property.GetFrameWidth() * property.GetScaleX();
541     const float rootHeight = property.GetFrameHeight() * property.GetScaleY();
542 #ifndef USE_ROSEN_DRAWING
543     SkMatrix gravityMatrix;
544 #else
545     Drawing::Matrix gravityMatrix;
546 #endif // USE_ROSEN_DRAWING
547     (void)RSPropertiesPainter::GetGravityMatrix(
548         Gravity::RESIZE, RectF { 0.0f, 0.0f, bufferWidth, bufferHeight }, rootWidth, rootHeight, gravityMatrix);
549 
550     if (isRenderForced_ ||
551         curDirtyManager_->GetCurrentFrameDirtyRegion().GetWidth() == 0 ||
552         curDirtyManager_->GetCurrentFrameDirtyRegion().GetHeight() == 0 ||
553 #ifndef USE_ROSEN_DRAWING
554         !gravityMatrix.isIdentity()) {
555 #else
556         !(gravityMatrix == Drawing::Matrix())) {
557 #endif // USE_ROSEN_DRAWING
558         curDirtyManager_->ResetDirtyAsSurfaceSize();
559     }
560 #ifdef NEW_RENDER_CONTEXT
561     UpdateDirtyAndSetEGLDamageRegion(rsSurface);
562 #else
563     UpdateDirtyAndSetEGLDamageRegion(surfaceFrame);
564 #endif
565 
566 #ifndef USE_ROSEN_DRAWING
567     canvas_->clipRect(SkRect::MakeWH(bufferWidth, bufferHeight));
568     canvas_->clear(SK_ColorTRANSPARENT);
569 #else
570     canvas_->ClipRect(Drawing::Rect(0, 0, bufferWidth, bufferHeight), Drawing::ClipOp::INTERSECT, false);
571     canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
572 #endif // USE_ROSEN_DRAWING
573     isIdle_ = false;
574 
575     // clear current children before traversal, we will re-add them again during traversal
576     childSurfaceNodeIds_.clear();
577 
578 #ifndef USE_ROSEN_DRAWING
579     canvas_->concat(gravityMatrix);
580 #else
581     canvas_->ConcatMatrix(gravityMatrix);
582 #endif // USE_ROSEN_DRAWING
583     parentSurfaceNodeMatrix_ = gravityMatrix;
584 
585     RS_TRACE_BEGIN("ProcessRenderNodes");
586     ProcessCanvasRenderNode(node);
587 
588     if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_) {
589         auto thisSurfaceNodeId = node.GetRSSurfaceNodeId();
590         std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearChild>(thisSurfaceNodeId);
591         SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
592         for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
593             command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
594             SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
595         }
596         node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
597     }
598     RS_TRACE_END();
599 
600     auto transactionProxy = RSTransactionProxy::GetInstance();
601     if (transactionProxy != nullptr) {
602         ROSEN_LOGD("RSRenderThreadVisitor FlushImplicitTransactionFromRT uiTimestamp = %" PRIu64, uiTimestamp_);
603         transactionProxy->FlushImplicitTransactionFromRT(uiTimestamp_);
604     }
605 
606     if ((dfxDirtyType_ != DirtyRegionDebugType::DISABLED) && curDirtyManager_->IsDirty()) {
607         ROSEN_LOGD("ProcessRootRenderNode %s [%" PRIu64 "] draw dirtyRect", ptr->GetName().c_str(), node.GetId());
608         DrawDirtyRegion();
609     }
610 
611 #ifdef ROSEN_OHOS
612     if (overdrawListener != nullptr) {
613         overdrawListener->Draw();
614     }
615 
616     FramePainter fpainter(FrameCollector::GetInstance());
617     fpainter.Draw(*canvas_);
618     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
619     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushStart);
620 #endif
621 
622     RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->FlushFrame");
623     ROSEN_LOGD("RSRenderThreadVisitor FlushFrame surfaceNodeId = %" PRIu64 ", uiTimestamp = %" PRIu64,
624         node.GetRSSurfaceNodeId(), uiTimestamp_);
625 #ifdef NEW_RENDER_CONTEXT
626     rsSurface->FlushFrame(uiTimestamp_);
627 #else
628     rsSurface->FlushFrame(surfaceFrame, uiTimestamp_);
629 #endif
630 #ifdef ROSEN_OHOS
631     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushEnd);
632 #endif
633     RS_TRACE_END();
634 
635     canvas_ = nullptr;
636     isIdle_ = true;
637 }
638 
639 void RSRenderThreadVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node)
640 {
641     if (!node.ShouldPaint()) {
642         return;
643     }
644     if (!canvas_) {
645         ROSEN_LOGE("RSRenderThreadVisitor::ProcessCanvasRenderNode, canvas is nullptr");
646         return;
647     }
648 #ifdef RS_ENABLE_EGLQUERYSURFACE
649     node.UpdateRenderStatus(curDirtyRegion_, isOpDropped_);
650     if (node.IsRenderUpdateIgnored()) {
651         return;
652     }
653 #endif
654     const auto& property = node.GetRenderProperties();
655     if (property.IsSpherizeValid()) {
656         if (node.GetCacheType() != CacheType::ANIMATE_PROPERTY) {
657             node.SetCacheType(CacheType::ANIMATE_PROPERTY);
658             node.ClearCacheSurface();
659         }
660         if (!node.GetCompletedCacheSurface() && UpdateAnimatePropertyCacheSurface(node)) {
661             node.UpdateCompletedCacheSurface();
662         }
663         node.ProcessTransitionBeforeChildren(*canvas_);
664         RSPropertiesPainter::DrawSpherize(
665             property, *canvas_, node.GetCompletedCacheSurface());
666         node.ProcessTransitionAfterChildren(*canvas_);
667         return;
668     }
669 
670     if (node.GetCompletedCacheSurface()) {
671         node.SetCacheType(CacheType::NONE);
672         node.ClearCacheSurface();
673     }
674     node.ProcessRenderBeforeChildren(*canvas_);
675     node.ProcessRenderContents(*canvas_);
676     ProcessChildren(node);
677     node.ProcessRenderAfterChildren(*canvas_);
678 }
679 
680 bool RSRenderThreadVisitor::UpdateAnimatePropertyCacheSurface(RSRenderNode& node)
681 {
682     if (!node.GetCacheSurface()) {
683 #ifndef USE_ROSEN_DRAWING
684 #ifdef NEW_SKIA
685         node.InitCacheSurface(canvas_ ? canvas_->recordingContext() : nullptr);
686 #else
687         node.InitCacheSurface(canvas_ ? canvas_->getGrContext() : nullptr);
688 #endif
689 #else
690         node.InitCacheSurface(canvas_ ? canvas_->GetGPUContext().get() : nullptr);
691 #endif
692     }
693     if (!node.GetCacheSurface()) {
694         return false;
695     }
696     auto cacheCanvas = std::make_shared<RSPaintFilterCanvas>(node.GetCacheSurface().get());
697     if (!cacheCanvas) {
698         return false;
699     }
700 
701     // copy current canvas properties into cacheCanvas
702     cacheCanvas->CopyConfiguration(*canvas_);
703 
704     // When drawing CacheSurface, all child node should be drawn.
705     // So set isOpDropped_ = false here.
706     bool isOpDropped = isOpDropped_;
707     isOpDropped_ = false;
708 
709     swap(cacheCanvas, canvas_);
710     node.ProcessAnimatePropertyBeforeChildren(*canvas_);
711     node.ProcessRenderContents(*canvas_);
712     ProcessChildren(node);
713     node.ProcessAnimatePropertyAfterChildren(*canvas_);
714     swap(cacheCanvas, canvas_);
715 
716     isOpDropped_ = isOpDropped;
717     return true;
718 }
719 
720 void RSRenderThreadVisitor::ProcessEffectRenderNode(RSEffectRenderNode& node)
721 {
722     if (!node.ShouldPaint()) {
723         RS_LOGD("RSRenderThreadVisitor::ProcessEffectRenderNode, no need process");
724         return;
725     }
726     if (!canvas_) {
727         RS_LOGE("RSRenderThreadVisitor::ProcessEffectRenderNode, canvas is nullptr");
728         return;
729     }
730     node.ProcessRenderBeforeChildren(*canvas_);
731     ProcessChildren(node);
732     node.ProcessRenderAfterChildren(*canvas_);
733 }
734 
735 void RSRenderThreadVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
736 {
737     if (!canvas_) {
738         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
739         return;
740     }
741     if (!node.ShouldPaint()) {
742         ROSEN_LOGI("RSRenderThreadVisitor::ProcessSurfaceRenderNode node : %" PRIu64 " is invisible", node.GetId());
743         node.SetContextAlpha(0.0f);
744         return;
745     }
746     // RSSurfaceRenderNode in RSRenderThreadVisitor do not have information of property.
747     // We only get parent's matrix and send it to RenderService
748 #ifndef USE_ROSEN_DRAWING
749     SkMatrix invertMatrix;
750     SkMatrix contextMatrix = canvas_->getTotalMatrix();
751 
752     if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
753         contextMatrix.preConcat(invertMatrix);
754 #else
755     Drawing::Matrix invertMatrix;
756     Drawing::Matrix contextMatrix = canvas_->GetTotalMatrix();
757 
758     if (parentSurfaceNodeMatrix_.Invert(invertMatrix)) {
759         contextMatrix.PreConcat(invertMatrix);
760 #endif // USE_ROSEN_DRAWING
761     } else {
762         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, invertMatrix failed");
763     }
764     node.SetContextMatrix(contextMatrix);
765     node.SetContextAlpha(canvas_->GetAlpha());
766 
767     // PLANNING: This is a temporary modification. Animation for surfaceView should not be triggered in RenderService.
768     // We plan to refactor code here.
769     node.SetContextBounds(node.GetRenderProperties().GetBounds());
770 
771     auto clipRect = RSPaintFilterCanvas::GetLocalClipBounds(*canvas_);
772 #ifndef USE_ROSEN_DRAWING
773     if (!clipRect.has_value() ||
774         clipRect->width() < std::numeric_limits<float>::epsilon() ||
775         clipRect->height() < std::numeric_limits<float>::epsilon()) {
776 #else
777     if (!clipRect.has_value() ||
778         clipRect->GetWidth() < std::numeric_limits<float>::epsilon() ||
779         clipRect->GetHeight() < std::numeric_limits<float>::epsilon()) {
780 #endif
781         // if clipRect is empty, this node will be removed from parent's children list.
782         node.SetContextClipRegion(std::nullopt);
783 
784         static int pixel = 1;
785         auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
786         auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
787         auto iter = surfaceCallbacks_.find(node.GetId());
788         if (iter != surfaceCallbacks_.end()) {
789             (iter->second)(canvas_->getTotalMatrix().getTranslateX(), canvas_->getTotalMatrix().getTranslateY(), width, height);
790         }
791         return;
792     }
793     node.SetContextClipRegion(clipRect);
794 
795     // clip hole
796     ClipHoleForSurfaceNode(node);
797 
798     // 1. add this node to parent's children list
799     childSurfaceNodeIds_.emplace_back(node.GetId());
800 
801     // 2. backup and reset environment variables before traversal children
802     std::vector<NodeId> siblingSurfaceNodeIds(std::move(childSurfaceNodeIds_));
803     childSurfaceNodeIds_.clear();
804     auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
805 #ifndef USE_ROSEN_DRAWING
806     parentSurfaceNodeMatrix_ = canvas_->getTotalMatrix();
807 #else
808     parentSurfaceNodeMatrix_ = canvas_->GetTotalMatrix();
809 #endif // USE_ROSEN_DRAWING
810 
811     // 3. traversal children, child surface node will be added to childSurfaceNodeIds_
812     // note: apply current node properties onto canvas if there is any child node
813     ProcessChildren(node);
814 
815     // 4. if children changed, sync children to RenderService
816     if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_) {
817         auto thisSurfaceNodeId = node.GetId();
818         std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearChild>(thisSurfaceNodeId);
819         SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
820         for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
821             command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
822             SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
823         }
824         node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
825     }
826 
827     // 5. restore environments variables before continue traversal siblings
828     childSurfaceNodeIds_ = std::move(siblingSurfaceNodeIds);
829     parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
830 
831     // 6.draw border
832 #ifndef USE_ROSEN_DRAWING
833     canvas_->save();
834     auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
835     canvas_->concat(geoPtr->GetMatrix());
836     RSPropertiesPainter::DrawBorder(node.GetRenderProperties(), *canvas_);
837     canvas_->restore();
838 #else
839     canvas_->Save();
840     auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
841     canvas_->ConcatMatrix(geoPtr->GetMatrix());
842     RSPropertiesPainter::DrawBorder(node.GetRenderProperties(), *canvas_);
843     canvas_->Restore();
844 #endif
845 }
846 
847 void RSRenderThreadVisitor::ProcessProxyRenderNode(RSProxyRenderNode& node)
848 {
849     if (!canvas_) {
850         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, canvas is nullptr");
851         return;
852     }
853     // RSProxyRenderNode in RSRenderThreadVisitor do not have information of property.
854     // We only get parent's matrix and send it to RenderService
855 #ifdef ROSEN_OHOS
856 #ifndef USE_ROSEN_DRAWING
857     SkMatrix invertMatrix;
858     SkMatrix contextMatrix = canvas_->getTotalMatrix();
859     if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
860         contextMatrix.preConcat(invertMatrix);
861     } else {
862         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, invertMatrix failed");
863     }
864 #else
865     Drawing::Matrix invertMatrix;
866     Drawing::Matrix contextMatrix = canvas_->GetTotalMatrix();
867 
868     if (parentSurfaceNodeMatrix_.Invert(invertMatrix)) {
869         contextMatrix.PreConcat(invertMatrix);
870     } else {
871         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, invertMatrix failed");
872     }
873 #endif // USE_ROSEN_DRAWING
874     node.SetContextMatrix(contextMatrix);
875     node.SetContextAlpha(canvas_->GetAlpha());
876 
877     // context clipRect should be based on parent node's coordinate system, in dividend render mode, it is the
878     // same as canvas coordinate system.
879     auto clipRect = RSPaintFilterCanvas::GetLocalClipBounds(*canvas_);
880     node.SetContextClipRegion(clipRect);
881 #endif
882 }
883 
884 void RSRenderThreadVisitor::AddSurfaceChangedCallBack(uint64_t id,
885     const std::function<void(float, float, float, float)>& callback)
886 {
887     surfaceCallbacks_.emplace(id, callback);
888 }
889 
890 void RSRenderThreadVisitor::RemoveSurfaceChangedCallBack(uint64_t id)
891 {
892     surfaceCallbacks_.erase(id);
893 }
894 
895 void RSRenderThreadVisitor::ClipHoleForSurfaceNode(RSSurfaceRenderNode& node)
896 {
897     // Calculation position in RenderService may appear floating point number, and it will be removed.
898     // It caused missed line problem on surfaceview hap, so we subtract one pixel when cliphole to avoid this problem
899     static int pixel = 1;
900     auto x = std::ceil(node.GetRenderProperties().GetBoundsPositionX() + pixel); // x increase 1 pixel
901     auto y = std::ceil(node.GetRenderProperties().GetBoundsPositionY() + pixel); // y increase 1 pixel
902     auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
903     auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
904 #ifndef USE_ROSEN_DRAWING
905     canvas_->save();
906     SkRect originRect = SkRect::MakeXYWH(x, y, width, height);
907     canvas_->clipRect(originRect);
908 
909     auto iter = surfaceCallbacks_.find(node.GetId());
910     if (iter != surfaceCallbacks_.end()) {
911         (iter->second)(canvas_->getTotalMatrix().getTranslateX(), canvas_->getTotalMatrix().getTranslateY(), width, height);
912     }
913 
914     if (node.IsNotifyRTBufferAvailable()) {
915         ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", clip [%f, %f, %f, %f]",
916             node.GetId(), x, y, width, height);
917         canvas_->clear(SK_ColorTRANSPARENT);
918     } else {
919         ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", not clip [%f, %f, %f, %f]",
920             node.GetId(), x, y, width, height);
921         auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
922         if (backgroundColor != RgbPalette::Transparent()) {
923             canvas_->clear(backgroundColor.AsArgbInt());
924         }
925     }
926     canvas_->restore();
927 #else
928     canvas_->Save();
929     Drawing::Rect originRect = Drawing::Rect(x, y, width + x, height + y);
930     canvas_->ClipRect(originRect, Drawing::ClipOp::INTERSECT, false);
931     if (node.IsNotifyRTBufferAvailable() == true) {
932         ROSEN_LOGI("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", clip [%f, %f, %f, %f]",
933             node.GetId(), x, y, width, height);
934         canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
935     } else {
936         ROSEN_LOGI("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", not clip [%f, %f, %f, %f]",
937             node.GetId(), x, y, width, height);
938         auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
939         if (backgroundColor != RgbPalette::Transparent()) {
940             canvas_->Clear(backgroundColor.AsArgbInt());
941         }
942     }
943     canvas_->Restore();
944 #endif // USE_ROSEN_DRAWING
945 }
946 
947 void RSRenderThreadVisitor::SendCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
948 {
949     auto transactionProxy = RSTransactionProxy::GetInstance();
950     if (transactionProxy != nullptr) {
951         transactionProxy->AddCommandFromRT(command, nodeId, followType);
952     }
953 }
954 } // namespace Rosen
955 } // namespace OHOS
956