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