• 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     auto surfaceFrame = rsSurface->RequestFrame(bufferWidth, bufferHeight, uiTimestamp_);
336     RS_TRACE_END();
337     if (surfaceFrame == nullptr) {
338         ROSEN_LOGI("ProcessRoot %s: Request Frame Failed", ptr->GetName().c_str());
339 #ifdef ROSEN_OHOS
340         FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
341 #endif
342         return;
343     }
344 
345     auto skSurface = surfaceFrame->GetSurface();
346     if (skSurface == nullptr) {
347         ROSEN_LOGE("skSurface null.");
348         return;
349     }
350     if (skSurface->getCanvas() == nullptr) {
351         ROSEN_LOGE("skSurface.getCanvas is null.");
352         return;
353     }
354 
355 #ifdef ROSEN_OHOS
356     // if listenedCanvas is nullptr, that means disabled or listen failed
357     std::shared_ptr<RSListenedCanvas> listenedCanvas = nullptr;
358     std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
359 
360     if (RSOverdrawController::GetInstance().IsEnabled()) {
361         auto &oc = RSOverdrawController::GetInstance();
362         listenedCanvas = std::make_shared<RSListenedCanvas>(skSurface.get());
363         overdrawListener = oc.CreateListener<RSGPUOverdrawCanvasListener>(listenedCanvas.get());
364         if (overdrawListener == nullptr) {
365             overdrawListener = oc.CreateListener<RSCPUOverdrawCanvasListener>(listenedCanvas.get());
366         }
367 
368         if (overdrawListener != nullptr) {
369             listenedCanvas->SetListener(overdrawListener);
370         } else {
371             // create listener failed
372             listenedCanvas = nullptr;
373         }
374     }
375 
376     if (listenedCanvas != nullptr) {
377         canvas_ = listenedCanvas;
378     } else {
379         canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
380     }
381 #else
382     canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
383 #endif
384 
385     canvas_->SetHighContrast(RSRenderThread::Instance().isHighContrastEnabled());
386 
387     // node's surface size already check, so here we do not need to check return
388     // attention: currently surfaceW/H are float values transformed into int implicitly
389     (void)curDirtyManager_->SetSurfaceSize(bufferWidth, bufferHeight);
390     // keep non-negative rect region within surface
391     curDirtyManager_->ClipDirtyRectWithinSurface();
392     // reset matrix
393     const float rootWidth = property.GetFrameWidth() * property.GetScaleX();
394     const float rootHeight = property.GetFrameHeight() * property.GetScaleY();
395     SkMatrix gravityMatrix;
396     (void)RSPropertiesPainter::GetGravityMatrix(
397         Gravity::RESIZE, RectF { 0.0f, 0.0f, bufferWidth, bufferHeight }, rootWidth, rootHeight, gravityMatrix);
398 
399     if (isRenderForced_ ||
400         curDirtyManager_->GetDirtyRegion().GetWidth() == 0 ||
401         curDirtyManager_->GetDirtyRegion().GetHeight() == 0 ||
402         !gravityMatrix.isIdentity()) {
403         curDirtyManager_->ResetDirtyAsSurfaceSize();
404     }
405     UpdateDirtyAndSetEGLDamageRegion(surfaceFrame);
406 
407     canvas_->clipRect(SkRect::MakeWH(bufferWidth, bufferHeight));
408     canvas_->clear(SK_ColorTRANSPARENT);
409     isIdle_ = false;
410 
411     // clear current children before traversal, we will re-add them again during traversal
412     childSurfaceNodeIds_.clear();
413 
414     canvas_->concat(gravityMatrix);
415     parentSurfaceNodeMatrix_ = gravityMatrix;
416 
417     RS_TRACE_BEGIN("ProcessRenderNodes");
418     needUpdateSurfaceNode_ = node.GetNeedUpdateSurfaceNode();
419     ProcessCanvasRenderNode(node);
420 
421     if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_ || needUpdateSurfaceNode_) {
422         auto thisSurfaceNodeId = node.GetRSSurfaceNodeId();
423         std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearSurfaceNodeChild>(thisSurfaceNodeId);
424         SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
425         for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
426             command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
427             SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
428         }
429         node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
430     }
431     needUpdateSurfaceNode_ = false;
432     node.SetNeedUpdateSurfaceNode(false);
433     RS_TRACE_END();
434 
435     auto transactionProxy = RSTransactionProxy::GetInstance();
436     if (transactionProxy != nullptr) {
437         ROSEN_LOGD("RSRenderThreadVisitor FlushImplicitTransactionFromRT uiTimestamp = %" PRIu64, uiTimestamp_);
438         transactionProxy->FlushImplicitTransactionFromRT(uiTimestamp_);
439     }
440 
441     if (curDirtyManager_->IsDirty() && curDirtyManager_->IsDebugEnabled()) {
442         ROSEN_LOGD("ProcessRootRenderNode %s [%" PRIu64 "] draw dirtyRect", ptr->GetName().c_str(), node.GetId());
443         DrawDirtyRegion();
444     }
445 
446 #ifdef ROSEN_OHOS
447     if (overdrawListener != nullptr) {
448         overdrawListener->Draw();
449     }
450 
451     FramePainter fpainter(FrameCollector::GetInstance());
452     fpainter.Draw(*canvas_);
453     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::ReleaseEnd);
454     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushStart);
455 #endif
456 
457     RS_TRACE_BEGIN(ptr->GetName() + " rsSurface->FlushFrame");
458     ROSEN_LOGD("RSRenderThreadVisitor FlushFrame surfaceNodeId = %" PRIu64 ", uiTimestamp = %" PRIu64,
459         node.GetRSSurfaceNodeId(), uiTimestamp_);
460     rsSurface->FlushFrame(surfaceFrame, uiTimestamp_);
461 #ifdef ROSEN_OHOS
462     FrameCollector::GetInstance().MarkFrameEvent(FrameEventType::FlushEnd);
463 #endif
464     RS_TRACE_END();
465 
466     canvas_ = nullptr;
467     isIdle_ = true;
468 }
469 
ProcessCanvasRenderNode(RSCanvasRenderNode & node)470 void RSRenderThreadVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node)
471 {
472     if (!node.ShouldPaint()) {
473         return;
474     }
475     if (!canvas_) {
476         ROSEN_LOGE("RSRenderThreadVisitor::ProcessCanvasRenderNode, canvas is nullptr");
477         return;
478     }
479     node.UpdateRenderStatus(curDirtyRegion_, isOpDropped_);
480     if (node.IsRenderUpdateIgnored()) {
481         return;
482     }
483     node.ProcessRenderBeforeChildren(*canvas_);
484     ProcessBaseRenderNode(node);
485     node.ProcessRenderAfterChildren(*canvas_);
486 }
487 
getLocalClipBounds(RSPaintFilterCanvas * canvas)488 static SkRect getLocalClipBounds(RSPaintFilterCanvas* canvas)
489 {
490     SkIRect ibounds = canvas->getDeviceClipBounds();
491     if (ibounds.isEmpty()) {
492         return SkRect::MakeEmpty();
493     }
494 
495     SkMatrix inverse;
496     // if we can't invert the CTM, we can't return local clip bounds
497     if (!(canvas->getTotalMatrix().invert(&inverse))) {
498         return SkRect::MakeEmpty();
499     }
500     SkRect bounds;
501     SkRect r = SkRect::Make(ibounds);
502     inverse.mapRect(&bounds, r);
503     return bounds;
504 }
505 
ProcessSurfaceRenderNode(RSSurfaceRenderNode & node)506 void RSRenderThreadVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
507 {
508     if (!canvas_) {
509         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
510         return;
511     }
512     if (!node.ShouldPaint()) {
513         ROSEN_LOGI("RSRenderThreadVisitor::ProcessSurfaceRenderNode node : %" PRIu64 " is invisible", node.GetId());
514         node.SetContextAlpha(0.0f);
515         return;
516     }
517     // RSSurfaceRenderNode in RSRenderThreadVisitor do not have information of property.
518     // We only get parent's matrix and send it to RenderService
519     SkMatrix invertMatrix;
520     SkMatrix contextMatrix = canvas_->getTotalMatrix();
521 
522     if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
523         contextMatrix.preConcat(invertMatrix);
524     } else {
525         ROSEN_LOGE("RSRenderThreadVisitor::ProcessSurfaceRenderNode, invertMatrix failed");
526     }
527     node.SetContextMatrix(contextMatrix);
528     node.SetContextAlpha(canvas_->GetAlpha());
529 
530     // PLANNING: This is a temporary modification. Animation for surfaceView should not be triggered in RenderService.
531     // We plan to refactor code here.
532     node.SetContextBounds(node.GetRenderProperties().GetBounds());
533 
534     auto clipRect = getLocalClipBounds(canvas_.get());
535     if (clipRect.width() < std::numeric_limits<float>::epsilon() ||
536         clipRect.height() < std::numeric_limits<float>::epsilon()) {
537         // if clipRect is empty, this node will be removed from parent's children list.
538         return;
539     }
540     node.SetContextClipRegion(clipRect);
541 
542     // clip hole
543     ClipHoleForSurfaceNode(node);
544 
545     // 1. add this node to parent's children list
546     childSurfaceNodeIds_.emplace_back(node.GetId());
547 
548     // 2. backup and reset environment variables before traversal children
549     std::vector<NodeId> siblingSurfaceNodeIds(std::move(childSurfaceNodeIds_));
550     childSurfaceNodeIds_.clear();
551     auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
552     parentSurfaceNodeMatrix_ = canvas_->getTotalMatrix();
553 
554     // 3. traversal children, child surface node will be added to childSurfaceNodeIds_
555     // note: apply current node properties onto canvas if there is any child node
556     ProcessBaseRenderNode(node);
557 
558     // 4. if children changed, sync children to RenderService
559     if (childSurfaceNodeIds_ != node.childSurfaceNodeIds_ || needUpdateSurfaceNode_) {
560         auto thisSurfaceNodeId = node.GetId();
561         std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearSurfaceNodeChild>(thisSurfaceNodeId);
562         SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
563         for (const auto& childSurfaceNodeId : childSurfaceNodeIds_) {
564             command = std::make_unique<RSBaseNodeAddChild>(thisSurfaceNodeId, childSurfaceNodeId, -1);
565             SendCommandFromRT(command, thisSurfaceNodeId, FollowType::FOLLOW_VISITOR);
566         }
567         node.childSurfaceNodeIds_ = std::move(childSurfaceNodeIds_);
568     }
569 
570     // 5. restore environments variables before continue traversal siblings
571     childSurfaceNodeIds_ = std::move(siblingSurfaceNodeIds);
572     parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
573 }
574 
ProcessProxyRenderNode(RSProxyRenderNode & node)575 void RSRenderThreadVisitor::ProcessProxyRenderNode(RSProxyRenderNode& node)
576 {
577     if (!canvas_) {
578         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, canvas is nullptr");
579         return;
580     }
581     // RSProxyRenderNode in RSRenderThreadVisitor do not have information of property.
582     // We only get parent's matrix and send it to RenderService
583 #ifdef ROSEN_OHOS
584     SkMatrix invertMatrix;
585     SkMatrix contextMatrix = canvas_->getTotalMatrix();
586 
587     if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
588         contextMatrix.preConcat(invertMatrix);
589     } else {
590         ROSEN_LOGE("RSRenderThreadVisitor::ProcessProxyRenderNode, invertMatrix failed");
591     }
592     node.SetContextMatrix(contextMatrix);
593     node.SetContextAlpha(canvas_->GetAlpha());
594 
595     // for proxied nodes (i.e. remote window components), we only extract matrix & alpha, do not change their hierarchy
596     // or clip or other properties.
597     node.ResetSortedChildren();
598 #endif
599 }
600 
ClipHoleForSurfaceNode(RSSurfaceRenderNode & node)601 void RSRenderThreadVisitor::ClipHoleForSurfaceNode(RSSurfaceRenderNode& node)
602 {
603     // Calculation position in RenderService may appear floating point number, and it will be removed.
604     // It caused missed line problem on surfaceview hap, so we subtract one pixel when cliphole to avoid this problem
605     static int pixel = 1;
606     auto x = std::ceil(node.GetRenderProperties().GetBoundsPositionX() + pixel); // x increase 1 pixel
607     auto y = std::ceil(node.GetRenderProperties().GetBoundsPositionY() + pixel); // y increase 1 pixel
608     auto width = std::floor(node.GetRenderProperties().GetBoundsWidth() - (2 * pixel)); // width decrease 2 pixels
609     auto height = std::floor(node.GetRenderProperties().GetBoundsHeight() - (2 * pixel)); // height decrease 2 pixels
610     canvas_->save();
611     SkRect originRect = SkRect::MakeXYWH(x, y, width, height);
612     canvas_->clipRect(originRect);
613     if (node.IsNotifyRTBufferAvailable()) {
614         ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", clip [%f, %f, %f, %f]",
615             node.GetId(), x, y, width, height);
616         canvas_->clear(SK_ColorTRANSPARENT);
617     } else {
618         ROSEN_LOGD("RSRenderThreadVisitor::ClipHoleForSurfaceNode node : %" PRIu64 ", not clip [%f, %f, %f, %f]",
619             node.GetId(), x, y, width, height);
620         auto backgroundColor = node.GetRenderProperties().GetBackgroundColor();
621         if (backgroundColor != RgbPalette::Transparent()) {
622             canvas_->clear(backgroundColor.AsArgbInt());
623         }
624     }
625     canvas_->restore();
626 }
627 
SendCommandFromRT(std::unique_ptr<RSCommand> & command,NodeId nodeId,FollowType followType)628 void RSRenderThreadVisitor::SendCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId, FollowType followType)
629 {
630     auto transactionProxy = RSTransactionProxy::GetInstance();
631     if (transactionProxy != nullptr) {
632         transactionProxy->AddCommandFromRT(command, nodeId, followType);
633     }
634 }
635 } // namespace Rosen
636 } // namespace OHOS
637