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