1 /*
2 * Copyright (c) 2022 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_uni_render_visitor.h"
17
18 #include "include/core/SkRegion.h"
19 #include "include/core/SkTextBlob.h"
20 #include "rs_trace.h"
21
22 #include "common/rs_common_def.h"
23 #include "common/rs_obj_abs_geometry.h"
24 #include "pipeline/rs_base_render_node.h"
25 #include "pipeline/rs_base_render_util.h"
26 #include "pipeline/rs_cold_start_thread.h"
27 #include "pipeline/rs_display_render_node.h"
28 #include "pipeline/rs_main_thread.h"
29 #include "pipeline/rs_paint_filter_canvas.h"
30 #include "pipeline/rs_processor_factory.h"
31 #include "pipeline/rs_proxy_render_node.h"
32 #include "pipeline/rs_recording_canvas.h"
33 #include "pipeline/rs_root_render_node.h"
34 #include "pipeline/rs_surface_render_node.h"
35 #include "pipeline/rs_uni_render_listener.h"
36 #include "pipeline/rs_uni_render_mirror_processor.h"
37 #include "pipeline/rs_uni_render_util.h"
38 #include "platform/common/rs_log.h"
39 #include "platform/common/rs_system_properties.h"
40 #include "property/rs_properties_painter.h"
41 #include "render/rs_skia_filter.h"
42
43 namespace OHOS {
44 namespace Rosen {
45 namespace {
46 constexpr uint32_t USE_CACHE_SURFACE_NUM = 7;
47
IsFirstFrameReadyToDraw(RSSurfaceRenderNode & node)48 bool IsFirstFrameReadyToDraw(RSSurfaceRenderNode& node)
49 {
50 for (auto& child : node.GetSortedChildren()) {
51 if (child != nullptr && child->IsInstanceOf<RSRootRenderNode>()) {
52 auto rootNode = child->ReinterpretCastTo<RSRootRenderNode>();
53 const auto& property = rootNode->GetRenderProperties();
54 if (property.GetFrameWidth() > 0 && property.GetFrameHeight() > 0 && rootNode->GetEnableRender()) {
55 return true;
56 }
57 }
58 }
59 return false;
60 }
61 }
RSUniRenderVisitor()62 RSUniRenderVisitor::RSUniRenderVisitor()
63 : curSurfaceDirtyManager_(std::make_shared<RSDirtyRegionManager>())
64 {
65 auto mainThread = RSMainThread::Instance();
66 renderEngine_ = mainThread->GetRenderEngine();
67 partialRenderType_ = RSSystemProperties::GetUniPartialRenderEnabled();
68 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
69 auto screenNum = screenManager->GetAllScreenIds().size();
70 isOcclusionEnabled_ = RSSystemProperties::GetOcclusionEnabled();
71 isPartialRenderEnabled_ = (screenNum <= 1) && (partialRenderType_ != PartialRenderType::DISABLED);
72 isDirtyRegionDfxEnabled_ = (RSSystemProperties::GetDirtyRegionDebugType() == DirtyRegionDebugType::EGL_DAMAGE);
73 isTargetDirtyRegionDfxEnabled_ = RSSystemProperties::GetTargetDirtyRegionDfxEnabled(dfxTargetSurfaceNames_);
74 if (isDirtyRegionDfxEnabled_ && isTargetDirtyRegionDfxEnabled_) {
75 isDirtyRegionDfxEnabled_ = false;
76 }
77 isOpDropped_ = isPartialRenderEnabled_ && (partialRenderType_ != PartialRenderType::SET_DAMAGE)
78 && (!isDirtyRegionDfxEnabled_ && !isTargetDirtyRegionDfxEnabled_);
79 // this config may downgrade the calcOcclusion performance when windows number become huge (i.e. > 30), keep it now
80 containerWindowConfig_ = RSSystemProperties::GetContainerWindowConfig();
81 }
~RSUniRenderVisitor()82 RSUniRenderVisitor::~RSUniRenderVisitor() {}
83
PrepareBaseRenderNode(RSBaseRenderNode & node)84 void RSUniRenderVisitor::PrepareBaseRenderNode(RSBaseRenderNode& node)
85 {
86 node.ClearPaintOutOfParentRect();
87 node.UpdateChildrenOutOfRectFlag(false);
88 node.ResetSortedChildren();
89 for (auto& child : node.GetChildren()) {
90 if (auto renderChild = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(child.lock())) {
91 renderChild->ApplyModifiers();
92 }
93 }
94 const auto& children = node.GetSortedChildren();
95
96 // GetSortedChildren() may remove disappearingChildren_ when transition animation end.
97 // So the judgement whether node has removed child should be executed after this.
98 // merge last childRect as dirty if any child has been removed
99 if (curSurfaceDirtyManager_ && node.HasRemovedChild()) {
100 curSurfaceDirtyManager_->MergeDirtyRect(node.GetChildrenRect());
101 node.ResetHasRemovedChild();
102 }
103
104 // reset childRect before prepare children
105 node.ResetChildrenRect();
106 for (auto& child : children) {
107 child->Prepare(shared_from_this());
108 }
109 SetPaintOutOfParentFlag(node);
110 }
111
SetPaintOutOfParentFlag(RSBaseRenderNode & node)112 void RSUniRenderVisitor::SetPaintOutOfParentFlag(RSBaseRenderNode& node)
113 {
114 if (!isPartialRenderEnabled_) {
115 return;
116 }
117 if (node.GetType() != RSRenderNodeType::CANVAS_NODE && node.GetType() != RSRenderNodeType::SURFACE_NODE) {
118 RS_LOGD("Other types do not need to processed %d", node.GetType());
119 return;
120 }
121 auto nodeParent = node.GetParent().lock();
122 std::shared_ptr<RSRenderNode> rsParent = nullptr;
123 if (nodeParent == nullptr) {
124 return;
125 }
126 rsParent = nodeParent->ReinterpretCastTo<RSRenderNode>();
127 auto& property = node.shared_from_this()->ReinterpretCastTo<RSRenderNode>()->GetMutableRenderProperties();
128 auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(property.GetBoundsGeometry());
129 RectI rect;
130 if (geoPtr != nullptr) {
131 rect = geoPtr->GetAbsRect();
132 rect = rect.JoinRect(node.ReinterpretCastTo<RSRenderNode>()->GetOldDirty());
133 }
134 RectI parentRect;
135 auto& parentProperty = rsParent->GetMutableRenderProperties();
136 auto parentGeoPtr = std::static_pointer_cast<RSObjAbsGeometry>(parentProperty.GetBoundsGeometry());
137 if (parentGeoPtr != nullptr) {
138 parentRect = parentGeoPtr->GetAbsRect();
139 parentRect = parentRect.JoinRect(rsParent->GetOldDirty());
140 }
141 if (node.HasChildrenOutOfRect()) {
142 if (!node.GetPaintOutOfParentRect().IsInsideOf(parentRect) || parentRect.IsEmpty()) {
143 nodeParent->UpdateChildrenOutOfRectFlag(true);
144 nodeParent->UpdatePaintOutOfParentRect(node.GetPaintOutOfParentRect());
145 }
146 } else {
147 if (!rect.IsInsideOf(parentRect) || parentRect.IsEmpty()) {
148 nodeParent->UpdateChildrenOutOfRectFlag(true);
149 nodeParent->UpdatePaintOutOfParentRect(rect);
150 }
151 }
152 }
153
CheckColorSpace(RSSurfaceRenderNode & node)154 void RSUniRenderVisitor::CheckColorSpace(RSSurfaceRenderNode& node)
155 {
156 if (node.IsAppWindow()) {
157 auto surfaceNodeColorSpace = node.GetColorSpace();
158 if (surfaceNodeColorSpace != ColorGamut::COLOR_GAMUT_SRGB) {
159 ROSEN_LOGD("RSUniRenderVisitor::CheckColorSpace: node (%s) set new colorspace %d",
160 node.GetName().c_str(), surfaceNodeColorSpace);
161 if (std::find(colorGamutmodes_.begin(), colorGamutmodes_.end(),
162 static_cast<ScreenColorGamut>(surfaceNodeColorSpace)) != colorGamutmodes_.end()) {
163 newColorSpace_ = surfaceNodeColorSpace;
164 } else {
165 RS_LOGD("RSUniRenderVisitor::CheckColorSpace: colorSpace is not supported on current screen");
166 }
167 }
168 } else {
169 if (node.GetSortedChildren().size() > 0) {
170 auto surfaceNodePtr = node.GetSortedChildren().front()->ReinterpretCastTo<RSSurfaceRenderNode>();
171 if (!surfaceNodePtr) {
172 return;
173 }
174 CheckColorSpace(*surfaceNodePtr);
175 }
176 }
177 }
178
PrepareDisplayRenderNode(RSDisplayRenderNode & node)179 void RSUniRenderVisitor::PrepareDisplayRenderNode(RSDisplayRenderNode& node)
180 {
181 currentVisitDisplay_ = node.GetScreenId();
182 displayHasSecSurface_.emplace(currentVisitDisplay_, false);
183 dirtySurfaceNodeMap_.clear();
184
185 RS_TRACE_NAME("RSUniRender:PrepareDisplay " + std::to_string(currentVisitDisplay_));
186 curDisplayDirtyManager_ = node.GetDirtyManager();
187 curDisplayDirtyManager_->Clear();
188 curDisplayNode_ = node.shared_from_this()->ReinterpretCastTo<RSDisplayRenderNode>();
189
190 dirtyFlag_ = isDirty_;
191
192 node.ApplyModifiers();
193 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
194 if (!screenManager) {
195 RS_LOGE("RSUniRenderVisitor::PrepareDisplayRenderNode ScreenManager is nullptr");
196 return;
197 }
198 screenInfo_ = screenManager->QueryScreenInfo(node.GetScreenId());
199 screenManager->GetScreenSupportedColorGamuts(node.GetScreenId(), colorGamutmodes_);
200 for (auto& child : node.GetSortedChildren()) {
201 auto surfaceNodePtr = child->ReinterpretCastTo<RSSurfaceRenderNode>();
202 if (!surfaceNodePtr) {
203 RS_LOGE("RSUniRenderVisitor::PrepareDisplayRenderNode ReinterpretCastTo fail");
204 return;
205 }
206 CheckColorSpace(*surfaceNodePtr);
207 }
208 parentSurfaceNodeMatrix_ = SkMatrix::I();
209 auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(node.GetRenderProperties().GetBoundsGeometry());
210 if (geoPtr != nullptr) {
211 geoPtr->UpdateByMatrixFromSelf();
212 parentSurfaceNodeMatrix_ = geoPtr->GetAbsMatrix();
213 }
214 dirtyFlag_ = dirtyFlag_ || node.IsRotationChanged();
215 // when display is in rotation state, occlusion relationship will be ruined,
216 // hence partialrender quickreject should be disabled.
217 if(node.IsRotationChanged()) {
218 isOpDropped_ = false;
219 }
220 node.UpdateRotation();
221 curAlpha_ = node.GetRenderProperties().GetAlpha();
222 PrepareBaseRenderNode(node);
223 auto mirrorNode = node.GetMirrorSource().lock();
224 if (mirrorNode) {
225 mirroredDisplays_.insert(mirrorNode->GetScreenId());
226 }
227
228 node.GetCurAllSurfaces().clear();
229 node.CollectSurface(node.shared_from_this(), node.GetCurAllSurfaces(), true);
230 }
231
PrepareSurfaceRenderNode(RSSurfaceRenderNode & node)232 void RSUniRenderVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node)
233 {
234 if (node.GetSecurityLayer()) {
235 displayHasSecSurface_[currentVisitDisplay_] = true;
236 }
237 // avoid mouse error
238 if (node.GetName() == "pointer window") {
239 isOpDropped_ = false;
240 isPartialRenderEnabled_ = false;
241 }
242 node.CleanDstRectChanged();
243 node.ApplyModifiers();
244 bool dirtyFlag = dirtyFlag_;
245 bool isCustomizedDirtyRect = false;
246
247 // update geoptr with ContextMatrix
248 auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
249 auto& property = node.GetMutableRenderProperties();
250 auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(property.GetBoundsGeometry());
251 float alpha = curAlpha_;
252 curAlpha_ *= (property.GetAlpha() * node.GetContextAlpha());
253 node.SetGlobalAlpha(curAlpha_);
254
255 // prepare the surfaceRenderNode whose child is rootRenderNode
256 if (node.IsAppWindow() || node.GetSurfaceNodeType() == RSSurfaceNodeType::STARTING_WINDOW_NODE) {
257 curSurfaceDirtyManager_ = node.GetDirtyManager();
258 curSurfaceDirtyManager_->Clear();
259 curSurfaceDirtyManager_->SetSurfaceSize(screenInfo_.width, screenInfo_.height);
260 if (auto parentNode = node.GetParent().lock()) {
261 auto rsParent = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(parentNode);
262 dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, &(rsParent->GetRenderProperties()), dirtyFlag_);
263 } else {
264 dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, nullptr, dirtyFlag_);
265 }
266 geoPtr->ConcatMatrix(node.GetContextMatrix());
267 node.SetDstRect(geoPtr->GetAbsRect().IntersectRect(RectI(0, 0, screenInfo_.width, screenInfo_.height)));
268 curDisplayNode_->UpdateSurfaceNodePos(node.GetId(), node.GetOldDirtyInSurface());
269 if (node.IsAppWindow()) {
270 curSurfaceNode_ = node.ReinterpretCastTo<RSSurfaceRenderNode>();
271 boundsRect_ = SkRect::MakeWH(property.GetBoundsWidth(), property.GetBoundsHeight());
272 frameGravity_ = property.GetFrameGravity();
273 }
274 } else {
275 RSUniRenderUtil::UpdateRenderNodeDstRect(node, node.GetContextMatrix());
276 node.SetDstRect(geoPtr->GetAbsRect().IntersectRect(RectI(0, 0, screenInfo_.width, screenInfo_.height)));
277 if (node.GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE) {
278 curSurfaceDirtyManager_ = node.GetDirtyManager();
279 curSurfaceDirtyManager_->Clear();
280 curDisplayNode_->UpdateSurfaceNodePos(node.GetId(), node.GetDstRect());
281 }
282 if (node.GetBuffer() != nullptr) {
283 auto& surfaceHandler = static_cast<RSSurfaceHandler&>(node);
284 if (surfaceHandler.IsCurrentFrameBufferConsumed()) {
285 curSurfaceDirtyManager_->MergeDirtyRect(node.GetDstRect());
286 }
287 }
288 isCustomizedDirtyRect = true;
289 }
290 // [planning] Remove this after skia is upgraded, the clipRegion is supported
291 if (node.GetRenderProperties().NeedFilter() && !node.IsAppFreeze()) {
292 needFilter_ = true;
293 }
294 dirtyFlag_ = dirtyFlag_ || node.GetDstRectChanged();
295 parentSurfaceNodeMatrix_ = geoPtr->GetAbsMatrix();
296 node.ResetSurfaceOpaqueRegion(RectI(0, 0, screenInfo_.width, screenInfo_.height), geoPtr->GetAbsRect(),
297 containerWindowConfig_, node.IsFocusedWindow(currentFocusedPid_));
298
299 PrepareBaseRenderNode(node);
300 // [planning] apply dirty rect instead of customized rect
301 node.UpdateParentChildrenRect(node.GetParent().lock(), isCustomizedDirtyRect, node.GetDstRect());
302 // restore flags
303 parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
304 curAlpha_ = alpha;
305 dirtyFlag_ = dirtyFlag;
306 if (node.GetDstRectChanged() || (node.GetDirtyManager() && node.GetDirtyManager()->IsDirty())) {
307 dirtySurfaceNodeMap_.emplace(node.GetId(), node.ReinterpretCastTo<RSSurfaceRenderNode>());
308 }
309 }
310
PrepareProxyRenderNode(RSProxyRenderNode & node)311 void RSUniRenderVisitor::PrepareProxyRenderNode(RSProxyRenderNode& node)
312 {
313 auto rsParent = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(node.GetParent().lock());
314 if (rsParent == nullptr) {
315 return;
316 }
317 auto& property = rsParent->GetMutableRenderProperties();
318 auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(property.GetBoundsGeometry());
319 SkMatrix invertMatrix;
320 SkMatrix contextMatrix = geoPtr->GetAbsMatrix();
321
322 if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
323 contextMatrix.preConcat(invertMatrix);
324 } else {
325 ROSEN_LOGE("RSUniRenderVisitor::PrepareProxyRenderNode, invertMatrix failed");
326 }
327 node.SetContextMatrix(contextMatrix);
328 node.SetContextAlpha(curAlpha_);
329
330 PrepareBaseRenderNode(node);
331 }
332
PrepareRootRenderNode(RSRootRenderNode & node)333 void RSUniRenderVisitor::PrepareRootRenderNode(RSRootRenderNode& node)
334 {
335 node.ApplyModifiers();
336 bool dirtyFlag = dirtyFlag_;
337 float alpha = curAlpha_;
338 auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
339
340 auto rsParent = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(node.GetParent().lock());
341 const auto& property = node.GetRenderProperties();
342 bool geoDirty = property.IsGeoDirty();
343 auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(property.GetBoundsGeometry());
344
345 dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, rsParent ? &(rsParent->GetRenderProperties()) : nullptr,
346 dirtyFlag_);
347 curAlpha_ *= property.GetAlpha();
348 if (rsParent == curSurfaceNode_) {
349 const float rootWidth = property.GetFrameWidth() * property.GetScaleX();
350 const float rootHeight = property.GetFrameHeight() * property.GetScaleY();
351 SkMatrix gravityMatrix;
352 (void)RSPropertiesPainter::GetGravityMatrix(frameGravity_,
353 RectF { 0.0f, 0.0f, boundsRect_.width(), boundsRect_.height() }, rootWidth, rootHeight, gravityMatrix);
354 // Only Apply gravityMatrix when rootNode is dirty
355 if (geoPtr != nullptr && (dirtyFlag || geoDirty)) {
356 geoPtr->ConcatMatrix(gravityMatrix);
357 }
358 }
359
360 if (geoPtr != nullptr) {
361 parentSurfaceNodeMatrix_ = geoPtr->GetAbsMatrix();
362 }
363 PrepareBaseRenderNode(node);
364
365 parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
366 curAlpha_ = alpha;
367 dirtyFlag_ = dirtyFlag;
368 }
369
PrepareCanvasRenderNode(RSCanvasRenderNode & node)370 void RSUniRenderVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode &node)
371 {
372 node.ApplyModifiers();
373 bool dirtyFlag = dirtyFlag_;
374 auto nodeParent = node.GetParent().lock();
375 while (nodeParent && nodeParent->ReinterpretCastTo<RSSurfaceRenderNode>() &&
376 nodeParent->ReinterpretCastTo<RSSurfaceRenderNode>()->GetSurfaceNodeType() ==
377 RSSurfaceNodeType::SELF_DRAWING_NODE) {
378 nodeParent = nodeParent->GetParent().lock();
379 }
380 std::shared_ptr<RSRenderNode> rsParent = nullptr;
381 if (nodeParent != nullptr) {
382 rsParent = nodeParent->ReinterpretCastTo<RSRenderNode>();
383 }
384 dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, rsParent ? &(rsParent->GetRenderProperties()) : nullptr,
385 dirtyFlag_);
386 float alpha = curAlpha_;
387 curAlpha_ *= node.GetRenderProperties().GetAlpha();
388
389 PrepareBaseRenderNode(node);
390 // attention: accumulate direct parent's childrenRect
391 node.UpdateParentChildrenRect(node.GetParent().lock());
392
393 // [planning] Remove this after skia is upgraded, the clipRegion is supported
394 if (node.GetRenderProperties().NeedFilter() && curSurfaceNode_) {
395 if (!curSurfaceNode_->IsAppFreeze()) {
396 needFilter_ = true;
397 }
398 filterRects_[curSurfaceNode_->GetId()].push_back(node.GetOldDirtyInSurface());
399 }
400 curAlpha_ = alpha;
401 dirtyFlag_ = dirtyFlag;
402 }
403
DrawDirtyRectForDFX(const RectI & dirtyRect,const SkColor color,const SkPaint::Style fillType,float alpha)404 void RSUniRenderVisitor::DrawDirtyRectForDFX(const RectI& dirtyRect, const SkColor color,
405 const SkPaint::Style fillType, float alpha)
406 {
407 ROSEN_LOGD("DrawDirtyRectForDFX current dirtyRect = [%d, %d, %d, %d]", dirtyRect.left_, dirtyRect.top_,
408 dirtyRect.width_, dirtyRect.height_);
409 if (dirtyRect.width_ <= 0 || dirtyRect.height_ <= 0) {
410 ROSEN_LOGD("DrawDirtyRectForDFX dirty rect is invalid.");
411 return;
412 }
413 auto skRect = SkRect::MakeXYWH(dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
414 std::string position = std::to_string(dirtyRect.left_) + ',' + std::to_string(dirtyRect.top_) + ',' +
415 std::to_string(dirtyRect.width_) + ',' + std::to_string(dirtyRect.height_);
416 const int defaultEdgeWidth = 6;
417 const int defaultTextOffsetX = defaultEdgeWidth;
418 const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the skRect
419 SkPaint rectPaint;
420 // font size: 24
421 sk_sp<SkTextBlob> SkTextBlob = SkTextBlob::MakeFromString(position.c_str(), SkFont(nullptr, 24.0f, 1.0f, 0.0f));
422 rectPaint.setColor(color);
423 rectPaint.setAntiAlias(true);
424 rectPaint.setAlphaf(alpha);
425 rectPaint.setStyle(fillType);
426 rectPaint.setStrokeWidth(defaultEdgeWidth);
427 if (fillType == SkPaint::kFill_Style) {
428 rectPaint.setStrokeJoin(SkPaint::kRound_Join);
429 }
430 canvas_->drawRect(skRect, rectPaint);
431 canvas_->drawTextBlob(SkTextBlob, dirtyRect.left_ + defaultTextOffsetX,
432 dirtyRect.top_ + defaultTextOffsetY, SkPaint());
433 }
434
DrawDirtyRegionForDFX(std::vector<RectI> dirtyRects)435 void RSUniRenderVisitor::DrawDirtyRegionForDFX(std::vector<RectI> dirtyRects)
436 {
437 const float fillAlpha = 0.2;
438 for (const auto& subRect : dirtyRects) {
439 DrawDirtyRectForDFX(subRect, SK_ColorBLUE, SkPaint::kStroke_Style, fillAlpha);
440 }
441 }
442
DrawAllSurfaceDirtyRegionForDFX(RSDisplayRenderNode & node,const Occlusion::Region & region)443 void RSUniRenderVisitor::DrawAllSurfaceDirtyRegionForDFX(RSDisplayRenderNode& node, const Occlusion::Region& region)
444 {
445 RectI dirtySurfaceRect = node.GetDirtyManager()->GetDirtyRegion();
446 std::vector<Occlusion::Rect> visibleDirtyRects = region.GetRegionRects();
447 std::vector<RectI> rects;
448 rects.emplace_back(dirtySurfaceRect);
449 for (auto rect : visibleDirtyRects) {
450 rects.emplace_back(RectI(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_));
451 }
452 DrawDirtyRegionForDFX(rects);
453 }
454
DrawTargetSurfaceDirtyRegionForDFX(RSDisplayRenderNode & node)455 void RSUniRenderVisitor::DrawTargetSurfaceDirtyRegionForDFX(RSDisplayRenderNode& node)
456 {
457 for (auto it = node.GetCurAllSurfaces().rbegin(); it != node.GetCurAllSurfaces().rend(); ++it) {
458 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
459 if (surfaceNode == nullptr || !surfaceNode->IsAppWindow()) {
460 continue;
461 }
462 if (std::find(dfxTargetSurfaceNames_.begin(), dfxTargetSurfaceNames_.end(),
463 surfaceNode->GetName()) != dfxTargetSurfaceNames_.end()) {
464 auto visibleDirtyRegions = surfaceNode->GetVisibleDirtyRegion().GetRegionRects();
465 std::vector<RectI> rects;
466 for (auto rect : visibleDirtyRegions) {
467 rects.emplace_back(RectI(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_));
468 }
469 auto visibleRegions = surfaceNode->GetVisibleRegion().GetRegionRects();
470 auto displayDirtyRegion = node.GetDirtyManager()->GetDirtyRegion();
471 for (auto rect : visibleRegions) {
472 auto visibleRect = RectI(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
473 auto intersectRegion = displayDirtyRegion.IntersectRect(visibleRect);
474 rects.emplace_back(intersectRegion);
475 }
476 DrawDirtyRegionForDFX(rects);
477 }
478 }
479 }
480
ProcessBaseRenderNode(RSBaseRenderNode & node)481 void RSUniRenderVisitor::ProcessBaseRenderNode(RSBaseRenderNode& node)
482 {
483 for (auto& child : node.GetSortedChildren()) {
484 child->Process(shared_from_this());
485 }
486 // clear SortedChildren, it will be generated again in next frame
487 node.ResetSortedChildren();
488 }
489
ProcessDisplayRenderNode(RSDisplayRenderNode & node)490 void RSUniRenderVisitor::ProcessDisplayRenderNode(RSDisplayRenderNode& node)
491 {
492 RS_TRACE_NAME("ProcessDisplayRenderNode[" + std::to_string(node.GetScreenId()) + "]" +
493 node.GetDirtyManager()->GetDirtyRegion().ToString().c_str());
494 RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode node: %" PRIu64 ", child size:%u", node.GetId(),
495 node.GetChildrenCount());
496 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
497 if (!screenManager) {
498 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode ScreenManager is nullptr");
499 return;
500 }
501 screenInfo_ = screenManager->QueryScreenInfo(node.GetScreenId());
502 isSecurityDisplay_ = node.GetSecurityDisplay();
503 switch (screenInfo_.state) {
504 case ScreenState::PRODUCER_SURFACE_ENABLE:
505 node.SetCompositeType(RSDisplayRenderNode::CompositeType::UNI_RENDER_MIRROR_COMPOSITE);
506 break;
507 case ScreenState::HDI_OUTPUT_ENABLE:
508 node.SetCompositeType(node.IsForceSoftComposite() ?
509 RSDisplayRenderNode::CompositeType::SOFTWARE_COMPOSITE :
510 RSDisplayRenderNode::CompositeType::UNI_RENDER_COMPOSITE);
511 break;
512 default:
513 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode ScreenState unsupported");
514 return;
515 }
516 offsetX_ = node.GetDisplayOffsetX();
517 offsetY_ = node.GetDisplayOffsetY();
518 processor_ = RSProcessorFactory::CreateProcessor(node.GetCompositeType());
519 if (processor_ == nullptr) {
520 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: RSProcessor is null!");
521 return;
522 }
523 auto mirrorNode = node.GetMirrorSource().lock();
524 if (!processor_->Init(node, node.GetDisplayOffsetX(), node.GetDisplayOffsetY(),
525 mirrorNode ? mirrorNode->GetScreenId() : INVALID_SCREEN_ID)) {
526 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: processor init failed!");
527 return;
528 }
529 std::shared_ptr<RSBaseRenderNode> nodePtr = node.shared_from_this();
530 auto displayNodePtr = nodePtr->ReinterpretCastTo<RSDisplayRenderNode>();
531 if (!displayNodePtr) {
532 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode ReinterpretCastTo fail");
533 return;
534 }
535 if (!node.IsSurfaceCreated()) {
536 sptr<IBufferConsumerListener> listener = new RSUniRenderListener(displayNodePtr);
537 if (!node.CreateSurface(listener)) {
538 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode CreateSurface failed");
539 return;
540 }
541 }
542
543 if (mirrorNode) {
544 auto processor = std::static_pointer_cast<RSUniRenderMirrorProcessor>(processor_);
545 if (displayHasSecSurface_[mirrorNode->GetScreenId()] && mirrorNode->GetSecurityDisplay() != isSecurityDisplay_
546 && processor) {
547 canvas_ = processor->GetCanvas();
548 ProcessBaseRenderNode(*mirrorNode);
549 } else {
550 processor_->ProcessDisplaySurface(*mirrorNode);
551 }
552 } else {
553 #ifdef RS_ENABLE_EGLQUERYSURFACE
554 if (isPartialRenderEnabled_) {
555 curDisplayDirtyManager_->SetSurfaceSize(screenInfo_.width, screenInfo_.height);
556 CalcDirtyDisplayRegion(displayNodePtr);
557 CalcDirtyRegionForFilterNode(displayNodePtr);
558 displayNodePtr->ClearCurrentSurfacePos();
559 }
560 if (isOpDropped_ && dirtySurfaceNodeMap_.empty() && !curDisplayDirtyManager_->IsDirty()) {
561 RS_LOGD("DisplayNode skip");
562 return;
563 }
564 #endif
565 auto rsSurface = node.GetRSSurface();
566 if (rsSurface == nullptr) {
567 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode No RSSurface found");
568 return;
569 }
570 rsSurface->SetColorSpace(newColorSpace_);
571 // we should request a framebuffer whose size is equals to the physical screen size.
572 RS_TRACE_BEGIN("RSUniRender:RequestFrame");
573 auto renderFrame = renderEngine_->RequestFrame(std::static_pointer_cast<RSSurfaceOhos>(rsSurface),
574 RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo_, true));
575 RS_TRACE_END();
576 if (renderFrame == nullptr) {
577 RS_LOGE("RSUniRenderVisitor Request Frame Failed");
578 return;
579 }
580 std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
581 AddOverDrawListener(renderFrame, overdrawListener);
582
583 if (canvas_ == nullptr) {
584 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: failed to create canvas");
585 return;
586 }
587 int saveLayerCnt = 0;
588 SkRegion region;
589 Occlusion::Region dirtyRegionTest;
590 #ifdef RS_ENABLE_EGLQUERYSURFACE
591 // Get displayNode buffer age in order to merge visible dirty region for displayNode.
592 // And then set egl damage region to improve uni_render efficiency.
593 if (isPartialRenderEnabled_) {
594 // Early history buffer Merging will have impact on Overdraw display, so we need to
595 // set the full screen dirty to avoid this impact.
596 if (RSOverdrawController::GetInstance().IsEnabled()) {
597 node.GetDirtyManager()->ResetDirtyAsSurfaceSize();
598 }
599 int bufferAge = renderFrame->GetBufferAge();
600 RSUniRenderUtil::MergeDirtyHistory(displayNodePtr, bufferAge);
601 auto dirtyRegion = RSUniRenderUtil::MergeVisibleDirtyRegion(displayNodePtr);
602 dirtyRegionTest = dirtyRegion;
603 SetSurfaceGlobalDirtyRegion(displayNodePtr);
604 std::vector<RectI> rects = GetDirtyRects(dirtyRegion);
605 RectI rect = node.GetDirtyManager()->GetDirtyRegionFlipWithinSurface();
606 if (!rect.IsEmpty()) {
607 rects.emplace_back(rect);
608 }
609 auto disH = screenInfo_.GetRotatedHeight();
610 for (auto& r : rects) {
611 region.op(SkIRect::MakeXYWH(r.left_, disH - r.GetBottom(), r.width_, r.height_), SkRegion::kUnion_Op);
612 RS_LOGD("SetDamageRegion %s", r.ToString().c_str());
613 }
614 // SetDamageRegion and opDrop will be disabled for dirty region DFX visualization
615 if (!isDirtyRegionDfxEnabled_ && !isTargetDirtyRegionDfxEnabled_) {
616 renderFrame->SetDamageRegion(rects);
617 }
618 }
619 if (isOpDropped_) {
620 if (region.isEmpty()) {
621 // [planning] Remove this after frame buffer can cancel
622 canvas_->clipRect(SkRect::MakeEmpty());
623 } else if (region.isRect()) {
624 canvas_->clipRegion(region);
625 } else {
626 SkPath dirtyPath;
627 region.getBoundaryPath(&dirtyPath);
628 canvas_->clipPath(dirtyPath, true);
629 // [planning] Remove this after skia is upgraded, the clipRegion is supported
630 if (!needFilter_) {
631 saveLayerCnt = canvas_->saveLayer(SkRect::MakeWH(screenInfo_.width, screenInfo_.height), nullptr);
632 }
633 }
634 }
635 #endif
636 int saveCount = canvas_->save();
637 canvas_->SetHighContrast(renderEngine_->IsHighContrastEnabled());
638 RSPropertiesPainter::SetBgAntiAlias(true);
639 auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(node.GetRenderProperties().GetBoundsGeometry());
640 if (geoPtr != nullptr) {
641 canvas_->concat(geoPtr->GetMatrix());
642 // enable cache if screen rotation is not times of 90 degree
643 canvas_->SetCacheEnabled(geoPtr->IsNeedClientCompose());
644 }
645 canvas_->SetCacheEnabled(canvas_->isCacheEnabled() || node.GetCurAllSurfaces().size() > USE_CACHE_SURFACE_NUM);
646 if (canvas_->isCacheEnabled()) {
647 // we are doing rotation animation, try offscreen render if capable
648 PrepareOffscreenRender(node);
649 ProcessBaseRenderNode(node);
650 FinishOffscreenRender();
651 } else {
652 // render directly
653 ProcessBaseRenderNode(node);
654 }
655 canvas_->restoreToCount(saveCount);
656
657 if (saveLayerCnt > 0) {
658 RS_TRACE_NAME("RSUniRender:RestoreLayer");
659 canvas_->restoreToCount(saveLayerCnt);
660 }
661
662 if (overdrawListener != nullptr) {
663 overdrawListener->Draw();
664 }
665 // the following code makes DirtyRegion visible, enable this method by turning on the dirtyregiondebug property
666 if (isPartialRenderEnabled_) {
667 if (isDirtyRegionDfxEnabled_) {
668 DrawAllSurfaceDirtyRegionForDFX(node, dirtyRegionTest);
669 }
670 if (isTargetDirtyRegionDfxEnabled_) {
671 DrawTargetSurfaceDirtyRegionForDFX(node);
672 }
673 }
674 RS_TRACE_BEGIN("RSUniRender:FlushFrame");
675 renderFrame->Flush();
676 RS_TRACE_END();
677 RS_TRACE_BEGIN("RSUniRender:WaitUtilUniRenderFinished");
678 RSMainThread::Instance()->WaitUtilUniRenderFinished();
679 RS_TRACE_END();
680 processor_->ProcessDisplaySurface(node);
681 }
682 processor_->PostProcess();
683
684 // We should release DisplayNode's surface buffer after PostProcess(),
685 // since the buffer's releaseFence was set in PostProcess().
686 auto& surfaceHandler = static_cast<RSSurfaceHandler&>(node);
687 (void)RSUniRenderUtil::ReleaseBuffer(surfaceHandler);
688 RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode end");
689 }
690
AddOverDrawListener(std::unique_ptr<RSRenderFrame> & renderFrame,std::shared_ptr<RSCanvasListener> & overdrawListener)691 void RSUniRenderVisitor::AddOverDrawListener(std::unique_ptr<RSRenderFrame>& renderFrame,
692 std::shared_ptr<RSCanvasListener>& overdrawListener)
693 {
694 if (renderFrame->GetFrame() == nullptr) {
695 RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: RSSurfaceFrame is null");
696 return;
697 }
698 auto skSurface = renderFrame->GetFrame()->GetSurface();
699 if (skSurface == nullptr) {
700 RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: skSurface is null");
701 return;
702 }
703 if (skSurface->getCanvas() == nullptr) {
704 ROSEN_LOGE("skSurface.getCanvas is null.");
705 return;
706 }
707 // if listenedCanvas is nullptr, that means disabled or listen failed
708 std::shared_ptr<RSListenedCanvas> listenedCanvas = nullptr;
709
710 if (RSOverdrawController::GetInstance().IsEnabled()) {
711 auto &oc = RSOverdrawController::GetInstance();
712 listenedCanvas = std::make_shared<RSListenedCanvas>(skSurface.get());
713 overdrawListener = oc.CreateListener<RSGPUOverdrawCanvasListener>(listenedCanvas.get());
714 if (overdrawListener == nullptr) {
715 overdrawListener = oc.CreateListener<RSCPUOverdrawCanvasListener>(listenedCanvas.get());
716 }
717
718 if (overdrawListener != nullptr) {
719 listenedCanvas->SetListener(overdrawListener);
720 } else {
721 // create listener failed
722 listenedCanvas = nullptr;
723 }
724 }
725
726 if (listenedCanvas != nullptr) {
727 canvas_ = listenedCanvas;
728 } else {
729 canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
730 }
731 }
732
CalcDirtyDisplayRegion(std::shared_ptr<RSDisplayRenderNode> & node) const733 void RSUniRenderVisitor::CalcDirtyDisplayRegion(std::shared_ptr<RSDisplayRenderNode>& node) const
734 {
735 RS_TRACE_FUNC();
736 auto displayDirtyManager = node->GetDirtyManager();
737 for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
738 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
739 if (surfaceNode == nullptr) {
740 continue;
741 }
742 auto surfaceDirtyManager = surfaceNode->GetDirtyManager();
743 RectI surfaceDirtyRect = surfaceDirtyManager->GetDirtyRegion();
744 if (surfaceNode->IsTransparent()) {
745 // Handles the case of transparent surface, merge transparent dirty rect
746 RectI transparentDirtyRect = surfaceNode->GetDstRect().IntersectRect(surfaceDirtyRect);
747 if (!transparentDirtyRect.IsEmpty()) {
748 RS_LOGD("CalcDirtyDisplayRegion merge transparent dirty rect %s rect %s",
749 surfaceNode->GetName().c_str(), transparentDirtyRect.ToString().c_str());
750 displayDirtyManager->MergeDirtyRect(transparentDirtyRect);
751 }
752 }
753
754 if (surfaceNode->GetZorderChanged()) {
755 // Zorder changed case, merge surface dest Rect
756 RS_LOGD("CalcDirtyDisplayRegion merge GetZorderChanged %s rect %s", surfaceNode->GetName().c_str(),
757 surfaceNode->GetDstRect().ToString().c_str());
758 displayDirtyManager->MergeDirtyRect(surfaceNode->GetDstRect());
759 }
760
761 RectI lastFrameSurfacePos = node->GetLastFrameSurfacePos(surfaceNode->GetId());
762 RectI currentFrameSurfacePos = node->GetCurrentFrameSurfacePos(surfaceNode->GetId());
763 if (lastFrameSurfacePos != currentFrameSurfacePos) {
764 RS_LOGD("CalcDirtyDisplayRegion merge surface pos changed %s lastFrameRect %s currentFrameRect %s",
765 surfaceNode->GetName().c_str(), lastFrameSurfacePos.ToString().c_str(),
766 currentFrameSurfacePos.ToString().c_str());
767 if (!lastFrameSurfacePos.IsEmpty()) {
768 displayDirtyManager->MergeDirtyRect(lastFrameSurfacePos);
769 }
770 if (!currentFrameSurfacePos.IsEmpty()) {
771 displayDirtyManager->MergeDirtyRect(currentFrameSurfacePos);
772 }
773 }
774
775 bool isShadowDisappear = !surfaceNode->GetRenderProperties().IsShadowValid() && surfaceNode->IsShadowValidLastFrame();
776 if (surfaceNode->GetRenderProperties().IsShadowValid() || isShadowDisappear) {
777 RectI shadowDirtyRect = surfaceNode->GetOldDirtyInSurface().IntersectRect(surfaceDirtyRect);
778 RS_LOGD("CalcDirtyDisplayRegion merge ShadowValid %s rect %s",
779 surfaceNode->GetName().c_str(), surfaceNode->GetOldDirtyInSurface().ToString().c_str());
780 // There are two situation here:
781 // 1. SurfaceNode first has shadow or shadow radius is larger than the last frame,
782 // surfaceDirtyRect == surfaceNode->GetOldDirtyInSurface()
783 // 2. SurfaceNode remove shadow or shadow radius is smaller than the last frame,
784 // surfaceDirtyRect > surfaceNode->GetOldDirtyInSurface()
785 // So we should always merge surfaceDirtyRect here.
786 if (!shadowDirtyRect.IsEmpty()) {
787 displayDirtyManager->MergeDirtyRect(surfaceDirtyRect);
788 }
789 if (isShadowDisappear) {
790 surfaceNode->SetShadowValidLastFrame(false);
791 }
792 }
793 auto transparentRegion = surfaceNode->GetTransparentRegion();
794 Occlusion::Rect tmpRect = Occlusion::Rect { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
795 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() };
796 Occlusion::Region surfaceDirtyRegion { tmpRect };
797 Occlusion::Region transparentDirtyRegion = transparentRegion.And(surfaceDirtyRegion);
798 std::vector<Occlusion::Rect> rects = transparentDirtyRegion.GetRegionRects();
799 for (const auto& rect : rects) {
800 displayDirtyManager->MergeDirtyRect(RectI
801 { rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_ });
802 }
803 }
804 std::vector<RectI> surfaceChangedRects = node->GetSurfaceChangedRects();
805 for (auto& surfaceChangedRect : surfaceChangedRects) {
806 RS_LOGD("CalcDirtyDisplayRegion merge Surface closed %s", surfaceChangedRect.ToString().c_str());
807 if (!surfaceChangedRect.IsEmpty()) {
808 displayDirtyManager->MergeDirtyRect(surfaceChangedRect);
809 }
810 }
811 }
812
CalcDirtyRegionForFilterNode(std::shared_ptr<RSDisplayRenderNode> & node) const813 void RSUniRenderVisitor::CalcDirtyRegionForFilterNode(std::shared_ptr<RSDisplayRenderNode>& node) const
814 {
815 auto displayDirtyManager = node->GetDirtyManager();
816 RectI displayDirtyRect = displayDirtyManager ? displayDirtyManager->GetDirtyRegion() : RectI{0, 0, 0, 0};
817 for (auto it = node->GetCurAllSurfaces().begin(); it != node->GetCurAllSurfaces().end(); ++it) {
818 auto currentSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
819 if (currentSurfaceNode == nullptr) {
820 continue;
821 }
822 auto currentSurfaceDirtyManager = currentSurfaceNode->GetDirtyManager();
823 RectI currentSurfaceDirtyRect = currentSurfaceDirtyManager->GetDirtyRegion();
824 NodeId currentSurfaceNodeId = currentSurfaceNode->GetId();
825
826 // child node (component) has filter
827 if (filterRects_.find(currentSurfaceNodeId) != filterRects_.end()) {
828 auto rectVec = filterRects_.find(currentSurfaceNodeId)->second;
829 for (auto rectIt = rectVec.begin(); rectIt != rectVec.end(); ++rectIt) {
830 if (!displayDirtyRect.IntersectRect(*rectIt).IsEmpty()) {
831 if (currentSurfaceNode->IsTransparent()) {
832 displayDirtyManager->MergeDirtyRect(*rectIt);
833 }
834 currentSurfaceDirtyManager->MergeDirtyRect(*rectIt);
835 } else if (!currentSurfaceDirtyRect.IntersectRect(*rectIt).IsEmpty()) {
836 currentSurfaceDirtyManager->MergeDirtyRect(*rectIt);
837 }
838 }
839 }
840
841 // surfaceNode self has filter
842 if (currentSurfaceNode->GetRenderProperties().NeedFilter()) {
843 if (!displayDirtyRect.IntersectRect(currentSurfaceNode->GetOldDirtyInSurface()).IsEmpty() ||
844 !currentSurfaceDirtyRect.IntersectRect(currentSurfaceNode->GetOldDirtyInSurface()).IsEmpty()) {
845 currentSurfaceDirtyManager->MergeDirtyRect(currentSurfaceNode->GetOldDirtyInSurface());
846 }
847
848 if (currentSurfaceNode->IsTransparent()) {
849 for (auto iter = node->GetCurAllSurfaces().begin(); iter != node->GetCurAllSurfaces().end(); ++iter) {
850 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*iter);
851 if (surfaceNode == nullptr) {
852 continue;
853 }
854 if (!surfaceNode->GetDirtyManager()->GetDirtyRegion().IntersectRect(
855 currentSurfaceNode->GetOldDirtyInSurface()).IsEmpty()) {
856 currentSurfaceDirtyManager->MergeDirtyRect(currentSurfaceNode->GetOldDirtyInSurface());
857 displayDirtyManager->MergeDirtyRect(currentSurfaceNode->GetOldDirtyInSurface());
858 break;
859 }
860 }
861 }
862 }
863 }
864 }
865
SetSurfaceGlobalDirtyRegion(std::shared_ptr<RSDisplayRenderNode> & node)866 void RSUniRenderVisitor::SetSurfaceGlobalDirtyRegion(std::shared_ptr<RSDisplayRenderNode>& node)
867 {
868 RS_TRACE_FUNC();
869 for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
870 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
871 if (surfaceNode == nullptr || !surfaceNode->IsAppWindow()) {
872 continue;
873 }
874 // set display dirty region to surfaceNode
875 surfaceNode->SetGloblDirtyRegion(node->GetDirtyManager()->GetDirtyRegion());
876 }
877 Occlusion::Region curVisibleDirtyRegion;
878 for (auto it = node->GetCurAllSurfaces().begin(); it != node->GetCurAllSurfaces().end(); ++it) {
879 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
880 if (surfaceNode == nullptr || !surfaceNode->IsAppWindow()) {
881 continue;
882 }
883 // set display dirty region to surfaceNode
884 surfaceNode->SetDirtyRegionBelowCurrentLayer(curVisibleDirtyRegion);
885 auto visibleDirtyRegion = surfaceNode->GetVisibleDirtyRegion();
886 curVisibleDirtyRegion = curVisibleDirtyRegion.Or(visibleDirtyRegion);
887 }
888 }
889
890 #ifdef RS_ENABLE_EGLQUERYSURFACE
GetDirtyRects(const Occlusion::Region & region)891 std::vector<RectI> RSUniRenderVisitor::GetDirtyRects(const Occlusion::Region ®ion)
892 {
893 std::vector<Occlusion::Rect> rects = region.GetRegionRects();
894 std::vector<RectI> retRects;
895 for (const Occlusion::Rect& rect : rects) {
896 // origin transformation
897 retRects.emplace_back(RectI(rect.left_, screenInfo_.GetRotatedHeight() - rect.bottom_,
898 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
899 }
900 RS_LOGD("GetDirtyRects size %d %s", region.GetSize(), region.GetRegionInfo().c_str());
901 return retRects;
902 }
903 #endif
904
InitCacheSurface(RSSurfaceRenderNode & node,int width,int height)905 void RSUniRenderVisitor::InitCacheSurface(RSSurfaceRenderNode& node, int width, int height)
906 {
907 #if (defined RS_ENABLE_GL) && (defined RS_ENABLE_EGLIMAGE)
908 SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
909 node.SetCacheSurface(SkSurface::MakeRenderTarget(canvas_->getGrContext(), SkBudgeted::kYes, info));
910 #else
911 node.SetCacheSurface(SkSurface::MakeRasterN32Premul(width, height));
912 #endif
913 }
914
ProcessSurfaceRenderNode(RSSurfaceRenderNode & node)915 void RSUniRenderVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
916 {
917 RS_TRACE_NAME("RSUniRender::Process:[" + node.GetName() + "]" + node.GetDstRect().ToString());
918 RS_LOGD("RSUniRenderVisitor::ProcessSurfaceRenderNode node: %" PRIu64 ", child size:%u %s", node.GetId(),
919 node.GetChildrenCount(), node.GetName().c_str());
920 node.UpdatePositionZ();
921 if (isSecurityDisplay_ && node.GetSecurityLayer()) {
922 RS_TRACE_NAME("SecurityLayer Skip");
923 return;
924 }
925 if (node.GetSurfaceNodeType() == RSSurfaceNodeType::STARTING_WINDOW_NODE && !needDrawStartingWindow_) {
926 RS_LOGD("RSUniRenderVisitor::ProcessSurfaceRenderNode skip startingWindow");
927 return;
928 }
929 const auto& property = node.GetRenderProperties();
930 if (!node.ShouldPaint()) {
931 RS_LOGD("RSUniRenderVisitor::ProcessSurfaceRenderNode node: %" PRIu64 " invisible", node.GetId());
932 return;
933 }
934 if (!node.GetOcclusionVisible() && !doAnimate_ && isOcclusionEnabled_ && !isSecurityDisplay_) {
935 RS_TRACE_NAME("Occlusion Skip");
936 return;
937 }
938 #ifdef RS_ENABLE_EGLQUERYSURFACE
939 // skip clean surface node
940 if (isOpDropped_ && node.IsAppWindow()) {
941 if (!node.SubNodeNeedDraw(node.GetOldDirtyInSurface(), partialRenderType_)) {
942 RS_TRACE_NAME("QuickReject Skip");
943 RS_LOGD("RSUniRenderVisitor::ProcessSurfaceRenderNode skip: %s", node.GetName().c_str());
944 return;
945 }
946 }
947 if (node.IsAppWindow()) {
948 curSurfaceNode_ = node.ReinterpretCastTo<RSSurfaceRenderNode>();
949 }
950 #endif
951
952 if (!canvas_) {
953 RS_LOGE("RSUniRenderVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
954 return;
955 }
956 auto geoPtr = std::static_pointer_cast<RSObjAbsGeometry>(property.GetBoundsGeometry());
957 if (!geoPtr) {
958 RS_LOGE("RSUniRenderVisitor::ProcessSurfaceRenderNode node:%" PRIu64 ", get geoPtr failed", node.GetId());
959 return;
960 }
961
962 #ifdef RS_ENABLE_EGLQUERYSURFACE
963 // when display is in rotation state, occlusion relationship will be ruined,
964 // hence visibleRegions cannot be used.
965 if (isOpDropped_ && node.IsAppWindow()) {
966 auto visibleRegions = node.GetVisibleRegion().GetRegionRects();
967 if (visibleRegions.size() == 1) {
968 canvas_->SetVisibleRect(SkRect::MakeLTRB(
969 visibleRegions[0].left_, visibleRegions[0].top_, visibleRegions[0].right_, visibleRegions[0].bottom_));
970 }
971 }
972 #endif
973
974 if (node.GetSurfaceNodeType() == RSSurfaceNodeType::LEASH_WINDOW_NODE) {
975 needDrawStartingWindow_ = true; // reset to default value
976 needColdStartThread_ = RSSystemProperties::GetColdStartThreadEnabled() &&
977 !node.IsStartAnimationFinished() && doAnimate_;
978 needCheckFirstFrame_ = node.GetChildrenCount() > 1; // childCount > 1 means startingWindow and appWindow
979 }
980
981 if (node.IsAppWindow() && needColdStartThread_ && needCheckFirstFrame_ &&
982 !RSColdStartManager::Instance().IsColdStartThreadRunning(node.GetId())) {
983 if (!IsFirstFrameReadyToDraw(node)) {
984 return;
985 }
986 auto nodePtr = node.shared_from_this();
987 RSColdStartManager::Instance().StartColdStartThreadIfNeed(nodePtr->ReinterpretCastTo<RSSurfaceRenderNode>());
988 RecordAppWindowNodeAndPostTask(node, property.GetBoundsWidth(), property.GetBoundsHeight());
989 return;
990 }
991
992 auto savedState = canvas_->SaveCanvasAndAlpha();
993 auto bgAntiAliasState = RSPropertiesPainter::GetBgAntiAlias();
994 if (doAnimate_ && (!ROSEN_EQ(geoPtr->GetScaleX(), 1.f) || !ROSEN_EQ(geoPtr->GetScaleY(), 1.f))) {
995 // disable background antialias when surfacenode has scale animation
996 RSPropertiesPainter::SetBgAntiAlias(false);
997 }
998
999 canvas_->MultiplyAlpha(property.GetAlpha());
1000 canvas_->MultiplyAlpha(node.GetContextAlpha());
1001
1002 bool isSelfDrawingSurface = node.GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE;
1003 if (isSelfDrawingSurface) {
1004 canvas_->save();
1005 }
1006
1007 canvas_->concat(geoPtr->GetMatrix());
1008
1009 const RectF absBounds = {0, 0, property.GetBoundsWidth(), property.GetBoundsHeight()};
1010 RRect absClipRRect = RRect(absBounds, property.GetCornerRadius());
1011 RSPropertiesPainter::DrawShadow(property, *canvas_, &absClipRRect);
1012
1013 if (isSelfDrawingSurface) {
1014 canvas_->save();
1015 }
1016
1017 if (node.GetSurfaceNodeType() != RSSurfaceNodeType::LEASH_WINDOW_NODE) {
1018 if (!property.GetCornerRadius().IsZero()) {
1019 canvas_->clipRRect(RSPropertiesPainter::RRect2SkRRect(absClipRRect), true);
1020 } else {
1021 canvas_->clipRect(SkRect::MakeWH(property.GetBoundsWidth(), property.GetBoundsHeight()));
1022 }
1023 }
1024
1025 RSPropertiesPainter::DrawBackground(property, *canvas_);
1026 RSPropertiesPainter::DrawMask(property, *canvas_);
1027 auto filter = std::static_pointer_cast<RSSkiaFilter>(property.GetBackgroundFilter());
1028 if (filter != nullptr) {
1029 auto skRectPtr = std::make_unique<SkRect>();
1030 skRectPtr->setXYWH(0, 0, property.GetBoundsWidth(), property.GetBoundsHeight());
1031 RSPropertiesPainter::DrawFilter(property, *canvas_, filter, skRectPtr, canvas_->GetSurface());
1032 }
1033
1034 if (isSelfDrawingSurface) {
1035 canvas_->restore();
1036 }
1037
1038 node.SetTotalMatrix(canvas_->getTotalMatrix());
1039
1040 if (!node.IsAppWindow() && node.GetBuffer() != nullptr) {
1041 node.NotifyRTBufferAvailable();
1042 node.SetGlobalAlpha(1.0f);
1043 auto params = RSUniRenderUtil::CreateBufferDrawParam(node, false);
1044 renderEngine_->DrawSurfaceNodeWithParams(*canvas_, node, params);
1045 }
1046
1047 if (isSelfDrawingSurface) {
1048 canvas_->restore();
1049 }
1050
1051 if (node.IsAppWindow() &&
1052 (!needColdStartThread_ || !RSColdStartManager::Instance().IsColdStartThreadRunning(node.GetId()))) {
1053 if (RSColdStartManager::Instance().IsColdStartThreadRunning(node.GetId())) {
1054 node.ClearCachedImage();
1055 RSColdStartManager::Instance().StopColdStartThread(node.GetId());
1056 }
1057 if (needCheckFirstFrame_ && IsFirstFrameReadyToDraw(node)) {
1058 node.NotifyUIBufferAvailable();
1059 needDrawStartingWindow_ = false;
1060 }
1061 if (!node.IsAppFreeze()) {
1062 ProcessBaseRenderNode(node);
1063 node.ClearCacheSurface();
1064 } else if (node.GetCacheSurface()) {
1065 RSUniRenderUtil::DrawCachedSurface(node, *canvas_, node.GetCacheSurface());
1066 } else {
1067 InitCacheSurface(node, property.GetBoundsWidth(), property.GetBoundsHeight());
1068 if (node.GetCacheSurface()) {
1069 auto cacheCanvas = std::make_shared<RSPaintFilterCanvas>(node.GetCacheSurface().get());
1070
1071 swap(cacheCanvas, canvas_);
1072 ProcessBaseRenderNode(node);
1073 swap(cacheCanvas, canvas_);
1074
1075 RSUniRenderUtil::DrawCachedSurface(node, *canvas_, node.GetCacheSurface());
1076 } else {
1077 RS_LOGE("RSUniRenderVisitor::ProcessSurfaceRenderNode %s Create CacheSurface failed",
1078 node.GetName().c_str());
1079 }
1080 }
1081 } else if (node.IsAppWindow()) { // use skSurface drawn by cold start thread
1082 if (node.GetCachedImage() != nullptr) {
1083 needDrawStartingWindow_ = false;
1084 RSUniRenderUtil::DrawCachedImage(node, *canvas_, node.GetCachedImage());
1085 }
1086 RecordAppWindowNodeAndPostTask(node, property.GetBoundsWidth(), property.GetBoundsHeight());
1087 } else {
1088 ProcessBaseRenderNode(node);
1089 }
1090
1091 if (node.GetSurfaceNodeType() == RSSurfaceNodeType::LEASH_WINDOW_NODE) {
1092 // reset to default value
1093 needColdStartThread_ = false;
1094 needCheckFirstFrame_ = false;
1095 }
1096
1097 filter = std::static_pointer_cast<RSSkiaFilter>(property.GetFilter());
1098 if (filter != nullptr) {
1099 auto skRectPtr = std::make_unique<SkRect>();
1100 skRectPtr->setXYWH(0, 0, property.GetBoundsWidth(), property.GetBoundsHeight());
1101 RSPropertiesPainter::DrawFilter(property, *canvas_, filter, skRectPtr, canvas_->GetSurface());
1102 }
1103
1104 RSPropertiesPainter::SetBgAntiAlias(bgAntiAliasState);
1105 canvas_->RestoreCanvasAndAlpha(savedState);
1106 if (node.IsAppWindow()) {
1107 canvas_->SetVisibleRect(SkRect::MakeLTRB(0, 0, 0, 0));
1108 }
1109 }
1110
ProcessProxyRenderNode(RSProxyRenderNode & node)1111 void RSUniRenderVisitor::ProcessProxyRenderNode(RSProxyRenderNode& node)
1112 {
1113 ProcessBaseRenderNode(node);
1114 }
1115
ProcessRootRenderNode(RSRootRenderNode & node)1116 void RSUniRenderVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
1117 {
1118 RS_LOGD("RSUniRenderVisitor::ProcessRootRenderNode node: %" PRIu64 ", child size:%u", node.GetId(),
1119 node.GetChildrenCount());
1120 if (!node.ShouldPaint()) {
1121 RS_LOGD("RSUniRenderVisitor::ProcessRootRenderNode, no need process");
1122 return;
1123 }
1124 if (!canvas_) {
1125 RS_LOGE("RSUniRenderVisitor::ProcessRootRenderNode, canvas is nullptr");
1126 return;
1127 }
1128
1129 ColorFilterMode colorFilterMode = renderEngine_->GetColorFilterMode();
1130 int saveCount;
1131 if (colorFilterMode >= ColorFilterMode::INVERT_COLOR_ENABLE_MODE &&
1132 colorFilterMode <= ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE) {
1133 RS_LOGD("RsDebug RSBaseRenderEngine::SetColorFilterModeToPaint mode:%d", static_cast<int32_t>(colorFilterMode));
1134 SkPaint paint;
1135 RSBaseRenderUtil::SetColorFilterModeToPaint(colorFilterMode, paint);
1136 saveCount = canvas_->saveLayer(nullptr, &paint);
1137 } else {
1138 saveCount = canvas_->save();
1139 }
1140 ProcessCanvasRenderNode(node);
1141 canvas_->restoreToCount(saveCount);
1142 }
1143
ProcessCanvasRenderNode(RSCanvasRenderNode & node)1144 void RSUniRenderVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node)
1145 {
1146 if (!node.ShouldPaint()) {
1147 RS_LOGD("RSUniRenderVisitor::ProcessCanvasRenderNode, no need process");
1148 return;
1149 }
1150 #ifdef RS_ENABLE_EGLQUERYSURFACE
1151 if (isOpDropped_ && curSurfaceNode_ &&
1152 !curSurfaceNode_->SubNodeNeedDraw(node.GetOldDirtyInSurface(), partialRenderType_) &&
1153 !node.HasChildrenOutOfRect()) {
1154 return;
1155 }
1156 #endif
1157 if (!canvas_) {
1158 RS_LOGE("RSUniRenderVisitor::ProcessCanvasRenderNode, canvas is nullptr");
1159 return;
1160 }
1161 node.ProcessRenderBeforeChildren(*canvas_);
1162 ProcessBaseRenderNode(node);
1163 node.ProcessRenderAfterChildren(*canvas_);
1164 }
1165
RecordAppWindowNodeAndPostTask(RSSurfaceRenderNode & node,float width,float height)1166 void RSUniRenderVisitor::RecordAppWindowNodeAndPostTask(RSSurfaceRenderNode& node, float width, float height)
1167 {
1168 RSRecordingCanvas canvas(width, height);
1169 #ifdef RS_ENABLE_GL
1170 canvas.SetGrContext(canvas_->getGrContext()); // SkImage::MakeFromCompressed need GrContext
1171 #endif
1172 auto recordingCanvas = std::make_shared<RSPaintFilterCanvas>(&canvas);
1173 swap(canvas_, recordingCanvas);
1174 ProcessBaseRenderNode(node);
1175 swap(canvas_, recordingCanvas);
1176 RSColdStartManager::Instance().PostPlayBackTask(node.GetId(), canvas.GetDrawCmdList(), width, height);
1177 }
1178
PrepareOffscreenRender(RSRenderNode & node)1179 void RSUniRenderVisitor::PrepareOffscreenRender(RSRenderNode& node)
1180 {
1181 // cleanup
1182 canvasBackup_ = nullptr;
1183 offscreenSurface_ = nullptr;
1184 // check offscreen size and hardware renderer
1185 int32_t offscreenWidth = node.GetRenderProperties().GetFrameWidth();
1186 int32_t offscreenHeight = node.GetRenderProperties().GetFrameHeight();
1187 if (offscreenWidth <= 0 || offscreenHeight <= 0) {
1188 RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, offscreenWidth or offscreenHeight is invalid");
1189 return;
1190 }
1191 if (canvas_->GetSurface() == nullptr) {
1192 canvas_->clipRect(SkRect::MakeWH(offscreenWidth, offscreenHeight));
1193 RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, current surface is nullptr (software renderer?)");
1194 return;
1195 }
1196 // create offscreen surface and canvas
1197 auto offscreenInfo = SkImageInfo::Make(offscreenWidth, offscreenHeight, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
1198 canvas_->GetSurface()->imageInfo().refColorSpace());
1199 offscreenSurface_ = canvas_->GetSurface()->makeSurface(offscreenInfo);
1200 if (offscreenSurface_ == nullptr) {
1201 RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, offscreenSurface is nullptr");
1202 canvas_->clipRect(SkRect::MakeWH(offscreenWidth, offscreenHeight));
1203 return;
1204 }
1205 auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface_.get());
1206 // backup current canvas and replace with offscreen canvas
1207 canvasBackup_ = std::move(canvas_);
1208 canvas_ = std::move(offscreenCanvas);
1209 }
1210
FinishOffscreenRender()1211 void RSUniRenderVisitor::FinishOffscreenRender()
1212 {
1213 if (canvasBackup_ == nullptr) {
1214 RS_LOGD("RSUniRenderVisitor::FinishOffscreenRender, canvasBackup_ is nullptr");
1215 return;
1216 }
1217 // flush offscreen canvas, maybe unnecessary
1218 canvas_->flush();
1219 // draw offscreen surface to current canvas
1220 SkPaint paint;
1221 paint.setAntiAlias(true);
1222 canvasBackup_->drawImage(offscreenSurface_->makeImageSnapshot(), 0, 0, &paint);
1223 // restore current canvas and cleanup
1224 offscreenSurface_ = nullptr;
1225 canvas_ = std::move(canvasBackup_);
1226 }
1227 } // namespace Rosen
1228 } // namespace OHOS
1229