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