• 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 <include/core/SkColor.h>
20 #include <include/core/SkFont.h>
21 #include <include/core/SkMatrix.h>
22 #include <include/core/SkPaint.h>
23 #include <include/core/SkRect.h>
24 
25 #include "rs_trace.h"
26 
27 #include "command/rs_base_node_command.h"
28 #include "common/rs_vector4.h"
29 #include "pipeline/rs_canvas_render_node.h"
30 #include "pipeline/rs_dirty_region_manager.h"
31 #include "pipeline/rs_node_map.h"
32 #include "pipeline/rs_proxy_render_node.h"
33 #include "pipeline/rs_render_thread.h"
34 #include "pipeline/rs_root_render_node.h"
35 #include "pipeline/rs_surface_render_node.h"
36 #include "platform/common/rs_log.h"
37 #include "platform/drawing/rs_surface.h"
38 #include "transaction/rs_transaction_proxy.h"
39 #include "ui/rs_surface_extractor.h"
40 #include "ui/rs_surface_node.h"
41 
42 #ifdef ROSEN_OHOS
43 #include <frame_collector.h>
44 #include <frame_painter.h>
45 #include "platform/ohos/overdraw/rs_cpu_overdraw_canvas_listener.h"
46 #include "platform/ohos/overdraw/rs_gpu_overdraw_canvas_listener.h"
47 #include "platform/ohos/overdraw/rs_overdraw_controller.h"
48 #endif
49 
50 namespace OHOS {
51 namespace Rosen {
RSRenderThreadVisitor()52 RSRenderThreadVisitor::RSRenderThreadVisitor()
53     : curDirtyManager_(std::make_shared<RSDirtyRegionManager>()), canvas_(nullptr) {}
54 
55 RSRenderThreadVisitor::~RSRenderThreadVisitor() = default;
56 
IsValidRootRenderNode(RSRootRenderNode & node)57 bool RSRenderThreadVisitor::IsValidRootRenderNode(RSRootRenderNode& node)
58 {
59     auto ptr = RSNodeMap::Instance().GetNode<RSSurfaceNode>(node.GetRSSurfaceNodeId());
60     if (ptr == nullptr) {
61         ROSEN_LOGE("No valid RSSurfaceNode id");
62         return false;
63     }
64     if (!node.enableRender_) {
65         ROSEN_LOGD("RootNode %s: Invisible", ptr->GetName().c_str());
66         return false;
67     }
68     if (node.GetSuggestedBufferWidth() <= 0 || node.GetSuggestedBufferHeight() <= 0) {
69         ROSEN_LOGD("Root %s: Negative width or height [%f %f]", ptr->GetName().c_str(),
70             node.GetSuggestedBufferWidth(), node.GetSuggestedBufferHeight());
71         return false;
72     }
73     return true;
74 }
75 
SetPartialRenderStatus(PartialRenderType status,bool isRenderForced)76 void RSRenderThreadVisitor::SetPartialRenderStatus(PartialRenderType status, bool isRenderForced)
77 {
78     isRenderForced_ = isRenderForced;
79     isEglSetDamageRegion_ = !isRenderForced_ && (status != PartialRenderType::DISABLED);
80     isOpDropped_ = !isRenderForced_ && (status == PartialRenderType::SET_DAMAGE_AND_DROP_OP);
81     if (partialRenderStatus_ == status) {
82         ROSEN_LOGD("SetPartialRenderStatus: %d->%d, isRenderForced_=%d, isEglSetDamageRegion_=%d, isOpDropped_=%d",
83             partialRenderStatus_, status, isRenderForced_, isEglSetDamageRegion_, isOpDropped_);
84     }
85     partialRenderStatus_ = status;
86 }
87 
PrepareBaseRenderNode(RSBaseRenderNode & node)88 void RSRenderThreadVisitor::PrepareBaseRenderNode(RSBaseRenderNode& node)
89 {
90     node.ResetSortedChildren();
91     for (auto& child : node.GetChildren()) {
92         if (auto renderChild = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(child.lock())) {
93             renderChild->ApplyModifiers();
94         }
95     }
96     for (auto& child : node.GetSortedChildren()) {
97         child->Prepare(shared_from_this());
98     }
99 }
100 
PrepareRootRenderNode(RSRootRenderNode & node)101 void RSRenderThreadVisitor::PrepareRootRenderNode(RSRootRenderNode& node)
102 {
103     if (isIdle_) {
104         curDirtyManager_ = node.GetDirtyManager();
105         curDirtyManager_->Clear();
106         // After the node calls ApplyModifiers, the modifiers assign the renderProperties to the node
107         // Otherwise node.GetSuggestedBufferHeight always less than 0, causing black screen
108         node.ApplyModifiers();
109         if (!IsValidRootRenderNode(node)) {
110             return;
111         }
112         dirtyFlag_ = false;
113         isIdle_ = false;
114         PrepareCanvasRenderNode(node);
115         isIdle_ = true;
116     } else {
117         PrepareCanvasRenderNode(node);
118     }
119 }
120 
PrepareCanvasRenderNode(RSCanvasRenderNode & node)121 void RSRenderThreadVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode& node)
122 {
123     node.ApplyModifiers();
124     if (!node.ShouldPaint()) {
125         return;
126     }
127     bool dirtyFlag = dirtyFlag_;
128     auto nodeParent = node.GetParent().lock();
129     std::shared_ptr<RSRenderNode> rsParent = nullptr;
130     if (nodeParent != nullptr) {
131         rsParent = nodeParent->ReinterpretCastTo<RSRenderNode>();
132     }
133     dirtyFlag_ = node.Update(*curDirtyManager_, rsParent ? &(rsParent->GetRenderProperties()) : nullptr, dirtyFlag_);
134     if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
135         curDirtyManager_->UpdateDirtyCanvasNodes(node.GetId(), node.GetOldDirty());
136     }
137     PrepareBaseRenderNode(node);
138     dirtyFlag_ = dirtyFlag;
139 }
140 
PrepareSurfaceRenderNode(RSSurfaceRenderNode & node)141 void RSRenderThreadVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node)
142 {
143     node.ApplyModifiers();
144     bool dirtyFlag = dirtyFlag_;
145     auto nodeParent = node.GetParent().lock();
146     std::shared_ptr<RSRenderNode> rsParent = nullptr;
147     if (nodeParent != nullptr) {
148         rsParent = nodeParent->ReinterpretCastTo<RSRenderNode>();
149     }
150     // If rt buffer switches to be available
151     // set its SurfaceRenderNode's render dirty
152     if (!node.IsNotifyRTBufferAvailablePre() && node.IsNotifyRTBufferAvailable()) {
153         ROSEN_LOGD("NotifyRTBufferAvailable and set it dirty");
154         node.SetDirty();
155     }
156     dirtyFlag_ = node.Update(*curDirtyManager_, rsParent ? &(rsParent->GetRenderProperties()) : nullptr, dirtyFlag_);
157     if (node.IsDirtyRegionUpdated() && curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
158         curDirtyManager_->UpdateDirtySurfaceNodes(node.GetId(), node.GetOldDirty());
159     }
160     PrepareBaseRenderNode(node);
161     dirtyFlag_ = dirtyFlag;
162 }
163 
DrawRectOnCanvas(const RectI & dirtyRect,const SkColor color,const SkPaint::Style fillType,float alpha)164 void RSRenderThreadVisitor::DrawRectOnCanvas(const RectI& dirtyRect, const SkColor color,
165     const SkPaint::Style fillType, float alpha)
166 {
167     if (dirtyRect.width_ <= 0 || dirtyRect.height_ <= 0) {
168         ROSEN_LOGD("DrawRectOnCanvas dirty rect is invalid.");
169         return;
170     }
171     auto skRect = SkRect::MakeXYWH(dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
172     const int defaultEdgeWidth = 6;
173     SkPaint rectPaint;
174     rectPaint.setColor(color);
175     rectPaint.setAntiAlias(true);
176     rectPaint.setAlphaf(alpha);
177     rectPaint.setStyle(fillType);
178     rectPaint.setStrokeWidth(defaultEdgeWidth);
179     if (fillType == SkPaint::kFill_Style) {
180         rectPaint.setStrokeJoin(SkPaint::kRound_Join);
181     }
182     canvas_->drawRect(skRect, rectPaint);
183 }
184 
DrawDirtyRegion()185 void RSRenderThreadVisitor::DrawDirtyRegion()
186 {
187     auto dirtyRect = RectI();
188     const float fillAlpha = 0.2;
189     const float edgeAlpha = 0.4;
190     const float subFactor = 2.0;
191 
192     if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::MULTI_HISTORY)) {
193         dirtyRect = curDirtyManager_->GetDirtyRegion();
194         if (dirtyRect.IsEmpty()) {
195             ROSEN_LOGD("DrawDirtyRegion his dirty rect is invalid. dirtyRect = [%d, %d, %d, %d]",
196                 dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
197         } else {
198             ROSEN_LOGD("DrawDirtyRegion his dirty rect. dirtyRect = [%d, %d, %d, %d]",
199                 dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
200             // green
201             DrawRectOnCanvas(dirtyRect, 0xFF0AFF0A, SkPaint::kFill_Style, fillAlpha / subFactor);
202             DrawRectOnCanvas(dirtyRect, 0xFF0AFF0A, SkPaint::kStroke_Style, edgeAlpha);
203         }
204     }
205 
206     if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_WHOLE)) {
207         dirtyRect = curDirtyManager_->GetLatestDirtyRegion();
208         if (dirtyRect.IsEmpty()) {
209             ROSEN_LOGD("DrawDirtyRegion current frame's dirty rect is invalid. dirtyRect = [%d, %d, %d, %d]",
210                 dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
211         } else {
212             ROSEN_LOGD("DrawDirtyRegion cur dirty rect. dirtyRect = [%d, %d, %d, %d]",
213                 dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
214             // yellow
215             DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, SkPaint::kFill_Style, fillAlpha);
216             DrawRectOnCanvas(dirtyRect, 0xFFFFFF00, SkPaint::kStroke_Style, edgeAlpha);
217         }
218     }
219 
220     if (curDirtyManager_->IsDebugRegionTypeEnable(DebugRegionType::CURRENT_SUB)) {
221         std::map<NodeId, RectI> dirtySubRects_;
222         curDirtyManager_->GetDirtyCanvasNodes(dirtySubRects_);
223         for (const auto& [nid, subRect] : dirtySubRects_) {
224             ROSEN_LOGD("DrawDirtyRegion canvasNode id %" PRIu64 " is dirty. dirtyRect = [%d, %d, %d, %d]", nid,
225                 subRect.left_, subRect.top_, subRect.width_, subRect.height_);
226             // red
227             DrawRectOnCanvas(subRect, 0xFFFF0000, SkPaint::kStroke_Style, edgeAlpha / subFactor);
228         }
229 
230         curDirtyManager_->GetDirtySurfaceNodes(dirtySubRects_);
231         for (const auto& [nid, subRect] : dirtySubRects_) {
232             ROSEN_LOGD("DrawDirtyRegion surfaceNode id %" PRIu64 " is dirty. dirtyRect = [%d, %d, %d, %d]", nid,
233                 subRect.left_, subRect.top_, subRect.width_, subRect.height_);
234             // light purple
235             DrawRectOnCanvas(subRect, 0xFFD899D8, SkPaint::kStroke_Style, edgeAlpha);
236         }
237     }
238 }
239 
UpdateDirtyAndSetEGLDamageRegion(std::unique_ptr<RSSurfaceFrame> & surfaceFrame)240 void RSRenderThreadVisitor::UpdateDirtyAndSetEGLDamageRegion(std::unique_ptr<RSSurfaceFrame>& surfaceFrame)
241 {
242     RS_TRACE_BEGIN("UpdateDirtyAndSetEGLDamageRegion");
243 #ifdef RS_ENABLE_EGLQUERYSURFACE
244     if (isEglSetDamageRegion_) {
245         // get and update valid buffer age(>0) to merge history
246         int32_t bufferAge = surfaceFrame->GetBufferAge();
247         if (!curDirtyManager_->SetBufferAge(bufferAge)) {
248             ROSEN_LOGD("ProcessRootRenderNode SetBufferAge with invalid buffer age %d", bufferAge);
249             curDirtyManager_->ResetDirtyAsSurfaceSize();
250         }
251         curDirtyManager_->UpdateDirtyByAligned();
252         curDirtyManager_->UpdateDirty();
253         curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
254         // only set damage region if dirty region and buffer age is valid(>0)
255         if (bufferAge >= 0) {
256             // get dirty rect coordinated from upper left to lower left corner in current surface
257             RectI dirtyRectFlip = curDirtyManager_->GetRectFlipWithinSurface(curDirtyRegion_);
258             // set dirty rect as eglSurfaceFrame's damage region
259             surfaceFrame->SetDamageRegion(dirtyRectFlip.left_, dirtyRectFlip.top_, dirtyRectFlip.width_,
260                 dirtyRectFlip.height_);
261             // flip aligned rect for op drops
262             curDirtyRegion_ = curDirtyManager_->GetRectFlipWithinSurface(dirtyRectFlip);
263             ROSEN_LOGD("GetPartialRenderEnabled buffer age %d, dirtyRectFlip = [%d, %d, %d, %d], "
264                 "dirtyRectAlign = [%d, %d, %d, %d]", bufferAge,
265                 dirtyRectFlip.left_, dirtyRectFlip.top_, dirtyRectFlip.width_, dirtyRectFlip.height_,
266                 curDirtyRegion_.left_, curDirtyRegion_.top_, curDirtyRegion_.width_, curDirtyRegion_.height_);
267         }
268     } else {
269         curDirtyManager_->UpdateDirty();
270         curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
271     }
272 #else
273     curDirtyManager_->UpdateDirty();
274     curDirtyRegion_ = curDirtyManager_->GetDirtyRegion();
275 #endif
276     ROSEN_LOGD("UpdateDirtyAndSetEGLDamageRegion dirtyRect = [%d, %d, %d, %d]",
277         curDirtyRegion_.left_, curDirtyRegion_.top_, curDirtyRegion_.width_, curDirtyRegion_.height_);
278     RS_TRACE_END();
279 }
280 
ProcessBaseRenderNode(RSBaseRenderNode & node)281 void RSRenderThreadVisitor::ProcessBaseRenderNode(RSBaseRenderNode& node)
282 {
283     for (auto& child : node.GetSortedChildren()) {
284         child->Process(shared_from_this());
285     }
286     // clear SortedChildren, it will be generated again in next frame
287     node.ResetSortedChildren();
288 }
289 
ProcessRootRenderNode(RSRootRenderNode & node)290 void RSRenderThreadVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
291 {
292     if (!isIdle_) {
293         ProcessCanvasRenderNode(node);
294         return;
295     }
296     auto ptr = RSNodeMap::Instance().GetNode<RSSurfaceNode>(node.GetRSSurfaceNodeId());
297     if (!IsValidRootRenderNode(node)) {
298         return;
299     }
300 
301     curDirtyManager_ = node.GetDirtyManager();
302 
303 #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__gnu_linux__)
304     auto surfaceNodeColorSpace = ptr->GetColorSpace();
305 #endif
306     std::shared_ptr<RSSurface> rsSurface = RSSurfaceExtractor::ExtractRSSurface(ptr);
307     if (rsSurface == nullptr) {
308         ROSEN_LOGE("ProcessRoot %s: No RSSurface found", ptr->GetName().c_str());
309         return;
310     }
311     // Update queue size for each process loop in case it dynamically changes
312     queueSize_ = rsSurface->GetQueueSize();
313 
314 #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__gnu_linux__)
315     auto rsSurfaceColorSpace = rsSurface->GetColorSpace();
316     if (surfaceNodeColorSpace != rsSurfaceColorSpace) {
317         ROSEN_LOGD("Set new colorspace %d to rsSurface", surfaceNodeColorSpace);
318         rsSurface->SetColorSpace(surfaceNodeColorSpace);
319     }
320 #endif
321 
322 #ifdef ACE_ENABLE_GL
323     RenderContext* rc = RSRenderThread::Instance().GetRenderContext();
324     rsSurface->SetRenderContext(rc);
325 #endif
326     uiTimestamp_ = RSRenderThread::Instance().GetUITimestamp();
327     RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->RequestFrame");
328 #ifdef ROSEN_OHOS
329     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseStart);
330 #endif
331 
332     const auto& property = node.GetRenderProperties();
333     const float bufferWidth = node.GetSuggestedBufferWidth() * property.GetScaleX();
334     const float bufferHeight = node.GetSuggestedBufferHeight() * property.GetScaleY();
335 #ifdef ROSEN_OHOS
336     auto surfaceFrame = rsSurface->RequestFrame(bufferWidth, bufferHeight, uiTimestamp_);
337 #else
338     auto surfaceFrame = rsSurface->RequestFrame(std::round(bufferWidth), std::round(bufferHeight), uiTimestamp_);
339 #endif
340     RS_TRACE_END();
341     if (surfaceFrame == nullptr) {
342         ROSEN_LOGI("ProcessRoot %s: Request Frame Failed", ptr->GetName().c_str());
343 #ifdef ROSEN_OHOS
344         FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
345 #endif
346         return;
347     }
348 
349     auto skSurface = surfaceFrame->GetSurface();
350     if (skSurface == nullptr) {
351         ROSEN_LOGE("skSurface null.");
352         return;
353     }
354     if (skSurface->getCanvas() == nullptr) {
355         ROSEN_LOGE("skSurface.getCanvas is null.");
356         return;
357     }
358 
359 #ifdef ROSEN_OHOS
360     // if listenedCanvas is nullptr, that means disabled or listen failed
361     std::shared_ptr<RSListenedCanvas> listenedCanvas = nullptr;
362     std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
363 
364     if (RSOverdrawController::GetInstance().IsEnabled()) {
365         auto &oc = RSOverdrawController::GetInstance();
366         listenedCanvas = std::make_shared<RSListenedCanvas>(skSurface.get());
367         overdrawListener = oc.CreateListener<RSGPUOverdrawCanvasListener>(listenedCanvas.get());
368         if (overdrawListener == nullptr) {
369             overdrawListener = oc.CreateListener<RSCPUOverdrawCanvasListener>(listenedCanvas.get());
370         }
371 
372         if (overdrawListener != nullptr) {
373             listenedCanvas->SetListener(overdrawListener);
374         } else {
375             // create listener failed
376             listenedCanvas = nullptr;
377         }
378     }
379 
380     if (listenedCanvas != nullptr) {
381         canvas_ = listenedCanvas;
382     } else {
383         canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
384     }
385 #else
386     canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
387 #endif
388 
389     canvas_->SetHighContrast(RSRenderThread::Instance().isHighContrastEnabled());
390 
391     // node's surface size already check, so here we do not need to check return
392     // attention: currently surfaceW/H are float values transformed into int implicitly
393     (void)curDirtyManager_->SetSurfaceSize(bufferWidth, bufferHeight);
394     // keep non-negative rect region within surface
395     curDirtyManager_->ClipDirtyRectWithinSurface();
396     // reset matrix
397     const float rootWidth = property.GetFrameWidth() * property.GetScaleX();
398     const float rootHeight = property.GetFrameHeight() * property.GetScaleY();
399     SkMatrix gravityMatrix;
400     (void)RSPropertiesPainter::GetGravityMatrix(
401         Gravity::RESIZE, RectF { 0.0f, 0.0f, bufferWidth, bufferHeight }, rootWidth, rootHeight, gravityMatrix);
402 
403     if (isRenderForced_ ||
404         curDirtyManager_->GetDirtyRegion().GetWidth() == 0 ||
405         curDirtyManager_->GetDirtyRegion().GetHeight() == 0 ||
406         !gravityMatrix.isIdentity()) {
407         curDirtyManager_->ResetDirtyAsSurfaceSize();
408     }
409     UpdateDirtyAndSetEGLDamageRegion(surfaceFrame);
410 
411     canvas_->clipRect(SkRect::MakeWH(bufferWidth, bufferHeight));
412     canvas_->clear(SK_ColorTRANSPARENT);
413     isIdle_ = false;
414 
415     // clear current children before traversal, we will re-add them again during traversal
416     childSurfaceNodeIds_.clear();
417 
418     canvas_->concat(gravityMatrix);
419     parentSurfaceNodeMatrix_ = gravityMatrix;
420 
421     RS_TRACE_BEGIN("ProcessRenderNodes");
422     needUpdateSurfaceNode_ = node.GetNeedUpdateSurfaceNode();
423     ProcessCanvasRenderNode(node);
424 
425     if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_ || needUpdateSurfaceNode_) {
426         auto thisSurfaceNodeId = node.GetRSSurfaceNodeId();
427         std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearSurfaceNodeChild>(thisSurfaceNodeId);
428         SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
429         for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
430             command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
431             SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
432         }
433         node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
434     }
435     needUpdateSurfaceNode_ = false;
436     node.SetNeedUpdateSurfaceNode(false);
437     RS_TRACE_END();
438 
439     auto transactionProxy = RSTransactionProxy::GetInstance();
440     if (transactionProxy != nullptr) {
441         ROSEN_LOGD("RSRenderThreadVisitor FlushImplicitTransactionFromRT uiTimestamp = %" PRIu64, uiTimestamp_);
442         transactionProxy->FlushImplicitTransactionFromRT(uiTimestamp_);
443     }
444 
445     if (curDirtyManager_->IsDirty() && curDirtyManager_->IsDebugEnabled()) {
446         ROSEN_LOGD("ProcessRootRenderNode %s [%" PRIu64 "] draw dirtyRect", ptr->GetName().c_str(), node.GetId());
447         DrawDirtyRegion();
448     }
449 
450 #ifdef ROSEN_OHOS
451     if (overdrawListener != nullptr) {
452         overdrawListener->Draw();
453     }
454 
455     FramePainter fpainter(FrameCollector::GetInstance());
456     fpainter.Draw(*canvas_);
457     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
458     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushStart);
459 #endif
460 
461     RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->FlushFrame");
462     ROSEN_LOGD("RSRenderThreadVisitor FlushFrame surfaceNodeId = %" PRIu64 ", uiTimestamp = %" PRIu64,
463         node.GetRSSurfaceNodeId(), uiTimestamp_);
464     rsSurface->FlushFrame(surfaceFrame, uiTimestamp_);
465 #ifdef ROSEN_OHOS
466     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushEnd);
467 #endif
468     RS_TRACE_END();
469 
470     canvas_ = nullptr;
471     isIdle_ = true;
472 }
473 
ProcessCanvasRenderNode(RSCanvasRenderNode & node)474 void RSRenderThreadVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node)
475 {
476     if (!node.ShouldPaint()) {
477         return;
478     }
479     if (!canvas_) {
480         ROSEN_LOGE("RSRenderThreadVisitor::ProcessCanvasRenderNode, canvas is nullptr");
481         return;
482     }
483     node.UpdateRenderStatus(curDirtyRegion_, isOpDropped_);
484     if (node.IsRenderUpdateIgnored()) {
485         return;
486     }
487     node.ProcessRenderBeforeChildren(*canvas_);
488     ProcessBaseRenderNode(node);
489     node.ProcessRenderAfterChildren(*canvas_);
490 }
491 
getLocalClipBounds(RSPaintFilterCanvas * canvas)492 static SkRect getLocalClipBounds(RSPaintFilterCanvas* canvas)
493 {
494     SkIRect ibounds = canvas->getDeviceClipBounds();
495     if (ibounds.isEmpty()) {
496         return SkRect::MakeEmpty();
497     }
498 
499     SkMatrix inverse;
500     // if we can't invert the CTM, we can't return local clip bounds
501     if (!(canvas->getTotalMatrix().invert(&inverse))) {
502         return SkRect::MakeEmpty();
503     }
504     SkRect bounds;
505     SkRect r = SkRect::Make(ibounds);
506     inverse.mapRect(&bounds, r);
507     return bounds;
508 }
509 
ProcessSurfaceRenderNode(RSSurfaceRenderNode & node)510 void RSRenderThreadVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
511 {
512     if (!canvas_) {
513         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
514         return;
515     }
516     if (!node.ShouldPaint()) {
517         ROSEN_LOGI("RSRenderThreadVisitor::ProcessSurfaceRenderNode node : %" PRIu64 " is invisible", node.GetId());
518         node.SetContextAlpha(0.0f);
519         return;
520     }
521     // RSSurfaceRenderNode in RSRenderThreadVisitor do not have information of property.
522     // We only get parent's matrix and send it to RenderService
523     SkMatrix invertMatrix;
524     SkMatrix contextMatrix = canvas_->getTotalMatrix();
525 
526     if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
527         contextMatrix.preConcat(invertMatrix);
528     } else {
529         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, invertMatrix failed");
530     }
531     node.SetContextMatrix(contextMatrix);
532     node.SetContextAlpha(canvas_->GetAlpha());
533 
534     // PLANNING: This is a temporary modification. Animation for surfaceView should not be triggered in RenderService.
535     // We plan to refactor code here.
536     node.SetContextBounds(node.GetRenderProperties().GetBounds());
537 
538     auto clipRect = getLocalClipBounds(canvas_.get());
539     if (clipRect.width() < std::numeric_limits<float>::epsilon() ||
540         clipRect.height() < std::numeric_limits<float>::epsilon()) {
541         // if clipRect is empty, this node will be removed from parent's children list.
542         return;
543     }
544     node.SetContextClipRegion(clipRect);
545 
546     // clip hole
547     ClipHoleForSurfaceNode(node);
548 
549     // 1. add this node to parent's children list
550     childSurfaceNodeIds_.emplace_back(node.GetId());
551 
552     // 2. backup and reset environment variables before traversal children
553     std::vector<NodeId> siblingSurfaceNodeIds(std::move(childSurfaceNodeIds_));
554     childSurfaceNodeIds_.clear();
555     auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
556     parentSurfaceNodeMatrix_ = canvas_->getTotalMatrix();
557 
558     // 3. traversal children, child surface node will be added to childSurfaceNodeIds_
559     // note: apply current node properties onto canvas if there is any child node
560     ProcessBaseRenderNode(node);
561 
562     // 4. if children changed, sync children to RenderService
563     if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_ || needUpdateSurfaceNode_) {
564         auto thisSurfaceNodeId = node.GetId();
565         std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearSurfaceNodeChild>(thisSurfaceNodeId);
566         SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
567         for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
568             command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
569             SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
570         }
571         node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
572     }
573 
574     // 5. restore environments variables before continue traversal siblings
575     childSurfaceNodeIds_ = std::move(siblingSurfaceNodeIds);
576     parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
577 }
578 
ProcessProxyRenderNode(RSProxyRenderNode & node)579 void RSRenderThreadVisitor::ProcessProxyRenderNode(RSProxyRenderNode& node)
580 {
581     if (!canvas_) {
582         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, canvas is nullptr");
583         return;
584     }
585     // RSProxyRenderNode in RSRenderThreadVisitor do not have information of property.
586     // We only get parent's matrix and send it to RenderService
587 #ifdef ROSEN_OHOS
588     SkMatrix invertMatrix;
589     SkMatrix contextMatrix = canvas_->getTotalMatrix();
590 
591     if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
592         contextMatrix.preConcat(invertMatrix);
593     } else {
594         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, invertMatrix failed");
595     }
596     node.SetContextMatrix(contextMatrix);
597     node.SetContextAlpha(canvas_->GetAlpha());
598 
599     // for proxied nodes (i.e. remote window components), we only extract matrix & alpha, do not change their hierarchy
600     // or clip or other properties.
601     node.ResetSortedChildren();
602 #endif
603 }
604 
ClipHoleForSurfaceNode(RSSurfaceRenderNode & node)605 void RSRenderThreadVisitor::ClipHoleForSurfaceNode(RSSurfaceRenderNode& node)
606 {
607     // Calculation position in RenderService may appear floating point number, and it will be removed.
608     // It caused missed line problem on surfaceview hap, so we subtract one pixel when cliphole to avoid this problem
609     static int pixel = 1;
610     auto x = std::ceil(node.GetRenderProperties().GetBoundsPositionX() + pixel); // x increase 1 pixel
611     auto y = std::ceil(node.GetRenderProperties().GetBoundsPositionY() + pixel); // y increase 1 pixel
612     auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
613     auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
614     canvas_->save();
615     SkRect originRect = SkRect::MakeXYWH(x, y, width, height);
616     canvas_->clipRect(originRect);
617     if (node.IsNotifyRTBufferAvailable()) {
618         ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", clip [%f, %f, %f, %f]",
619             node.GetId(), x, y, width, height);
620         canvas_->clear(SK_ColorTRANSPARENT);
621     } else {
622         ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", not clip [%f, %f, %f, %f]",
623             node.GetId(), x, y, width, height);
624         auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
625         if (backgroundColor != RgbPalette::Transparent()) {
626             canvas_->clear(backgroundColor.AsArgbInt());
627         }
628     }
629     canvas_->restore();
630 }
631 
SendCommandFromRT(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)632 void RSRenderThreadVisitor::SendCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
633 {
634     auto transactionProxy = RSTransactionProxy::GetInstance();
635     if (transactionProxy != nullptr) {
636         transactionProxy->AddCommandFromRT(command, nodeId, followType);
637     }
638 }
639 } // namespace Rosen
640 } // namespace OHOS
641