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