• 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 
568     canvas_->Restore();
569     if (RSSystemProperties::GetTextureExportDFXEnabled()) {
570         constexpr auto COLOR = Drawing::Color::COLOR_BLUE;
571         constexpr auto ALPHA = 0.3f;
572 
573         auto dstRect = Drawing::Rect(0, 0, bufferWidth, bufferHeight);
574         Drawing::Brush rectBrush;
575         rectBrush.SetColor(COLOR);
576         rectBrush.SetAntiAlias(true);
577         rectBrush.SetAlphaF(ALPHA);
578         canvas_->AttachBrush(rectBrush);
579         canvas_->DrawRect(dstRect);
580         canvas_->DetachBrush();
581     }
582 #endif
583 
584     RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->FlushFrame");
585     ROSEN_LOGD("RSRenderThreadVisitor FlushFrame surfaceNodeId = %{public}" PRIu64 ", uiTimestamp = %{public}" PRIu64,
586         node.GetRSSurfaceNodeId(), uiTimestamp_);
587     rsSurface->FlushFrame(surfaceFrame, uiTimestamp_);
588 #ifdef RS_ENABLE_VK
589     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
590         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
591         auto fenceFd = std::static_pointer_cast<RSSurfaceOhosVulkan>(rsSurface)->DupReservedFlushFd();
592         fdsan_exchange_owner_tag(fenceFd, 0, LOG_DOMAIN);
593         auto rootId = GetActiveSubtreeRootId();
594         if (rootId != INVALID_NODEID) {
595             RSSurfaceBufferCallbackManager::Instance().SetReleaseFence(fenceFd, rootId);
596             RSSurfaceBufferCallbackManager::Instance().RunSurfaceBufferSubCallbackForVulkan(rootId);
597         }
598         fdsan_close_with_tag(fenceFd, LOG_DOMAIN);
599     }
600 #endif
601 #ifdef ROSEN_OHOS
602     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushEnd);
603 #endif
604     RS_TRACE_END();
605 
606     canvas_ = nullptr;
607     isIdle_ = true;
608 }
609 
ProcessCanvasRenderNode(RSCanvasRenderNode & node)610 void RSRenderThreadVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node)
611 {
612 #ifndef ROSEN_CROSS_PLATFORM
613     RS_OPTIONAL_TRACE_NAME_FMT("RSRenderThreadVisitor::ProcessCanvasRenderNode nodeId is %" PRIu64
614                                " GetIsTextureExportNode is %d properties is %s",
615         node.GetId(), node.GetIsTextureExportNode(), node.GetRenderProperties().Dump().c_str());
616 #endif
617     if (!node.ShouldPaint()) {
618         return;
619     }
620     if (!canvas_) {
621         ROSEN_LOGE("RSRenderThreadVisitor::ProcessCanvasRenderNode, canvas is nullptr");
622         return;
623     }
624 #ifdef RS_ENABLE_EGLQUERYSURFACE
625     node.UpdateRenderStatus(curDirtyRegion_, isOpDropped_);
626     if (node.IsRenderUpdateIgnored()) {
627         return;
628     }
629 #endif
630     RSAutoCanvasRestore acr(canvas_, RSPaintFilterCanvas::SaveType::kAll);
631     node.ApplyAlphaAndBoundsGeometry(*canvas_);
632 
633     if (node.GetCompletedCacheSurface()) {
634         node.SetCacheType(CacheType::NONE);
635         node.ClearCacheSurface();
636     }
637     node.ProcessRenderBeforeChildren(*canvas_);
638     node.ProcessRenderContents(*canvas_);
639     ProcessChildren(node);
640     node.ProcessRenderAfterChildren(*canvas_);
641 }
642 
ProcessEffectRenderNode(RSEffectRenderNode & node)643 void RSRenderThreadVisitor::ProcessEffectRenderNode(RSEffectRenderNode& node)
644 {
645     if (!node.ShouldPaint()) {
646         RS_LOGD("RSRenderThreadVisitor::ProcessEffectRenderNode, no need process");
647         return;
648     }
649     if (!canvas_) {
650         RS_LOGE("RSRenderThreadVisitor::ProcessEffectRenderNode, canvas is nullptr");
651         return;
652     }
653     node.ProcessRenderBeforeChildren(*canvas_);
654     ProcessChildren(node);
655     node.ProcessRenderAfterChildren(*canvas_);
656 }
657 
CacRotationFromTransformType(GraphicTransformType transform,RectF & bounds)658 Drawing::Matrix RSRenderThreadVisitor::CacRotationFromTransformType(GraphicTransformType transform, RectF& bounds)
659 {
660     GraphicTransformType rotation;
661     switch (transform) {
662         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
663         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
664             rotation = GraphicTransformType::GRAPHIC_ROTATE_90;
665             break;
666         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
667         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
668             rotation = GraphicTransformType::GRAPHIC_ROTATE_180;
669             break;
670         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
671         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270:
672             rotation = GraphicTransformType::GRAPHIC_ROTATE_270;
673             break;
674         default:
675             rotation = transform;
676             break;
677     }
678     Drawing::Matrix matrix;
679     const float boundsWidth = bounds.GetWidth();
680     const float boundsHeight = bounds.GetHeight();
681     switch (rotation) {
682         case GraphicTransformType::GRAPHIC_ROTATE_90: {
683             matrix.PreTranslate(0, boundsHeight);
684             matrix.PreRotate(-90); // rotate 90 degrees anti-clockwise at last.
685             break;
686         }
687         case GraphicTransformType::GRAPHIC_ROTATE_180: {
688             matrix.PreTranslate(boundsWidth, boundsHeight);
689             matrix.PreRotate(-180); // rotate 180 degrees anti-clockwise at last.
690             break;
691         }
692         case GraphicTransformType::GRAPHIC_ROTATE_270: {
693             matrix.PreTranslate(boundsWidth, 0);
694             matrix.PreRotate(-270); // rotate 270 degrees anti-clockwise at last.
695             break;
696         }
697         default:
698             break;
699     }
700     if (rotation == GraphicTransformType::GRAPHIC_ROTATE_90 || rotation == GraphicTransformType::GRAPHIC_ROTATE_270) {
701         std::swap(bounds.width_, bounds.height_);
702     }
703     return matrix;
704 }
705 
GetFlipTransform(GraphicTransformType transform)706 GraphicTransformType RSRenderThreadVisitor::GetFlipTransform(GraphicTransformType transform)
707 {
708     switch (transform) {
709         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
710         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
711         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270: {
712             return GraphicTransformType::GRAPHIC_FLIP_H;
713         }
714         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
715         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
716         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
717             return GraphicTransformType::GRAPHIC_FLIP_V;
718         }
719         default: {
720             return transform;
721         }
722     }
723 }
724 
FlipMatrix(GraphicTransformType transform,Drawing::Matrix & matrix,const RectF & bounds)725 void RSRenderThreadVisitor::FlipMatrix(GraphicTransformType transform, Drawing::Matrix& matrix, const RectF& bounds)
726 {
727     GraphicTransformType type = GetFlipTransform(transform);
728     if (type != GraphicTransformType::GRAPHIC_FLIP_H && type != GraphicTransformType::GRAPHIC_FLIP_V) {
729         return;
730     }
731 
732     const int angle = 180;
733     Drawing::Camera3D camera3D;
734     if (GraphicTransformType::GRAPHIC_FLIP_H) {
735         camera3D.RotateYDegrees(angle);
736     } else {
737         camera3D.RotateXDegrees(angle);
738     }
739     Drawing::Matrix flip;
740     camera3D.ApplyToMatrix(flip);
741     const float half = 0.5f;
742     flip.PreTranslate(-half * bounds.GetWidth(), -half * bounds.GetHeight());
743     flip.PostTranslate(half * bounds.GetWidth(), half * bounds.GetHeight());
744     matrix.PreConcat(flip);
745 }
746 
ProcessSurfaceViewInRT(RSSurfaceRenderNode & node)747 void RSRenderThreadVisitor::ProcessSurfaceViewInRT(RSSurfaceRenderNode& node)
748 {
749     const auto& property = node.GetRenderProperties();
750     auto& geoPtr = property.GetBoundsGeometry();
751     canvas_->ConcatMatrix(geoPtr->GetMatrix());
752     canvas_->Save();
753 #ifdef ROSEN_OHOS
754     sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(node.GetSurfaceId());
755     if (surface == nullptr) {
756         RS_LOGE("RSRenderThreadVisitor::ProcessSurfaceViewInRT nodeId is %{public}" PRIu64
757                 " cannot find surface by surfaceId %{public}" PRIu64 "",
758             node.GetId(), node.GetSurfaceId());
759         RS_TRACE_NAME_FMT("RSRenderThreadVisitor::ProcessSurfaceViewInRT nodeId is " PRIu64
760                 " cannot find surface by surfaceId " PRIu64 "",
761             node.GetId(), node.GetSurfaceId());
762         return;
763     }
764     sptr<SurfaceBuffer> surfaceBuffer;
765     // a 4 * 4 idetity matrix
766     float matrix[16] = {
767         1, 0, 0, 0,
768         0, 1, 0, 0,
769         0, 0, 1, 0,
770         0, 0, 0, 1
771     };
772     sptr<SyncFence> fence;
773     int ret = surface->GetLastFlushedBuffer(surfaceBuffer, fence, matrix);
774     if (ret != OHOS::GSERROR_OK || surfaceBuffer == nullptr) {
775         RS_OPTIONAL_TRACE_NAME_FMT(
776             "RSRenderThreadVisitor::ProcessSurfaceViewInRT:GetLastFlushedBuffer failed, err: %d", ret);
777         RS_LOGE("RSRenderThreadVisitor::ProcessSurfaceViewInRT: GetLastFlushedBuffer failed, err: %{public}d", ret);
778         return;
779     }
780     if (fence != nullptr) {
781         RS_OPTIONAL_TRACE_NAME_FMT("RSRenderThreadVisitor::ProcessSurfaceViewInRT: waitfence");
782         fence->Wait(3000); // wait at most 3000ms
783     }
784     auto transform = surface->GetTransform();
785     RectF bounds = {property.GetBoundsPositionX(), property.GetBoundsPositionY(),
786         property.GetBoundsWidth(), property.GetBoundsHeight()};
787     Drawing::Matrix transfromMatrix = CacRotationFromTransformType(transform, bounds);
788     FlipMatrix(transform, transfromMatrix, bounds);
789     ScalingMode scalingMode = surfaceBuffer->GetSurfaceBufferScalingMode();
790     Drawing::Rect srcRect { 0, 0, surfaceBuffer->GetWidth(), surfaceBuffer->GetHeight() };
791     Drawing::Rect dstRect { 0, 0, bounds.width_, bounds.height_ };
792     Drawing::Rect boundsRect = { bounds.left_, bounds.top_, bounds.left_ + bounds.width_,
793         bounds.top_ + bounds.height_ };
794     if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
795         RSRenderThreadUtil::SrcRectScaleDown(srcRect, boundsRect);
796     } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
797         RSRenderThreadUtil::SrcRectScaleFit(srcRect, dstRect, boundsRect);
798     }
799     canvas_->ConcatMatrix(transfromMatrix);
800     auto recordingCanvas =
801         std::make_shared<ExtendRecordingCanvas>(property.GetBoundsWidth(), property.GetBoundsHeight());
802     DrawingSurfaceBufferInfo rsSurfaceBufferInfo(
803         surfaceBuffer, dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetWidth(), dstRect.GetHeight());
804     rsSurfaceBufferInfo.srcRect_ = srcRect;
805     recordingCanvas->DrawSurfaceBuffer(rsSurfaceBufferInfo);
806     auto drawCmdList = recordingCanvas->GetDrawCmdList();
807     drawCmdList->Playback(*canvas_);
808     drawCmdListVector_.emplace_back(drawCmdList);
809 #endif
810     canvas_->Restore();
811 }
812 
ProcessSurfaceRenderNode(RSSurfaceRenderNode & node)813 void RSRenderThreadVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
814 {
815 #ifndef ROSEN_CROSS_PLATFORM
816     RS_OPTIONAL_TRACE_NAME_FMT("RSRenderThreadVisitor::ProcessSurfaceRenderNode nodeId is %" PRIu64
817                                " GetIsTextureExportNode is %d name is %s properties is %s",
818         node.GetId(), node.GetIsTextureExportNode(), node.GetName().c_str(), node.GetRenderProperties().Dump().c_str());
819 #endif
820     if (!canvas_) {
821         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
822         return;
823     }
824     if (!node.ShouldPaint()) {
825         ROSEN_LOGI("RSRenderThreadVisitor::ProcessSurfaceRenderNode node : %{public}" PRIu64 " is invisible",
826             node.GetId());
827         node.SetContextAlpha(0.0f);
828         return;
829     }
830     // RSSurfaceRenderNode in RSRenderThreadVisitor do not have information of property.
831     // We only get parent's matrix and send it to RenderService
832     Drawing::Matrix invertMatrix;
833     Drawing::Matrix contextMatrix = canvas_->GetTotalMatrix();
834 
835     if (parentSurfaceNodeMatrix_.Invert(invertMatrix)) {
836         contextMatrix.PreConcat(invertMatrix);
837     } else {
838         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, invertMatrix failed");
839     }
840     if (!RSUniRenderJudgement::IsUniRender() && !node.GetIsTextureExportNode()) {
841         node.SetContextMatrix(contextMatrix);
842         node.SetContextAlpha(canvas_->GetAlpha());
843     }
844 
845     if (node.GetIsTextureExportNode()) {
846         canvas_->Save();
847         auto& geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
848         canvas_->ConcatMatrix(geoPtr->GetMatrix());
849         RSPropertiesPainter::DrawBackground(node.GetRenderProperties(), *canvas_);
850         canvas_->Restore();
851     }
852 
853     // PLANNING: This is a temporary modification. Animation for surfaceView should not be triggered in RenderService.
854     // We plan to refactor code here.
855     node.SetContextBounds(node.GetRenderProperties().GetBounds());
856 #ifdef USE_SURFACE_TEXTURE
857     if (node.GetIsTextureExportNode()) {
858         ProcessSurfaceViewInRT(node);
859     } else if (node.GetSurfaceNodeType() == RSSurfaceNodeType::SURFACE_TEXTURE_NODE) {
860         ProcessTextureSurfaceRenderNode(node);
861     } else {
862         ProcessOtherSurfaceRenderNode(node);
863     }
864 #else
865     if (node.GetIsTextureExportNode()) {
866         ProcessSurfaceViewInRT(node);
867     } else {
868         ProcessOtherSurfaceRenderNode(node);
869     }
870 #endif
871 
872     // 1. add this node to parent's children list
873     childSurfaceNodeIds_.emplace_back(node.GetId());
874 
875     // 2. backup and reset environment variables before traversal children
876     auto siblingSurfaceNodeIds(std::move(childSurfaceNodeIds_));
877     childSurfaceNodeIds_.clear();
878     auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
879     parentSurfaceNodeMatrix_ = canvas_->GetTotalMatrix();
880 
881     // 3. traversal children, child surface node will be added to childSurfaceNodeIds_
882     // note: apply current node properties onto canvas if there is any child node
883     ProcessChildren(node);
884 
885     // 4. if children changed, sync children to RenderService
886     if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_) {
887         auto thisSurfaceNodeId = node.GetId();
888         std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearChild>(thisSurfaceNodeId);
889         SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
890         for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
891             command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
892             SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_TO_SELF);
893         }
894         node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
895         childSurfaceNodeIds_.clear();
896     }
897 
898     // 5. restore environments variables before continue traversal siblings
899     childSurfaceNodeIds_ = std::move(siblingSurfaceNodeIds);
900     siblingSurfaceNodeIds.clear();
901     parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
902 
903     // 6.draw border
904     canvas_->Save();
905     auto& geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
906     canvas_->ConcatMatrix(geoPtr->GetMatrix());
907     RSPropertiesPainter::DrawOutline(node.GetRenderProperties(), *canvas_);
908     RSPropertiesPainter::DrawBorder(node.GetRenderProperties(), *canvas_);
909     canvas_->Restore();
910 }
911 
ProcessProxyRenderNode(RSProxyRenderNode & node)912 void RSRenderThreadVisitor::ProcessProxyRenderNode(RSProxyRenderNode& node)
913 {
914     if (!canvas_) {
915         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, canvas is nullptr");
916         return;
917     }
918     // RSProxyRenderNode in RSRenderThreadVisitor do not have information of property.
919     // We only get parent's matrix and send it to RenderService
920 #ifdef ROSEN_OHOS
921     Drawing::Matrix invertMatrix;
922     Drawing::Matrix contextMatrix = canvas_->GetTotalMatrix();
923 
924     if (parentSurfaceNodeMatrix_.Invert(invertMatrix)) {
925         contextMatrix.PreConcat(invertMatrix);
926     } else {
927         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, invertMatrix failed");
928     }
929     node.SetContextMatrix(contextMatrix);
930     node.SetContextAlpha(canvas_->GetAlpha());
931 
932     // context clipRect should be based on parent node's coordinate system, in dividend render mode, it is the
933     // same as canvas coordinate system.
934     auto clipRect = RSPaintFilterCanvas::GetLocalClipBounds(*canvas_);
935     node.SetContextClipRegion(clipRect);
936 #endif
937 }
938 
AddSurfaceChangedCallBack(uint64_t id,const std::function<void (float,float,float,float)> & callback)939 void RSRenderThreadVisitor::AddSurfaceChangedCallBack(uint64_t id,
940     const std::function<void(float, float, float, float)>& callback)
941 {
942     surfaceCallbacks_.emplace(id, callback);
943 }
944 
RemoveSurfaceChangedCallBack(uint64_t id)945 void RSRenderThreadVisitor::RemoveSurfaceChangedCallBack(uint64_t id)
946 {
947     surfaceCallbacks_.erase(id);
948 }
949 
ClipHoleForSurfaceNode(RSSurfaceRenderNode & node)950 void RSRenderThreadVisitor::ClipHoleForSurfaceNode(RSSurfaceRenderNode& node)
951 {
952     // Calculation position in RenderService may appear floating point number, and it will be removed.
953     // It caused missed line problem on surfaceview hap, so we subtract one pixel when cliphole to avoid this problem
954     static int pixel = 1;
955     auto x = std::ceil(node.GetRenderProperties().GetBoundsPositionX() + pixel); // x increase 1 pixel
956     auto y = std::ceil(node.GetRenderProperties().GetBoundsPositionY() + pixel); // y increase 1 pixel
957     auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
958     auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
959     canvas_->Save();
960     Drawing::Rect originRect = Drawing::Rect(x, y, width + x, height + y);
961     canvas_->ClipRect(originRect, Drawing::ClipOp::INTERSECT, false);
962     auto iter = surfaceCallbacks_.find(node.GetId());
963     if (iter != surfaceCallbacks_.end()) {
964         (iter->second)(canvas_->GetTotalMatrix().Get(Drawing::Matrix::TRANS_X),
965             canvas_->GetTotalMatrix().Get(Drawing::Matrix::TRANS_Y), width, height);
966     }
967     if (node.IsNotifyRTBufferAvailable() == true) {
968         ROSEN_LOGI("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %{public}" PRIu64 ","
969             "clip [%{public}f, %{public}f, %{public}f, %{public}f]", node.GetId(), x, y, width, height);
970         canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
971     } else {
972         ROSEN_LOGI("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %{public}" PRIu64 ","
973             "not clip [%{public}f, %{public}f, %{public}f, %{public}f]", node.GetId(), x, y, width, height);
974         auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
975         if (backgroundColor != RgbPalette::Transparent()) {
976             canvas_->Clear(backgroundColor.AsArgbInt());
977         }
978     }
979     canvas_->Restore();
980 }
981 
SendCommandFromRT(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)982 void RSRenderThreadVisitor::SendCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
983 {
984     auto transactionProxy = RSTransactionProxy::GetInstance(); // planing
985     if (transactionProxy != nullptr) {
986         transactionProxy->AddCommandFromRT(command, nodeId, followType);
987     }
988 }
989 
990 #ifdef USE_SURFACE_TEXTURE
ProcessTextureSurfaceRenderNode(RSSurfaceRenderNode & node)991 void RSRenderThreadVisitor::ProcessTextureSurfaceRenderNode(RSSurfaceRenderNode& node)
992 {
993     auto texture = node.GetSurfaceTexture();
994     if (texture == nullptr) {
995         ROSEN_LOGE("ProcessTextureSurfaceRenderNode %{public}" PRIu64, node.GetId());
996         return;
997     }
998     node.ApplyModifiers();
999     auto clipRect = RSPaintFilterCanvas::GetLocalClipBounds(*canvas_);
1000     if (!clipRect.has_value() ||
1001         clipRect->GetWidth() < std::numeric_limits<float>::epsilon() ||
1002         clipRect->GetHeight() < std::numeric_limits<float>::epsilon()) {
1003         // if clipRect is empty, this node will be removed from parent's children list.
1004         return;
1005     }
1006 
1007     // Calculation position in RenderService may appear floating point number, and it will be removed.
1008     // It caused missed line problem on surfaceview hap, so we subtract one pixel when cliphole to avoid this problem
1009     static int pixel = 1;
1010     auto x = std::ceil(node.GetRenderProperties().GetBoundsPositionX() + pixel); // x increase 1 pixel
1011     auto y = std::ceil(node.GetRenderProperties().GetBoundsPositionY() + pixel); // y increase 1 pixel
1012     auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
1013     auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
1014 
1015     canvas_->Save();
1016     Drawing::Rect originRect = Drawing::Rect(x, y, width + x, height + y);
1017 
1018     if (node.IsNotifyRTBufferAvailable()) {
1019         texture->DrawTextureImage(*canvas_, false, originRect);
1020     } else {
1021         auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
1022         if (backgroundColor != RgbPalette::Transparent()) {
1023             canvas_->Clear(backgroundColor.AsArgbInt());
1024         }
1025     }
1026     canvas_->Restore();
1027 }
1028 #endif
1029 
ProcessOtherSurfaceRenderNode(RSSurfaceRenderNode & node)1030 void RSRenderThreadVisitor::ProcessOtherSurfaceRenderNode(RSSurfaceRenderNode& node)
1031 {
1032     auto clipRect = RSPaintFilterCanvas::GetLocalClipBounds(*canvas_);
1033     if (!clipRect.has_value() ||
1034         clipRect->GetWidth() < std::numeric_limits<float>::epsilon() ||
1035         clipRect->GetHeight() < std::numeric_limits<float>::epsilon()) {
1036         // if clipRect is empty, this node will be removed from parent's children list.
1037         node.SetContextClipRegion(std::nullopt);
1038 
1039         static int pixel = 1;
1040         auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
1041         auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
1042         auto iter = surfaceCallbacks_.find(node.GetId());
1043         if (iter != surfaceCallbacks_.end()) {
1044             (iter->second)(canvas_->GetTotalMatrix().Get(Drawing::Matrix::TRANS_X),
1045                 canvas_->GetTotalMatrix().Get(Drawing::Matrix::TRANS_Y), width, height);
1046         }
1047         return;
1048     }
1049     if (!node.GetIsTextureExportNode()) {
1050         node.SetContextClipRegion(clipRect);
1051     }
1052     // temporary workaround since ContextAlpha/ContextClipRegion happens after ApplyModifiers
1053     node.ApplyModifiers();
1054 
1055     // clip hole
1056     ClipHoleForSurfaceNode(node);
1057 }
1058 
GetActiveSubtreeRootId()1059 NodeId RSRenderThreadVisitor::GetActiveSubtreeRootId()
1060 {
1061     return activeSubtreeRootId_;
1062 }
1063 } // namespace Rosen
1064 } // namespace OHOS
1065