• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "hwc_param.h"
16 #include "rs_uni_hwc_visitor.h"
17 
18 #include "feature/hwc/rs_uni_hwc_compute_util.h"
19 #include "feature/hdr/rs_hdr_util.h"
20 #include "pipeline/rs_canvas_render_node.h"
21 
22 #include "common/rs_common_hook.h"
23 #include "common/rs_optional_trace.h"
24 #include "rs_profiler.h"
25 #include "feature_cfg/graphic_feature_param_manager.h"
26 
27 #undef LOG_TAG
28 #define LOG_TAG "RSUniHwcVisitor"
29 
30 namespace OHOS {
31 namespace Rosen {
32 namespace {
33 constexpr int32_t MAX_ALPHA = 255;
34 constexpr uint32_t API18 = 18;
35 constexpr uint32_t INVALID_API_COMPATIBLE_VERSION = 0;
36 constexpr size_t MAX_NUM_SOLID_LAYER = 1;
37 constexpr int MIN_OVERLAP = 2;
38 
GetSolidLayerEnabled()39 bool GetSolidLayerEnabled()
40 {
41     return (HWCParam::IsSolidLayerEnable() || RsCommonHook::Instance().GetIsWhiteListForSolidColorLayerFlag()) &&
42         RSSystemParameters::GetSolidLayerHwcEnabled();
43 }
44 }
45 
RSUniHwcVisitor(RSUniRenderVisitor & visitor)46 RSUniHwcVisitor::RSUniHwcVisitor(RSUniRenderVisitor& visitor) : uniRenderVisitor_(visitor) {}
~RSUniHwcVisitor()47 RSUniHwcVisitor::~RSUniHwcVisitor() {}
48 
UpdateSrcRect(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix)49 void RSUniHwcVisitor::UpdateSrcRect(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix)
50 {
51     auto surfaceHandler = node.GetRSSurfaceHandler();
52     if (!surfaceHandler) {
53         return;
54     }
55     const auto buffer = surfaceHandler->GetBuffer();
56     const auto consumer = surfaceHandler->GetConsumer();
57     if (!consumer || !buffer) {
58         return;
59     }
60     const auto& property = node.GetRenderProperties();
61     auto bufferWidth = buffer->GetSurfaceBufferWidth();
62     auto bufferHeight = buffer->GetSurfaceBufferHeight();
63     const auto boundsWidth = property.GetBoundsWidth();
64     const auto boundsHeight = property.GetBoundsHeight();
65     const auto frameGravity = Gravity::RESIZE;
66     const GraphicTransformType consumerTransformType = node.GetFixRotationByUser() ?
67         RSUniHwcComputeUtil::GetRotateTransformForRotationFixed(node, consumer) :
68         RSUniHwcComputeUtil::GetConsumerTransform(node, buffer, consumer);
69     const auto dstRect = node.GetDstRect();
70     Drawing::Rect dst(dstRect.left_, dstRect.top_, dstRect.GetRight(), dstRect.GetBottom());
71     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
72         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
73         std::swap(bufferWidth, bufferHeight);
74     }
75     Drawing::Matrix gravityMatrix;
76     RSPropertiesPainter::GetGravityMatrix(frameGravity,
77         {0.f, 0.f, boundsWidth, boundsHeight}, bufferWidth, bufferHeight, gravityMatrix);
78     Drawing::Matrix inverseTotalMatrix;
79     Drawing::Matrix inverseGravityMatrix;
80     if (!totalMatrix.Invert(inverseTotalMatrix) || !gravityMatrix.Invert(inverseGravityMatrix)) {
81         node.SetSrcRect({0, 0, uniRenderVisitor_.curScreenNode_->GetScreenInfo().width,
82             uniRenderVisitor_.curScreenNode_->GetScreenInfo().height});
83         return;
84     }
85     Drawing::Rect srcRect;
86     inverseTotalMatrix.MapRect(srcRect, dst);
87     inverseGravityMatrix.MapRect(srcRect, srcRect);
88     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
89         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
90         std::swap(srcRect.left_, srcRect.top_);
91         std::swap(srcRect.right_, srcRect.bottom_);
92     }
93     srcRect = RSUniHwcComputeUtil::CalcSrcRectByBufferRotation(*buffer, consumerTransformType, srcRect);
94     node.SetSrcRect({srcRect.GetLeft(), srcRect.GetTop(), srcRect.GetWidth(), srcRect.GetHeight()});
95 }
96 
UpdateDstRect(RSSurfaceRenderNode & node,const RectI & absRect,const RectI & clipRect)97 void RSUniHwcVisitor::UpdateDstRect(RSSurfaceRenderNode& node, const RectI& absRect, const RectI& clipRect)
98 {
99     auto dstRect = absRect;
100     if (!node.IsHardwareEnabledTopSurface() && !node.GetHwcGlobalPositionEnabled()) {
101         // If the screen is expanded, intersect the destination rectangle with the screen rectangle
102         dstRect = dstRect.IntersectRect(RectI(0, 0, uniRenderVisitor_.curScreenNode_->GetScreenInfo().width,
103             uniRenderVisitor_.curScreenNode_->GetScreenInfo().height));
104         // global positon has been transformd to screen position in absRect
105     }
106     // If the node is a hardware-enabled type, intersect its destination rectangle with the prepare clip rectangle
107     if (node.IsHardwareEnabledType() || node.IsHardwareEnabledTopSurface()) {
108         if (!node.IsHwcCrossNode()) {
109             dstRect = dstRect.IntersectRect(clipRect);
110         }
111     }
112     auto widthRatio = uniRenderVisitor_.curScreenNode_->GetScreenInfo().GetRogWidthRatio();
113     auto heightRatio = uniRenderVisitor_.curScreenNode_->GetScreenInfo().GetRogHeightRatio();
114     dstRect.left_ = static_cast<int32_t>(std::floor(dstRect.left_ * widthRatio));
115     dstRect.top_ = static_cast<int32_t>(std::floor(dstRect.top_ * heightRatio));
116     dstRect.width_ = static_cast<int32_t>(std::ceil(dstRect.width_ * widthRatio));
117     dstRect.height_ = static_cast<int32_t>(std::ceil(dstRect.height_ * heightRatio));
118 
119     if (uniRenderVisitor_.curSurfaceNode_ && (node.GetId() != uniRenderVisitor_.curSurfaceNode_->GetId()) &&
120         !node.GetHwcGlobalPositionEnabled()) {
121         dstRect = dstRect.IntersectRect(uniRenderVisitor_.curSurfaceNode_->GetDstRect());
122     }
123     UpdateRenderResolutionDstRectForDrm(node, dstRect);
124     // Set the destination rectangle of the node
125     node.SetDstRect(dstRect);
126     node.SetDstRectWithoutRenderFit(dstRect);
127 }
128 
UpdateRenderResolutionDstRectForDrm(RSSurfaceRenderNode & node,RectI & dstRect)129 void RSUniHwcVisitor::UpdateRenderResolutionDstRectForDrm(RSSurfaceRenderNode& node, RectI& dstRect)
130 {
131     auto widthRatio = uniRenderVisitor_.curScreenNode_->GetScreenInfo().GetRogWidthRatio();
132     auto heightRatio = uniRenderVisitor_.curScreenNode_->GetScreenInfo().GetRogHeightRatio();
133     if (ROSEN_EQ(widthRatio, 0.f) || ROSEN_EQ(heightRatio, 0.f)) {
134         return;
135     }
136     if (node.GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED)) {
137         dstRect.left_ = static_cast<int32_t>(std::floor(dstRect.left_ / widthRatio));
138         dstRect.top_ = static_cast<int32_t>(std::floor(dstRect.top_ / heightRatio));
139         dstRect.width_ = static_cast<int32_t>(std::ceil(dstRect.width_ / widthRatio));
140         dstRect.height_ = static_cast<int32_t>(std::ceil(dstRect.height_ / heightRatio));
141     }
142 }
143 
UpdateHwcNodeByTransform(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix)144 void RSUniHwcVisitor::UpdateHwcNodeByTransform(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix)
145 {
146     if (!node.GetRSSurfaceHandler() || !node.GetRSSurfaceHandler()->GetBuffer()) {
147         return;
148     }
149     node.SetInFixedRotation(uniRenderVisitor_.displayNodeRotationChanged_ ||
150         uniRenderVisitor_.isScreenRotationAnimating_);
151     const uint32_t apiCompatibleVersion = node.GetApiCompatibleVersion();
152     auto surfaceParams = static_cast<RSSurfaceRenderParams *>(node.GetStagingRenderParams().get());
153     ((surfaceParams != nullptr && surfaceParams->GetIsHwcEnabledBySolidLayer()) || apiCompatibleVersion >= API18 ||
154         node.GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED) ||
155         node.GetName().find("RenderFitSurface") != std::string::npos) ?
156         RSUniHwcComputeUtil::DealWithNodeGravity(node, totalMatrix) :
157         RSUniHwcComputeUtil::DealWithNodeGravityOldVersion(node, uniRenderVisitor_.curScreenNode_->GetScreenInfo());
158     RSUniHwcComputeUtil::DealWithScalingMode(node, totalMatrix);
159     RSUniHwcComputeUtil::LayerRotate(node, uniRenderVisitor_.curScreenNode_->GetScreenInfo());
160     RSUniHwcComputeUtil::LayerCrop(node, uniRenderVisitor_.curScreenNode_->GetScreenInfo());
161     RSUniHwcComputeUtil::CalcSrcRectByBufferFlip(node, uniRenderVisitor_.curScreenNode_->GetScreenInfo());
162     node.SetCalcRectInPrepare(true);
163 }
164 
GetHwcVisibleEffectDirty(RSRenderNode & node,const RectI & globalFilterRect) const165 RectI RSUniHwcVisitor::GetHwcVisibleEffectDirty(RSRenderNode& node, const RectI& globalFilterRect) const
166 {
167     RectI childEffectRect;
168     if (!globalFilterRect.IsEmpty()) {
169         childEffectRect = globalFilterRect.JoinRect(node.GetFilterRect());
170     }
171     return childEffectRect;
172 }
173 
UpdateIsOffscreen(RSCanvasRenderNode & node)174 bool RSUniHwcVisitor::UpdateIsOffscreen(RSCanvasRenderNode& node)
175 {
176     const auto& property = node.GetRenderProperties();
177     bool isCurrOffscreen = isOffscreen_;
178     isOffscreen_ |= (property.IsColorBlendApplyTypeOffscreen() && !property.IsColorBlendModeNone()) ||
179         RSUniHwcComputeUtil::IsDangerousBlendMode(property.GetColorBlendMode(), property.GetColorBlendApplyType());
180     // The meaning of first prepared offscreen node is either its colorBlendApplyType is not FAST or
181     // its colorBlendMode is NONE.
182     // Node will classified as blendWithBackground if it is the first prepared offscreen node and
183     // its colorBlendMode is neither NONE nor SRC_OVER.
184     node.GetHwcRecorder().SetBlendWithBackground(!isCurrOffscreen && property.IsColorBlendModeValid());
185     return isCurrOffscreen;
186 }
187 
UpdateForegroundColorValid(RSCanvasRenderNode & node)188 void RSUniHwcVisitor::UpdateForegroundColorValid(RSCanvasRenderNode& node)
189 {
190     node.GetHwcRecorder().SetForegroundColorValid(RSUniHwcComputeUtil::IsForegroundColorStrategyValid(node));
191 }
192 
CheckNodeOcclusion(const std::shared_ptr<RSRenderNode> & node,const RectI & surfaceNodeAbsRect,Color & validBgColor)193 bool RSUniHwcVisitor::CheckNodeOcclusion(const std::shared_ptr<RSRenderNode>& node,
194     const RectI& surfaceNodeAbsRect, Color& validBgColor)
195 {
196     validBgColor = RgbPalette::Transparent();
197     if (node == nullptr) {
198         return false;
199     }
200     if (node->IsPureContainer() && !node->ShouldPaint()) {
201         return false;
202     }
203     const auto& nodeProperties = node->GetRenderProperties();
204     auto absRect = nodeProperties.GetBoundsGeometry()->GetAbsRect();
205     // The canvas node intersects with the surface node.
206     if (!absRect.IsEmpty() && !surfaceNodeAbsRect.IsEmpty() && !absRect.IntersectRect(surfaceNodeAbsRect).IsEmpty()) {
207         if (node->GetType() != RSRenderNodeType::CANVAS_NODE) {
208             RS_LOGD("solidLayer: node type isn't canvas node, id:%{public}" PRIu64 " ", node->GetId());
209             return true;
210         }
211 
212         bool willNotDraw = node->IsPureBackgroundColor();
213         RS_LOGD("solidLayer: id:%{public}" PRIu64 ", willNotDraw: %{public}d", node->GetId(), willNotDraw);
214         if (!willNotDraw) {
215             RS_LOGD("solidLayer: presence drawing, id:%{public}" PRIu64, node->GetId());
216             return true;
217         }
218         const auto& nodeBgColor = nodeProperties.GetBackgroundColor();
219         const auto& nodeBgColorAlpha = nodeBgColor.GetAlpha();
220         bool isSolid = ROSEN_EQ(nodeProperties.GetAlpha(), 1.f) && (nodeBgColorAlpha == MAX_ALPHA);
221         if (isSolid) {
222             if (surfaceNodeAbsRect.IsInsideOf(absRect)) {
223                 validBgColor = nodeBgColor;
224                 RS_LOGD("solidLayer: canvas node color, id:%{public}" PRIu64 ", color:%{public}08x",
225                     node->GetId(), validBgColor.AsArgbInt());
226                 return false;
227             }
228             RS_LOGD("solidLayer: the background color node doesn't cover the surface node, id:%{public}" PRIu64,
229                 node->GetId());
230             return true;
231         }
232         return nodeBgColorAlpha != 0;
233     }
234     return false;
235 }
236 
CheckSubTreeOcclusion(const std::shared_ptr<RSRenderNode> & branchNode,const RectI & surfaceNodeAbsRect,std::stack<Color> & validBgColors)237 bool RSUniHwcVisitor::CheckSubTreeOcclusion(
238     const std::shared_ptr<RSRenderNode>& branchNode, const RectI& surfaceNodeAbsRect, std::stack<Color>& validBgColors)
239 {
240     // Recursive operation, checking branches from top to bottpm, looking for background color
241     if (branchNode == nullptr) {
242         return false;
243     }
244     RS_LOGD("solidLayer: check branch, id:%{public}" PRIu64, branchNode->GetId());
245     Color bgColor = RgbPalette::Transparent();
246     if (CheckNodeOcclusion(branchNode, surfaceNodeAbsRect, bgColor)) {
247         RS_LOGD("solidLayer: node is occlusion, id:%{public}" PRIu64, branchNode->GetId());
248         while (!validBgColors.empty()) {
249             validBgColors.pop();
250         }
251         return true;
252     } else if (bgColor != RgbPalette::Transparent()) {
253         validBgColors.push(bgColor);
254     }
255     for (const auto& child : *branchNode->GetSortedChildren()) {
256         if (child != nullptr && CheckSubTreeOcclusion(child, surfaceNodeAbsRect, validBgColors)) {
257             while (!validBgColors.empty()) {
258                 validBgColors.pop();
259             }
260             return true;
261         }
262     }
263     return false;
264 }
265 
FindAppBackgroundColor(RSSurfaceRenderNode & node)266 Color RSUniHwcVisitor::FindAppBackgroundColor(RSSurfaceRenderNode& node)
267 {
268     RS_OPTIONAL_TRACE_NAME_FMT(
269         "solidLayer:%s name:%s id:%" PRIu64, __func__, node.GetName().c_str(), node.GetId());
270 
271     auto rootNode = uniRenderVisitor_.curSurfaceNode_->GetFirstChild();
272     auto parent = node.GetParent().lock();
273     auto childId = node.GetId();
274     auto surfaceNodeAbsRect = node.GetRenderProperties().GetBoundsGeometry()->GetAbsRect();
275     // Check the node from bottom up to look for the background color.
276     while (rootNode && parent && parent->GetId() != rootNode->GetId()) {
277         auto sortedChildren = parent->GetSortedChildren();
278         auto iter = std::find_if(
279             (*sortedChildren).begin(), (*sortedChildren).end(), [&childId](const std::shared_ptr<RSRenderNode>& node) {
280                 return node != nullptr && node->GetId() == childId;
281             });
282         if (iter == (*sortedChildren).end()) {
283             return RgbPalette::Transparent();
284         }
285         int32_t index = static_cast<int32_t>(std::distance((*sortedChildren).begin(), iter));
286         // Check branches from near to far
287         std::stack<Color> validBgColors;
288         for (int32_t i = 1; i <= index; i++) {
289             const auto& child = sortedChildren->at(index - i);
290             if (child == nullptr) {
291                 continue;
292             }
293             if (CheckSubTreeOcclusion(child, surfaceNodeAbsRect, validBgColors)) {
294                 return RgbPalette::Transparent();
295             } else if (!validBgColors.empty()) {
296                 Color backgroundColor = validBgColors.top();
297                 RS_LOGD("solidLayer:  branch color, branch id:%{public}" PRIu64 ", color:%{public}08x",
298                     node.GetId(), backgroundColor.AsArgbInt());
299                 return backgroundColor;
300             }
301         }
302         Color bgColor = RgbPalette::Transparent();
303         if (CheckNodeOcclusion(parent, surfaceNodeAbsRect, bgColor)) {
304             return RgbPalette::Transparent();
305         } else if (bgColor != RgbPalette::Transparent()) {
306             return bgColor;
307         }
308         childId = parent->GetId();
309         parent = parent->GetParent().lock();
310     }
311     return RgbPalette::Transparent();
312 }
313 
ProcessSolidLayerDisabled(RSSurfaceRenderNode & node)314 void RSUniHwcVisitor::ProcessSolidLayerDisabled(RSSurfaceRenderNode& node)
315 {
316     RS_OPTIONAL_TRACE_NAME_FMT("solidLayer: name:%s id:%" PRIu64 " solidLayer enabling condition is not met.",
317         node.GetName().c_str(), node.GetId());
318     RS_LOGD("solidLayer: solidLayer enabling condition is not met, name: %{public}s", node.GetName().c_str());
319     const auto& renderProperties = node.GetRenderProperties();
320     Color appBackgroundColor = renderProperties.GetBackgroundColor();
321     // Non-xcom or pure black nodes are not processed and are allowed to pass.
322     if (static_cast<uint8_t>(appBackgroundColor.GetAlpha()) == MAX_ALPHA &&
323         appBackgroundColor == RgbPalette::Black()) {
324         RS_LOGD("solidLayer: background color is black: %{public}s, go hwc directly", node.GetName().c_str());
325         return;
326     }
327     auto stagingSurfaceParams = static_cast<RSSurfaceRenderParams *>(node.GetStagingRenderParams().get());
328     if (static_cast<uint8_t>(appBackgroundColor.GetAlpha()) == MAX_ALPHA &&
329         stagingSurfaceParams->GetSelfDrawingNodeType() != SelfDrawingNodeType::XCOM) {
330         RS_LOGD("solidLayer: solid color surface node: %{public}s, go hwc directly", node.GetName().c_str());
331         return;
332     }
333     if (static_cast<uint8_t>(appBackgroundColor.GetAlpha()) < MAX_ALPHA) {
334         bool isSpecialNodeType = RsCommonHook::Instance().GetHardwareEnabledByBackgroundAlphaFlag() ||
335             node.IsHardwareEnableHint();
336         if (!isSpecialNodeType || node.IsRosenWeb()) {
337             auto parentNode = node.GetParent().lock();
338             RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
339                 "background color alpha < 1", node.GetName().c_str(), node.GetId(), parentNode ? parentNode->GetId() : 0);
340             RS_LOGD("solidLayer: disabled by background color alpha < 1: %{public}s", node.GetName().c_str());
341             PrintHiperfLog(&node, "background color alpha < 1");
342             node.SetHardwareForcedDisabledState(true);
343             Statistics().UpdateHwcDisabledReasonForDFX(
344                 node.GetId(), HwcDisabledReasons::DISABLED_BY_BACKGROUND_ALPHA, node.GetName());
345             return;
346         }
347         uniRenderVisitor_.curSurfaceNode_->SetExistTransparentHardwareEnabledNode(true);
348         node.SetNodeHasBackgroundColorAlpha(true);
349     } else {
350         auto parentNode = node.GetParent().lock();
351         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by background "
352             "solidColor && HDR", node.GetName().c_str(), node.GetId(), parentNode ? parentNode->GetId() : 0);
353         RS_LOGD("solidLayer: disabled by background solidColor && HDR: %{public}s", node.GetName().c_str());
354         PrintHiperfLog(&node, "background solidColor && HDR");
355         node.SetHardwareForcedDisabledState(true);
356         Statistics().UpdateHwcDisabledReasonForDFX(
357             node.GetId(), HwcDisabledReasons::DISABLED_BY_SOLID_BACKGROUND_ALPHA, node.GetName());
358     }
359 }
360 
ProcessSolidLayerEnabled(RSSurfaceRenderNode & node)361 void RSUniHwcVisitor::ProcessSolidLayerEnabled(RSSurfaceRenderNode& node)
362 {
363     if (!GetSolidLayerEnabled() || (GetSolidLayerHwcEnableCount() >= MAX_NUM_SOLID_LAYER)) {
364         RS_LOGD("solidLayer: solidLayer enabling condition is met, but the switch is not turned on or exceeds the "
365             "upper limit! solidLayer num: %{public}zu, name: %{public}s", GetSolidLayerHwcEnableCount(),
366             node.GetName().c_str());
367         RS_OPTIONAL_TRACE_NAME_FMT("solidLayer: solidLayer enabling condition is met, but the switch is not turned "
368             "on or exceeds the upper limit! solidLayer num: %zu, name: %s", GetSolidLayerHwcEnableCount(),
369             node.GetName().c_str());
370         auto parentNode = node.GetParent().lock();
371         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by solidLayer "
372             "enabling condition is met, but the switch is disabled!", node.GetName().c_str(), node.GetId(),
373             parentNode ? parentNode->GetId() : 0);
374         node.SetHardwareForcedDisabledState(true);
375         Statistics().UpdateHwcDisabledReasonForDFX(
376             node.GetId(), HwcDisabledReasons::DISABLED_BY_SOLID_BACKGROUND_ALPHA, node.GetName());
377         return;
378     }
379     RS_OPTIONAL_TRACE_NAME_FMT("solidLayer: name:%s id:%" PRIu64 " solidLayer enabling condition is met.",
380         node.GetName().c_str(), node.GetId());
381     RS_LOGD("solidLayer: solidLayer enabling condition is met, name: %{public}s", node.GetName().c_str());
382     const auto& renderProperties = node.GetRenderProperties();
383     Color appBackgroundColor = renderProperties.GetBackgroundColor();
384     if (static_cast<uint8_t>(appBackgroundColor.GetAlpha()) == 0) {
385         appBackgroundColor = FindAppBackgroundColor(node);
386         auto parentNode = node.GetParent().lock();
387         RS_OPTIONAL_TRACE_FMT("solidLayer: background color found upwards in a transparent situation, name:%s "
388             "id:%" PRIu64 " parentId:%" PRIu64 " color:%08x", node.GetName().c_str(), node.GetId(),
389             parentNode ? parentNode->GetId() : 0, appBackgroundColor.AsArgbInt());
390         RS_LOGD("solidLayer: isPureTransparentEnabled color:%{public}08x", appBackgroundColor.AsArgbInt());
391         if (appBackgroundColor == RgbPalette::Black()) {
392             // The background is black and does not overlap other surface node.
393             RS_LOGD("solidLayer: background color is black: %{public}s", node.GetName().c_str());
394             return;
395         }
396     }
397     // No background color available
398     if (static_cast<uint8_t>(appBackgroundColor.GetAlpha()) < MAX_ALPHA) {
399         auto parentNode = node.GetParent().lock();
400         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by background "
401             "color not found", node.GetName().c_str(), node.GetId(), parentNode ? parentNode->GetId() : 0);
402         RS_LOGD("solidLayer: disabled by background color not found: %{public}s", node.GetName().c_str());
403         PrintHiperfLog(&node, "background color not found");
404         node.SetHardwareForcedDisabledState(true);
405         Statistics().UpdateHwcDisabledReasonForDFX(
406             node.GetId(), HwcDisabledReasons::DISABLED_BY_SOLID_BACKGROUND_ALPHA, node.GetName());
407         return;
408     }
409     RS_OPTIONAL_TRACE_NAME_FMT("solidLayer: Set solid layer color, name:%s id:%" PRIu64 ", color:%08x",
410         node.GetName().c_str(), node.GetId(), appBackgroundColor.AsArgbInt());
411     RS_LOGD("solidLayer: Set solid layer color:%{public}08x", appBackgroundColor.AsArgbInt());
412     auto stagingSurfaceParams = static_cast<RSSurfaceRenderParams *>(node.GetStagingRenderParams().get());
413     if (!stagingSurfaceParams) {
414         node.SetHardwareForcedDisabledState(true);
415         return;
416     }
417     stagingSurfaceParams->SetIsHwcEnabledBySolidLayer(true);
418     stagingSurfaceParams->SetSolidLayerColor(appBackgroundColor);
419     IncreaseSolidLayerHwcEnableCount();
420 }
421 
UpdateHwcNodeEnableByBackgroundAlpha(RSSurfaceRenderNode & node)422 void RSUniHwcVisitor::UpdateHwcNodeEnableByBackgroundAlpha(RSSurfaceRenderNode& node)
423 {
424     auto stagingSurfaceParams = static_cast<RSSurfaceRenderParams *>(node.GetStagingRenderParams().get());
425     stagingSurfaceParams->SetIsHwcEnabledBySolidLayer(false);
426     if (node.GetAncoForceDoDirect()) {
427         return;
428     }
429     RS_LOGD("solidLayer: %{public}s, name: %{public}s id: %{public}" PRIu64,
430         __func__, node.GetName().c_str(), node.GetId());
431     const auto& renderProperties = node.GetRenderProperties();
432     Color appBackgroundColor = renderProperties.GetBackgroundColor();
433     // Enabling conditions: target type, overall a==1, pure color non-black/pure transparent,
434     // no bullet screen
435     bool isTargetNodeType = node.GetSelfDrawingNodeType() == SelfDrawingNodeType::XCOM ||
436         (node.IsRosenWeb() && static_cast<uint8_t>(appBackgroundColor.GetAlpha()) == 0);
437     bool isTargetColor = (static_cast<uint8_t>(appBackgroundColor.GetAlpha()) == MAX_ALPHA &&
438                           appBackgroundColor != RgbPalette::Black()) ||
439                           static_cast<uint8_t>(appBackgroundColor.GetAlpha()) == 0;
440     bool isSpecialNodeType = RsCommonHook::Instance().GetHardwareEnabledByBackgroundAlphaFlag() ||
441                              node.IsHardwareEnableHint();
442     auto GetHwcNodeHdrEnabled = [this]() {
443         const auto &selfDrawingNodes = RSMainThread::Instance()->GetSelfDrawingNodes();
444         for (auto surfaceNode : selfDrawingNodes) {
445             if (surfaceNode && RSHdrUtil::CheckIsHdrSurface(*surfaceNode) != HdrStatus::NO_HDR) {
446                 return true;
447             }
448         }
449         return false;
450     };
451     bool isNodeOpaque = ROSEN_EQ(renderProperties.GetAlpha(), 1.f);
452     bool isSolidLayerEnabled =
453         isTargetNodeType && isTargetColor && isNodeOpaque && !isSpecialNodeType;
454     bool isHdrOn = false;
455     bool hasBrightness = false;
456     if (isSolidLayerEnabled) {
457         isHdrOn = uniRenderVisitor_.curScreenNode_->GetHasUniRenderHdrSurface() || GetHwcNodeHdrEnabled();
458         hasBrightness = renderProperties.GetBgBrightnessParams().has_value();
459         if (!isHdrOn && !hasBrightness) {
460             ProcessSolidLayerEnabled(node);
461             return;
462         }
463     }
464     RS_LOGD("solidLayer: SolidLayer enabling conditions, isTargetNodeType:%{public}d, isTargetColor:%{public}d, "
465         "Alpha: %{public}d, !isSpecialNodeType: %{public}d, !isHdrOn: %{public}d, !hasBrightness: %{public}d",
466         isTargetNodeType, isTargetColor, isNodeOpaque, !isSpecialNodeType, !isHdrOn, !hasBrightness);
467     ProcessSolidLayerDisabled(node);
468 }
469 
UpdateHwcNodeEnableByBufferSize(RSSurfaceRenderNode & node)470 void RSUniHwcVisitor::UpdateHwcNodeEnableByBufferSize(RSSurfaceRenderNode& node)
471 {
472     if (!node.IsRosenWeb() || node.IsHardwareForcedDisabled() || !node.GetRSSurfaceHandler()) {
473         return;
474     }
475     auto surfaceHandler = node.GetRSSurfaceHandler();
476     auto buffer = surfaceHandler->GetBuffer();
477     auto consumer = surfaceHandler->GetConsumer();
478     if (buffer == nullptr || consumer == nullptr) {
479         return;
480     }
481     const auto& property = node.GetRenderProperties();
482     const auto boundsWidth = property.GetBoundsWidth();
483     const auto boundsHeight = property.GetBoundsHeight();
484     auto bufferWidth = buffer->GetSurfaceBufferWidth();
485     auto bufferHeight = buffer->GetSurfaceBufferHeight();
486     const auto consumerTransformType = node.GetFixRotationByUser() ?
487         RSUniHwcComputeUtil::GetRotateTransformForRotationFixed(node, consumer) :
488         RSUniHwcComputeUtil::GetConsumerTransform(node, buffer, consumer);
489     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
490         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
491         std::swap(bufferWidth, bufferHeight);
492     }
493     if (ROSEN_LNE(bufferWidth, boundsWidth) || ROSEN_LNE(bufferHeight, boundsHeight)) {
494         auto parentNode = node.GetParent().lock();
495         RS_OPTIONAL_TRACE_FMT(
496             "hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " bounds:[%f, %f] buffer:[%d, %d] "
497             "disabled by rosenWeb buffer nonmatching", node.GetName().c_str(), node.GetId(),
498             parentNode ? parentNode->GetId() : 0, boundsWidth, boundsHeight, bufferWidth, bufferHeight);
499         PrintHiperfLog(&node, "buffer nonmatching");
500         node.SetHardwareForcedDisabledState(true);
501         Statistics().UpdateHwcDisabledReasonForDFX(
502             node.GetId(), HwcDisabledReasons::DISABLED_BY_BUFFER_NONMATCH, node.GetName());
503     }
504 }
505 
UpdateHwcNodeEnableByRotate(const std::shared_ptr<RSSurfaceRenderNode> & hwcNode)506 void RSUniHwcVisitor::UpdateHwcNodeEnableByRotate(const std::shared_ptr<RSSurfaceRenderNode>& hwcNode)
507 {
508     if (hwcNode->IsHardwareForcedDisabled()) {
509         return;
510     }
511     // [planning] degree only multiples of 90 now
512     const auto& totalMatrix = hwcNode->GetTotalMatrix();
513     float degree = RSUniHwcComputeUtil::GetFloatRotationDegreeFromMatrix(totalMatrix);
514     bool hasRotate = !ROSEN_EQ(std::remainder(degree, 90.f), 0.f, EPSILON) ||
515                      RSUniHwcComputeUtil::HasNonZRotationTransform(totalMatrix);
516     if (hasRotate) {
517         auto parentNode = hwcNode->GetParent().lock();
518         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
519             "surfaceNode rotation:%f", hwcNode->GetName().c_str(), hwcNode->GetId(),
520             parentNode ? parentNode->GetId() : 0, degree);
521         PrintHiperfLog(hwcNode, "rotation");
522         hwcNode->SetHardwareForcedDisabledState(true);
523         Statistics().UpdateHwcDisabledReasonForDFX(hwcNode->GetId(),
524             HwcDisabledReasons::DISABLED_BY_ROTATION, hwcNode->GetName());
525         return;
526     }
527 }
528 
UpdateHwcNodeEnableByAlpha(const std::shared_ptr<RSSurfaceRenderNode> & hwcNode)529 void RSUniHwcVisitor::UpdateHwcNodeEnableByAlpha(const std::shared_ptr<RSSurfaceRenderNode>& hwcNode)
530 {
531     if (hwcNode->IsHardwareForcedDisabled()) {
532         return;
533     }
534     if (const auto alpha = hwcNode->GetGlobalAlpha(); ROSEN_LNE(alpha, 1.0f)) {
535         auto parentNode = hwcNode->GetParent().lock();
536         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
537             "accumulated alpha:%f", hwcNode->GetName().c_str(), hwcNode->GetId(),
538             parentNode ? parentNode->GetId() : 0, alpha);
539         PrintHiperfLog(hwcNode, "accumulated alpha");
540         hwcNode->SetHardwareForcedDisabledState(true);
541         if (ROSEN_NE(alpha, 0.f)) {
542             Statistics().UpdateHwcDisabledReasonForDFX(hwcNode->GetId(),
543                 HwcDisabledReasons::DISABLED_BY_ACCUMULATED_ALPHA, hwcNode->GetName());
544         }
545         return;
546     }
547 }
548 
UpdateHwcNodeEnable()549 void RSUniHwcVisitor::UpdateHwcNodeEnable()
550 {
551     std::unordered_set<std::shared_ptr<RSSurfaceRenderNode>> ancoNodes;
552     int inputHwclayers = 3;
553     auto& curMainAndLeashSurfaces = uniRenderVisitor_.curScreenNode_->GetAllMainAndLeashSurfaces();
554     std::for_each(curMainAndLeashSurfaces.rbegin(), curMainAndLeashSurfaces.rend(),
555         [this, &inputHwclayers, &ancoNodes](RSBaseRenderNode::SharedPtr& nodePtr) {
556         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(nodePtr);
557         if (!surfaceNode) {
558             return;
559         }
560 
561         if (RSSystemProperties::GetHveFilterEnabled()) {
562             const auto &preHwcNodes = surfaceNode->GetChildHardwareEnabledNodes();
563             for (const auto& preHwcNode : preHwcNodes) {
564                 auto hwcNodePtr = preHwcNode.lock();
565                 if (!hwcNodePtr || !hwcNodePtr->IsOnTheTree()) {
566                     continue;
567                 }
568                 hwcNodePtr->ResetMakeImageState();
569             }
570         }
571 
572         UpdateHwcNodeEnableByGlobalFilter(surfaceNode);
573         surfaceNode->ResetNeedCollectHwcNode();
574         const auto& hwcNodes = surfaceNode->GetChildHardwareEnabledNodes();
575         if (hwcNodes.empty()) {
576             return;
577         }
578         inputHwclayers += hwcNodes.size();
579         std::vector<RectI> hwcRects;
580         for (const auto& hwcNode : hwcNodes) {
581             auto hwcNodePtr = hwcNode.lock();
582             if (!hwcNodePtr || !hwcNodePtr->IsOnTheTree()) {
583                 continue;
584             }
585             if (hwcNodePtr->GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED)) {
586                 uniRenderVisitor_.drmNodes_.emplace_back(hwcNode);
587                 auto firstLevelNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(
588                     hwcNodePtr->GetFirstLevelNode());
589                 hwcNodePtr->SetForceDisableClipHoleForDRM(firstLevelNode != nullptr &&
590                     firstLevelNode->GetRenderProperties().IsAttractionValid());
591             }
592             RSUniHwcComputeUtil::UpdateHwcNodeProperty(hwcNodePtr);
593             UpdateHwcNodeEnableByAlpha(hwcNodePtr);
594             UpdateHwcNodeEnableByRotate(hwcNodePtr);
595             UpdateHwcNodeEnableByHwcNodeBelowSelfInApp(hwcNodePtr, hwcRects);
596             if ((hwcNodePtr->GetAncoFlags() & static_cast<uint32_t>(AncoFlags::IS_ANCO_NODE)) != 0) {
597                 ancoNodes.insert(hwcNodePtr);
598             }
599         }
600     });
601     RS_LOGW("hiperf_surface_counter1 %{public}" PRIu64 " ", static_cast<uint64_t>(inputHwclayers));
602     PrintHiperfCounterLog("counter1", static_cast<uint64_t>(inputHwclayers));
603     uniRenderVisitor_.PrevalidateHwcNode();
604     UpdateHwcNodeEnableByNodeBelow();
605     uniRenderVisitor_.UpdateAncoNodeHWCDisabledState(ancoNodes);
606 }
607 
UpdateHwcNodeEnableByNodeBelow()608 void RSUniHwcVisitor::UpdateHwcNodeEnableByNodeBelow()
609 {
610     auto& curMainAndLeashSurfaces = uniRenderVisitor_.curScreenNode_->GetAllMainAndLeashSurfaces();
611     // this is used to record mainAndLeash surface accumulatedDirtyRegion by Pre-order traversal
612     std::vector<RectI> hwcRects;
613     RectI backgroundAlphaRect;
614     bool isHardwareEnableByBackgroundAlpha = false;
615     std::vector<RectI> abovedBounds;
616     // Top-Down
617     std::for_each(curMainAndLeashSurfaces.begin(), curMainAndLeashSurfaces.end(),
618         [this, &backgroundAlphaRect, &isHardwareEnableByBackgroundAlpha, &abovedBounds]
619         (RSBaseRenderNode::SharedPtr& nodePtr) {
620         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(nodePtr);
621         if (!surfaceNode) {
622             RS_LOGE("%{public}s: surfaceNode is nullptr", __func__);
623             return;
624         }
625         // use in temporary scheme to realize DSS
626         auto& hwcNodes = surfaceNode->GetChildHardwareEnabledNodes();
627         UpdateHardwareStateByBoundNEDstRectInApps(hwcNodes, abovedBounds);
628         if (!hwcNodes.empty() && RsCommonHook::Instance().GetHardwareEnabledByBackgroundAlphaFlag() &&
629             RsCommonHook::Instance().GetHardwareEnabledByHwcnodeBelowSelfInAppFlag()) {
630             UpdateHardwareStateByHwcNodeBackgroundAlpha(hwcNodes, backgroundAlphaRect,
631                 isHardwareEnableByBackgroundAlpha);
632         } else if (surfaceNode->ExistTransparentHardwareEnabledNode()) {
633             UpdateTransparentHwcNodeEnable(hwcNodes);
634         }
635     });
636     // Down-Top
637     std::for_each(curMainAndLeashSurfaces.rbegin(), curMainAndLeashSurfaces.rend(),
638         [this, &hwcRects](RSBaseRenderNode::SharedPtr& nodePtr) {
639         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(nodePtr);
640         if (!surfaceNode) {
641             RS_LOGE("%{public}s: surfaceNode is nullptr", __func__);
642             return;
643         }
644         // use end
645         UpdateChildHwcNodeEnableByHwcNodeBelow(hwcRects, surfaceNode);
646     });
647 }
648 
UpdateTransparentHwcNodeEnable(const std::vector<std::weak_ptr<RSSurfaceRenderNode>> & hwcNodes)649 void RSUniHwcVisitor::UpdateTransparentHwcNodeEnable(
650     const std::vector<std::weak_ptr<RSSurfaceRenderNode>>& hwcNodes)
651 {
652     for (size_t index = 1; index < hwcNodes.size(); ++index) {
653         auto transparentHwcNodeSPtr = hwcNodes[index].lock();
654         if (!transparentHwcNodeSPtr) {
655             continue;
656         }
657         const bool isTransparentEnableHwcNode = transparentHwcNodeSPtr->IsNodeHasBackgroundColorAlpha() &&
658             !transparentHwcNodeSPtr->IsHardwareForcedDisabled() && transparentHwcNodeSPtr->IsHardwareEnableHint();
659         if (!isTransparentEnableHwcNode) {
660             continue;
661         }
662         auto transparentDstRect = transparentHwcNodeSPtr->GetDstRect();
663         for (size_t lowerIndex = 0; lowerIndex < index; ++lowerIndex) {
664             // 'lowerHwcNode' means lower device composition layer.
665             auto lowerHwcNodeSPtr = hwcNodes[lowerIndex].lock();
666             if (!lowerHwcNodeSPtr || !lowerHwcNodeSPtr->IsHardwareForcedDisabled()) {
667                 continue;
668             }
669             auto lowerHwcNodeRect = lowerHwcNodeSPtr->GetDstRect();
670             bool isIntersect = !transparentDstRect.IntersectRect(lowerHwcNodeRect).IsEmpty();
671             if (isIntersect) {
672                 RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by transparent hwc node"
673                     " cover other disabled hwc node name:%s id:%" PRIu64,
674                     transparentHwcNodeSPtr->GetName().c_str(), transparentHwcNodeSPtr->GetId(),
675                     lowerHwcNodeSPtr->GetName().c_str(), lowerHwcNodeSPtr->GetId());
676                 transparentHwcNodeSPtr->SetHardwareForcedDisabledState(true);
677                 break;
678             }
679         }
680     }
681 }
682 
UpdateChildHwcNodeEnableByHwcNodeBelow(std::vector<RectI> & hwcRects,std::shared_ptr<RSSurfaceRenderNode> & appNode)683 void RSUniHwcVisitor::UpdateChildHwcNodeEnableByHwcNodeBelow(std::vector<RectI>& hwcRects,
684     std::shared_ptr<RSSurfaceRenderNode>& appNode)
685 {
686     const auto& hwcNodes = appNode->GetChildHardwareEnabledNodes();
687     for (auto hwcNode : hwcNodes) {
688         auto hwcNodePtr = hwcNode.lock();
689         if (!hwcNodePtr || !hwcNodePtr->IsOnTheTree()) {
690             continue;
691         }
692         UpdateHwcNodeEnableByHwcNodeBelowSelf(hwcRects, hwcNodePtr,
693             hwcNodePtr->GetIntersectedRoundCornerAABBsSize() != 0);
694     }
695 }
696 
UpdateHwcNodeEnableByHwcNodeBelowSelf(std::vector<RectI> & hwcRects,std::shared_ptr<RSSurfaceRenderNode> & hwcNode,bool isIntersectWithRoundCorner)697 void RSUniHwcVisitor::UpdateHwcNodeEnableByHwcNodeBelowSelf(std::vector<RectI>& hwcRects,
698     std::shared_ptr<RSSurfaceRenderNode>& hwcNode, bool isIntersectWithRoundCorner)
699 {
700     if (!uniRenderVisitor_.curScreenNode_) {
701         RS_LOGE("%{public}s: curDisplayNode is null", __func__);
702         return;
703     }
704     if (hwcNode->IsHardwareForcedDisabled()) {
705         if (RSHdrUtil::CheckIsHdrSurface(*hwcNode) != HdrStatus::NO_HDR) {
706             uniRenderVisitor_.curScreenNode_->SetHasUniRenderHdrSurface(true);
707         }
708         return;
709     }
710     auto absBound = hwcNode->GetRenderProperties().GetBoundsGeometry()->GetAbsRect();
711     if (!isIntersectWithRoundCorner) {
712         hwcRects.emplace_back(absBound);
713         return;
714     }
715     for (const auto& rect : hwcRects) {
716         for (auto& roundCornerAABB : hwcNode->GetIntersectedRoundCornerAABBs()) {
717             if (!roundCornerAABB.IntersectRect(rect).IsEmpty()) {
718                 if (hwcNode->GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED)) {
719                     continue;
720                 }
721                 auto parentNode = hwcNode->GetParent().lock();
722                 RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
723                     "corner radius + hwc node below, rect:%s", hwcNode->GetName().c_str(), hwcNode->GetId(),
724                     parentNode ? parentNode->GetId() : 0, rect.ToString().c_str());
725                 PrintHiperfLog(hwcNode, "corner radius + hwc node below");
726                 hwcNode->SetHardwareForcedDisabledState(true);
727                 if (RSHdrUtil::CheckIsHdrSurface(*hwcNode) != HdrStatus::NO_HDR) {
728                     uniRenderVisitor_.curScreenNode_->SetHasUniRenderHdrSurface(true);
729                 }
730                 Statistics().UpdateHwcDisabledReasonForDFX(hwcNode->GetId(),
731                     HwcDisabledReasons::DISABLED_BY_HWC_NODE_ABOVE, hwcNode->GetName());
732                 return;
733             }
734         }
735     }
736     hwcRects.emplace_back(absBound);
737 }
738 
UpdateHwcNodeEnableByHwcNodeBelowSelfInApp(const std::shared_ptr<RSSurfaceRenderNode> & hwcNode,std::vector<RectI> & hwcRects)739 void RSUniHwcVisitor::UpdateHwcNodeEnableByHwcNodeBelowSelfInApp(const std::shared_ptr<RSSurfaceRenderNode>& hwcNode,
740     std::vector<RectI>& hwcRects)
741 {
742     if (hwcNode->IsHardwareForcedDisabled()) {
743         return;
744     }
745     auto dst = hwcNode->GetDstRect();
746     if (hwcNode->GetAncoForceDoDirect()) {
747         hwcRects.emplace_back(dst);
748         return;
749     }
750     for (const auto& rect : hwcRects) {
751         const bool isIntersect = !dst.IntersectRect(rect).IsEmpty();
752         if (isIntersect && !RsCommonHook::Instance().GetHardwareEnabledByHwcnodeBelowSelfInAppFlag() &&
753             !hwcNode->IsHardwareEnableHint()) {
754             if (RsCommonHook::Instance().GetVideoSurfaceFlag() &&
755                 ((dst.GetBottom() - rect.GetTop() <= MIN_OVERLAP && dst.GetBottom() - rect.GetTop() >= 0) ||
756                  (rect.GetBottom() - dst.GetTop() <= MIN_OVERLAP && rect.GetBottom() - dst.GetTop() >= 0))) {
757                 return;
758             }
759             RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by hwc node below self in app",
760                 hwcNode->GetName().c_str(), hwcNode->GetId());
761             PrintHiperfLog(hwcNode, "hwc node below self in app");
762             hwcNode->SetHardwareForcedDisabledState(true);
763             Statistics().UpdateHwcDisabledReasonForDFX(hwcNode->GetId(),
764                 HwcDisabledReasons::DISABLED_BY_HWC_NODE_BELOW_SELF_IN_APP, hwcNode->GetName());
765             return;
766         }
767     }
768     hwcRects.emplace_back(dst);
769 }
770 
771 // called by windows from Top to Down
UpdateHardwareStateByBoundNEDstRectInApps(const std::vector<std::weak_ptr<RSSurfaceRenderNode>> & hwcNodes,std::vector<RectI> & abovedBounds)772 void RSUniHwcVisitor::UpdateHardwareStateByBoundNEDstRectInApps(
773     const std::vector<std::weak_ptr<RSSurfaceRenderNode>>& hwcNodes, std::vector<RectI>& abovedBounds)
774 {
775     // Traverse hwcNodes in a app from Top to Down.
776     for (auto reverseIter = hwcNodes.rbegin(); reverseIter != hwcNodes.rend(); ++reverseIter) {
777         auto hwcNodePtr = reverseIter->lock();
778         if (!hwcNodePtr || hwcNodePtr->IsHardwareForcedDisabled()) {
779             continue;
780         }
781 
782         RectI boundRect = hwcNodePtr->GetRenderProperties().GetBoundsGeometry()->GetAbsRect();
783         RectI dstRect = hwcNodePtr->GetDstRect();
784         if (!abovedBounds.empty()) {
785             bool intersectWithAbovedRect = std::any_of(abovedBounds.begin(), abovedBounds.end(),
786                 [&boundRect](const RectI& abovedBound) { return !abovedBound.IntersectRect(boundRect).IsEmpty(); });
787             if (intersectWithAbovedRect) {
788                 hwcNodePtr->SetHardwareForcedDisabledState(true);
789                 RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by aboved BoundNEDstRect hwcNode",
790                     hwcNodePtr->GetName().c_str(), hwcNodePtr->GetId());
791                 continue;
792             }
793         }
794 
795         // Anco nodes do not collect
796         if (hwcNodePtr->GetAncoForceDoDirect()) {
797             continue;
798         }
799 
800         // Check if the hwcNode's DstRect is inside of BoundRect, and not equal each other.
801         if (dstRect.IsInsideOf(boundRect) && dstRect != boundRect) {
802             abovedBounds.emplace_back(boundRect);
803         }
804     }
805 }
806 
UpdateHardwareStateByHwcNodeBackgroundAlpha(const std::vector<std::weak_ptr<RSSurfaceRenderNode>> & hwcNodes,RectI & backgroundAlphaRect,bool & isHardwareEnableByBackgroundAlpha)807 void RSUniHwcVisitor::UpdateHardwareStateByHwcNodeBackgroundAlpha(
808     const std::vector<std::weak_ptr<RSSurfaceRenderNode>>& hwcNodes, RectI& backgroundAlphaRect,
809     bool& isHardwareEnableByBackgroundAlpha)
810 {
811     std::list<RectI> hwcRects;
812     for (size_t i = 0; i < hwcNodes.size(); i++) {
813         auto hwcNodePtr = hwcNodes[i].lock();
814         if (!hwcNodePtr) {
815             continue;
816         }
817 
818         bool isIntersect = !backgroundAlphaRect.IntersectRect(
819             hwcNodePtr->GetRenderProperties().GetBoundsGeometry()->GetAbsRect()).IsEmpty();
820         if (isHardwareEnableByBackgroundAlpha && !hwcNodePtr->IsHardwareForcedDisabled() && isIntersect) {
821             hwcNodePtr->SetHardwareForcedDisabledState(true);
822             auto parentNode = hwcNodePtr->GetParent().lock();
823             RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
824                 "cannot cover above transparent hwc node", hwcNodePtr->GetName().c_str(),
825                 hwcNodePtr->GetId(), parentNode ? parentNode->GetId() : 0);
826             Statistics().UpdateHwcDisabledReasonForDFX(hwcNodePtr->GetId(),
827                 HwcDisabledReasons::DISABLED_BY_HWC_NODE_ABOVE, hwcNodePtr->GetName());
828             continue;
829         }
830 
831         if (!hwcNodePtr->IsNodeHasBackgroundColorAlpha() && !hwcNodePtr->IsHardwareForcedDisabled()) {
832             hwcRects.push_back(hwcNodePtr->GetDstRect());
833         } else if (hwcNodePtr->IsNodeHasBackgroundColorAlpha() && !hwcNodePtr->IsHardwareForcedDisabled() &&
834                    hwcRects.size() != 0 && (hwcRects.back().IsInsideOf(hwcNodePtr->GetDstRect()) ||
835                                             hwcNodePtr->GetDstRect().IsInsideOf(hwcRects.back()))) {
836             isHardwareEnableByBackgroundAlpha = true;
837             backgroundAlphaRect = hwcNodePtr->GetRenderProperties().GetBoundsGeometry()->GetAbsRect();
838             continue;
839         } else {
840             hwcNodePtr->SetHardwareForcedDisabledState(true);
841             auto parentNode = hwcNodePtr->GetParent().lock();
842             RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
843                 "hwc node backgound alpha", hwcNodePtr->GetName().c_str(), hwcNodePtr->GetId(),
844                 parentNode ? parentNode->GetId() : 0);
845             Statistics().UpdateHwcDisabledReasonForDFX(hwcNodePtr->GetId(),
846                 HwcDisabledReasons::DISABLED_BY_BACKGROUND_ALPHA, hwcNodePtr->GetName());
847         }
848     }
849 }
850 
IsBackgroundFilterUnderSurface(const std::shared_ptr<RSSurfaceRenderNode> & hwcNode,const std::shared_ptr<RSRenderNode> & filterNode)851 bool RSUniHwcVisitor::IsBackgroundFilterUnderSurface(const std::shared_ptr<RSSurfaceRenderNode>& hwcNode,
852     const std::shared_ptr<RSRenderNode>& filterNode)
853 {
854     auto buildRSRenderNodePath =
855         [this](const std::shared_ptr<RSRenderNode>& startNode) -> std::stack<std::shared_ptr<RSRenderNode>> {
856         std::stack<std::shared_ptr<RSRenderNode>> nodeStack;
857         auto currentNode = startNode;
858         while (currentNode && currentNode != uniRenderVisitor_.curSurfaceNode_) {
859             nodeStack.push(currentNode);
860             currentNode = currentNode->GetParent().lock();
861         }
862         if (currentNode != nullptr) {
863             nodeStack.push(currentNode);
864         }
865         return nodeStack;
866     };
867     std::stack<std::shared_ptr<RSRenderNode>> surfaceNodeStack = buildRSRenderNodePath(hwcNode);
868     std::stack<std::shared_ptr<RSRenderNode>> filterNodeStack = buildRSRenderNodePath(filterNode);
869     if (surfaceNodeStack.top() != filterNodeStack.top()) {
870         return false;
871     }
872 
873     std::shared_ptr<RSRenderNode> publicParentNode = nullptr;
874     while (surfaceNodeStack.size() > 1 && filterNodeStack.size() > 1 &&
875         surfaceNodeStack.top() == filterNodeStack.top()) {
876         publicParentNode = surfaceNodeStack.top();
877         surfaceNodeStack.pop();
878         filterNodeStack.pop();
879     }
880     if (!publicParentNode) {
881         return false;
882     }
883 
884     auto surfaceParent = surfaceNodeStack.top();
885     auto filterParent = filterNodeStack.top();
886     if (surfaceParent == filterParent) {
887         return (surfaceParent != hwcNode && filterParent == filterNode);
888     } else {
889         uint32_t surfaceZOrder = surfaceParent->GetHwcRecorder().GetZOrderForHwcEnableByFilter();
890         uint32_t filterZOrder = filterParent->GetHwcRecorder().GetZOrderForHwcEnableByFilter();
891         return publicParentNode->GetCurFrameInfoDetail().curFrameReverseChildren ?
892             (filterZOrder > surfaceZOrder) : (filterZOrder < surfaceZOrder);
893     }
894 }
895 
CalcHwcNodeEnableByFilterRect(std::shared_ptr<RSSurfaceRenderNode> & node,RSRenderNode & filterNode,uint32_t filterZOrder)896 void RSUniHwcVisitor::CalcHwcNodeEnableByFilterRect(std::shared_ptr<RSSurfaceRenderNode>& node,
897     RSRenderNode& filterNode, uint32_t filterZOrder)
898 {
899     if (!node) {
900         return;
901     }
902     if (filterZOrder != 0 && node->GetHwcRecorder().GetZOrderForHwcEnableByFilter() != 0 &&
903         node->GetInstanceRootNodeId() == filterNode.GetInstanceRootNodeId() &&
904         RSUniHwcComputeUtil::IsBlendNeedBackground(filterNode) && uniRenderVisitor_.curSurfaceNode_ &&
905         uniRenderVisitor_.curSurfaceNode_->GetId() == node->GetInstanceRootNodeId() &&
906         RsCommonHook::Instance().GetFilterUnderHwcConfigByApp(node->GetBundleName()) == "1") {
907         if (IsBackgroundFilterUnderSurface(node, filterNode.shared_from_this())) {
908             return;
909         }
910     }
911     auto bound = node->GetRenderProperties().GetBoundsGeometry()->GetAbsRect();
912     bool isIntersect = !bound.IntersectRect(filterNode.GetOldDirtyInSurface()).IsEmpty();
913     if (isIntersect) {
914         auto parentNode = node->GetParent().lock();
915         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
916             "filter rect, filterId:%" PRIu64, node->GetName().c_str(), node->GetId(),
917             parentNode ? parentNode->GetId() : 0, filterNode.GetId());
918         PrintHiperfLog(node, "filter rect");
919         node->SetHardwareForcedDisabledState(true);
920         node->HwcSurfaceRecorder().SetIntersectWithPreviousFilter(true);
921         Statistics().UpdateHwcDisabledReasonForDFX(node->GetId(),
922             HwcDisabledReasons::DISABLED_BY_FLITER_RECT, node->GetName());
923     }
924 }
925 
UpdateHwcNodeEnableByFilterRect(std::shared_ptr<RSSurfaceRenderNode> & node,RSRenderNode & filterNode,uint32_t filterZOrder)926 void RSUniHwcVisitor::UpdateHwcNodeEnableByFilterRect(std::shared_ptr<RSSurfaceRenderNode>& node,
927     RSRenderNode& filterNode, uint32_t filterZOrder)
928 {
929     if (filterNode.GetOldDirtyInSurface().IsEmpty()) {
930         return;
931     }
932     if (!node) {
933         const auto& selfDrawingNodes = RSMainThread::Instance()->GetSelfDrawingNodes();
934         if (selfDrawingNodes.empty()) {
935             return;
936         }
937         for (auto hwcNode : selfDrawingNodes) {
938             CalcHwcNodeEnableByFilterRect(hwcNode, filterNode, filterZOrder);
939         }
940     } else {
941         const auto& hwcNodes = node->GetChildHardwareEnabledNodes();
942         if (hwcNodes.empty()) {
943             return;
944         }
945         for (auto hwcNode : hwcNodes) {
946             auto hwcNodePtr = hwcNode.lock();
947             CalcHwcNodeEnableByFilterRect(hwcNodePtr, filterNode, filterZOrder);
948         }
949     }
950 }
951 
UpdateHwcNodeEnableByGlobalFilter(std::shared_ptr<RSSurfaceRenderNode> & node)952 void RSUniHwcVisitor::UpdateHwcNodeEnableByGlobalFilter(std::shared_ptr<RSSurfaceRenderNode>& node)
953 {
954     auto cleanFilter = transparentHwcCleanFilter_.find(node->GetId());
955     bool cleanFilterFound = (cleanFilter != transparentHwcCleanFilter_.end());
956     auto dirtyFilter = transparentHwcDirtyFilter_.find(node->GetId());
957     bool dirtyFilterFound = (dirtyFilter != transparentHwcDirtyFilter_.end());
958     auto& curMainAndLeashSurfaces = uniRenderVisitor_.curScreenNode_->GetAllMainAndLeashSurfaces();
959     for (auto it = curMainAndLeashSurfaces.rbegin(); it != curMainAndLeashSurfaces.rend(); ++it) {
960         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
961         if (surfaceNode == nullptr) {
962             continue;
963         }
964         if (surfaceNode->GetId() == node->GetId()) {
965             return;
966         }
967         const auto& hwcNodes = surfaceNode->GetChildHardwareEnabledNodes();
968         if (hwcNodes.empty()) {
969             continue;
970         }
971         for (auto& hwcNode : hwcNodes) {
972             auto hwcNodePtr = hwcNode.lock();
973             if (!hwcNodePtr || hwcNodePtr->IsHardwareForcedDisabled()) {
974                 continue;
975             }
976             if (cleanFilterFound) {
977                 UpdateHwcNodeEnableByGlobalCleanFilter(cleanFilter->second, *hwcNodePtr);
978                 if (hwcNodePtr->IsHardwareForcedDisabled()) {
979                     continue;
980                 }
981             }
982             if (dirtyFilterFound) {
983                 UpdateHwcNodeEnableByGlobalDirtyFilter(dirtyFilter->second, *hwcNodePtr);
984                 if (hwcNodePtr->IsHardwareForcedDisabled()) {
985                     continue;
986                 }
987             }
988         }
989     }
990 }
991 
IntersectHwcDamage(RSSurfaceRenderNode & hwcNode,const RectI & filterRect)992 bool RSUniHwcVisitor::IntersectHwcDamage(RSSurfaceRenderNode& hwcNode, const RectI& filterRect)
993 {
994     // Intersection judgment of layer boundaries has already been conducted
995     bool isIntersect = true;
996 #ifndef ROSEN_CROSS_PLATFORM
997     if (RSSystemProperties::GetAIBarOptEnabled()) {
998         auto surfaceHandler = hwcNode.GetRSSurfaceHandler();
999         if (surfaceHandler && surfaceHandler->IsCurrentFrameBufferConsumed()) {
1000             auto rect = surfaceHandler->GetDamageRegion();
1001             const auto& matrix = hwcNode.GetBufferRelMatrix();
1002             auto bufferDirtyRect = hwcNode.GetRenderProperties().GetBoundsGeometry()->MapRect(
1003                 RectF(rect.x, rect.y, rect.w, rect.h), matrix);
1004             isIntersect = bufferDirtyRect.Intersect(filterRect);
1005             RS_OPTIONAL_TRACE_FMT("RSUniHwcVisitor::IntersectHwcDamage "
1006                 "bufferDirtyRect: [%d,%d,%d,%d] filterRect: [%d,%d,%d,%d]",
1007                 bufferDirtyRect.GetLeft(), bufferDirtyRect.GetTop(),
1008                 bufferDirtyRect.GetWidth(), bufferDirtyRect.GetHeight(),
1009                 filterRect.GetLeft(), filterRect.GetTop(),
1010                 filterRect.GetWidth(), filterRect.GetHeight());
1011         }
1012     }
1013 #endif
1014     RS_OPTIONAL_TRACE_FMT("RSUniHwcVisitor::IntersectHwcDamage isIntersect: %d", isIntersect);
1015     return isIntersect;
1016 }
1017 
UpdateHwcNodeEnableByGlobalCleanFilter(const std::vector<std::pair<NodeId,RectI>> & cleanFilter,RSSurfaceRenderNode & hwcNode)1018 void RSUniHwcVisitor::UpdateHwcNodeEnableByGlobalCleanFilter(
1019     const std::vector<std::pair<NodeId, RectI>>& cleanFilter, RSSurfaceRenderNode& hwcNode)
1020 {
1021     const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
1022     bool intersectedWithAIBar = false;
1023     bool checkDrawAIBar = false;
1024     for (auto filter = cleanFilter.begin(); filter != cleanFilter.end(); ++filter) {
1025         auto geo = hwcNode.GetRenderProperties().GetBoundsGeometry();
1026         if (!geo->GetAbsRect().IntersectRect(filter->second).IsEmpty()) {
1027             auto& renderNode = nodeMap.GetRenderNode<RSRenderNode>(filter->first);
1028             if (renderNode == nullptr) {
1029                 ROSEN_LOGD("UpdateHwcNodeByFilter: renderNode is null");
1030                 continue;
1031             }
1032 
1033             if (renderNode->IsAIBarFilter()) {
1034                 intersectedWithAIBar = true;
1035                 bool intersectHwcDamage = IntersectHwcDamage(hwcNode, filter->second);
1036                 if (renderNode->CheckAndUpdateAIBarCacheStatus(intersectHwcDamage)) {
1037                     ROSEN_LOGD("UpdateHwcNodeByFilter: skip intersection for using cache");
1038                     continue;
1039                 } else if (RSSystemProperties::GetHveFilterEnabled()) {
1040                     checkDrawAIBar = true;
1041                     continue;
1042                 }
1043             }
1044             auto parentNode = hwcNode.GetParent().lock();
1045             RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
1046                 "transparentCleanFilter, filterId:%" PRIu64, hwcNode.GetName().c_str(), hwcNode.GetId(),
1047                 parentNode ? parentNode->GetId() : 0, filter->first);
1048             PrintHiperfLog(&hwcNode, "transparentCleanFilter");
1049             hwcNode.SetHardwareForcedDisabledState(true);
1050             Statistics().UpdateHwcDisabledReasonForDFX(hwcNode.GetId(),
1051                 HwcDisabledReasons::DISABLED_BY_TRANSPARENT_CLEAN_FLITER, hwcNode.GetName());
1052             break;
1053         }
1054     }
1055     RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64", checkDrawAIBar:%d, intersectedWithAIBar:%d",
1056         hwcNode.GetName().c_str(), hwcNode.GetId(), checkDrawAIBar, intersectedWithAIBar);
1057     if (checkDrawAIBar) {
1058         hwcNode.SetHardwareNeedMakeImage(checkDrawAIBar);
1059     }
1060     if (intersectedWithAIBar) {
1061         hwcNode.SetIntersectWithAIBar(intersectedWithAIBar);
1062     }
1063 }
1064 
UpdateHwcNodeEnableByGlobalDirtyFilter(const std::vector<std::pair<NodeId,RectI>> & dirtyFilter,RSSurfaceRenderNode & hwcNode)1065 void RSUniHwcVisitor::UpdateHwcNodeEnableByGlobalDirtyFilter(
1066     const std::vector<std::pair<NodeId, RectI>>& dirtyFilter, RSSurfaceRenderNode& hwcNode)
1067 {
1068     const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
1069     for (auto filter = dirtyFilter.begin(); filter != dirtyFilter.end(); ++filter) {
1070         auto geo = hwcNode.GetRenderProperties().GetBoundsGeometry();
1071         if (!geo->GetAbsRect().IntersectRect(filter->second).IsEmpty()) {
1072             auto parentNode = hwcNode.GetParent().lock();
1073             RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
1074                 "transparentDirtyFilter, filterId:%" PRIu64, hwcNode.GetName().c_str(), hwcNode.GetId(),
1075                 parentNode ? parentNode->GetId() : 0, filter->first);
1076             PrintHiperfLog(&hwcNode, "transparentDirtyFilter");
1077             hwcNode.SetHardwareForcedDisabledState(true);
1078             Statistics().UpdateHwcDisabledReasonForDFX(hwcNode.GetId(),
1079                 HwcDisabledReasons::DISABLED_BY_TRANSPARENT_DIRTY_FLITER, hwcNode.GetName());
1080             break;
1081         }
1082     }
1083 }
1084 
UpdateHwcNodeRectInSkippedSubTree(const RSRenderNode & rootNode)1085 void RSUniHwcVisitor::UpdateHwcNodeRectInSkippedSubTree(const RSRenderNode& rootNode)
1086 {
1087     if (!uniRenderVisitor_.curSurfaceNode_ || RS_PROFILER_SHOULD_BLOCK_HWCNODE()) {
1088         return;
1089     }
1090     const auto& hwcNodes = uniRenderVisitor_.curSurfaceNode_->GetChildHardwareEnabledNodes();
1091     if (hwcNodes.empty()) {
1092         return;
1093     }
1094     for (auto hwcNode : hwcNodes) {
1095         auto hwcNodePtr = hwcNode.lock();
1096         if (!hwcNodePtr || !hwcNodePtr->IsOnTheTree() || hwcNodePtr->GetCalcRectInPrepare()) {
1097             continue;
1098         }
1099         if (!hwcNodePtr->GetRSSurfaceHandler() || !hwcNodePtr->GetRSSurfaceHandler()->GetBuffer()) {
1100             auto parentNode = hwcNodePtr->GetParent().lock();
1101             RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
1102                 "no buffer in skippedSubTree, HasBuffer[%d]", hwcNodePtr->GetName().c_str(),
1103                 hwcNodePtr->GetId(), parentNode ? parentNode->GetId() : 0,
1104                 hwcNodePtr->GetRSSurfaceHandler() && hwcNodePtr->GetRSSurfaceHandler()->GetBuffer());
1105             hwcNodePtr->SetHardwareForcedDisabledState(true);
1106             continue;
1107         }
1108         auto renderNode = hwcNodePtr->ReinterpretCastTo<RSRenderNode>();
1109         if (!IsFindRootSuccess(renderNode, rootNode)) {
1110             continue;
1111         }
1112         RectI clipRect;
1113         Drawing::Matrix matrix = rootNode.GetRenderProperties().GetBoundsGeometry()->GetAbsMatrix();
1114         UpdateHwcNodeClipRectAndMatrix(hwcNodePtr, rootNode, clipRect, matrix);
1115         auto surfaceHandler = hwcNodePtr->GetMutableRSSurfaceHandler();
1116         auto& properties = hwcNodePtr->GetMutableRenderProperties();
1117         auto offset = std::nullopt;
1118         properties.UpdateGeometryByParent(&matrix, offset);
1119         const auto& geoPtr = properties.GetBoundsGeometry();
1120         const auto& originalMatrix = geoPtr->GetMatrix();
1121         matrix.PreConcat(originalMatrix);
1122         Drawing::Rect bounds = Drawing::Rect(0, 0, properties.GetBoundsWidth(), properties.GetBoundsHeight());
1123         Drawing::Rect absRect;
1124         matrix.MapRect(absRect, bounds);
1125         RectI rect;
1126         rect.left_ = static_cast<int>(std::floor(absRect.GetLeft()));
1127         rect.top_ = static_cast<int>(std::floor(absRect.GetTop()));
1128         rect.width_ = static_cast<int>(std::ceil(absRect.GetRight() - rect.left_));
1129         rect.height_ = static_cast<int>(std::ceil(absRect.GetBottom() - rect.top_));
1130         UpdateCrossInfoForProtectedHwcNode(*hwcNodePtr);
1131         UpdateDstRect(*hwcNodePtr, rect, clipRect);
1132         UpdateHwcNodeInfo(*hwcNodePtr, matrix, rect, true);
1133         hwcNodePtr->SetTotalMatrix(matrix);
1134         hwcNodePtr->SetOldDirtyInSurface(geoPtr->MapRect(hwcNodePtr->GetSelfDrawRect(), matrix));
1135     }
1136 }
1137 
IsFindRootSuccess(std::shared_ptr<RSRenderNode> & parent,const RSRenderNode & rootNode)1138 bool RSUniHwcVisitor::IsFindRootSuccess(std::shared_ptr<RSRenderNode>& parent, const RSRenderNode& rootNode)
1139 {
1140     bool isFindInRootSubTree = false;
1141     do {
1142         auto cloneNodeParent = parent->GetCurCloneNodeParent().lock();
1143         parent = cloneNodeParent ? cloneNodeParent : parent->GetParent().lock();
1144         if (!parent) {
1145             break;
1146         }
1147         isFindInRootSubTree |= parent->GetId() == rootNode.GetId();
1148     } while (!isFindInRootSubTree && parent != uniRenderVisitor_.curSurfaceNode_);
1149     return isFindInRootSubTree;
1150 }
1151 
UpdateHwcNodeClipRect(const std::shared_ptr<RSRenderNode> & hwcNodeParent,Drawing::Rect & childRectMapped)1152 void RSUniHwcVisitor::UpdateHwcNodeClipRect(const std::shared_ptr<RSRenderNode>& hwcNodeParent,
1153     Drawing::Rect& childRectMapped)
1154 {
1155     if (hwcNodeParent->GetType() != RSRenderNodeType::CANVAS_NODE) {
1156         return;
1157     }
1158 
1159     const auto& parentProperties = hwcNodeParent->GetRenderProperties();
1160     const auto& parentGeoPtr = parentProperties.GetBoundsGeometry();
1161     const auto& matrix = parentGeoPtr->GetMatrix();
1162     matrix.MapRect(childRectMapped, childRectMapped);
1163 
1164     const auto ApplyClip = [&childRectMapped, &matrix](const Drawing::Rect& rect) {
1165         Drawing::Rect clipRect;
1166         matrix.MapRect(clipRect, rect);
1167         RSUniHwcComputeUtil::IntersectRect(childRectMapped, clipRect);
1168     };
1169 
1170     if (parentProperties.GetClipToBounds()) {
1171         const auto& selfDrawRectF = hwcNodeParent->GetSelfDrawRect();
1172         Drawing::Rect clipSelfDrawRect(selfDrawRectF.left_, selfDrawRectF.top_,
1173             selfDrawRectF.GetRight(), selfDrawRectF.GetBottom());
1174         ApplyClip(clipSelfDrawRect);
1175     }
1176     if (parentProperties.GetClipToFrame()) {
1177         auto left = parentProperties.GetFrameOffsetX() * matrix.Get(Drawing::Matrix::SCALE_X);
1178         auto top = parentProperties.GetFrameOffsetY() * matrix.Get(Drawing::Matrix::SCALE_Y);
1179         Drawing::Rect clipFrameRect(
1180             left, top, left + parentProperties.GetFrameWidth(), top + parentProperties.GetFrameHeight());
1181         ApplyClip(clipFrameRect);
1182     }
1183     if (parentProperties.GetClipToRRect()) {
1184         const RectF& rectF = parentProperties.GetClipRRect().rect_;
1185         Drawing::Rect clipRect(rectF.left_, rectF.top_, rectF.GetRight(), rectF.GetBottom());
1186         ApplyClip(clipRect);
1187     }
1188 }
1189 
UpdateHwcNodeMatrix(const std::shared_ptr<RSRenderNode> & hwcNodeParent,Drawing::Matrix & accumulatedMatrix)1190 void RSUniHwcVisitor::UpdateHwcNodeMatrix(const std::shared_ptr<RSRenderNode>& hwcNodeParent,
1191     Drawing::Matrix& accumulatedMatrix)
1192 {
1193     if (auto opt = RSUniHwcComputeUtil::GetMatrix(hwcNodeParent)) {
1194         accumulatedMatrix.PostConcat(opt.value());
1195     }
1196 }
1197 
UpdateHwcNodeClipRectAndMatrix(const std::shared_ptr<RSSurfaceRenderNode> & hwcNodePtr,const RSRenderNode & rootNode,RectI & clipRect,Drawing::Matrix & matrix)1198 void RSUniHwcVisitor::UpdateHwcNodeClipRectAndMatrix(const std::shared_ptr<RSSurfaceRenderNode>& hwcNodePtr,
1199     const RSRenderNode& rootNode, RectI& clipRect, Drawing::Matrix& matrix)
1200 {
1201     // The value here represents an imaginary plane of infinite width and infinite height,
1202     // using values summarized empirically.
1203     constexpr float MAX_FLOAT = std::numeric_limits<float>::max() * 1e-30;
1204     Drawing::Rect childRectMapped(0.0f, 0.0f, MAX_FLOAT, MAX_FLOAT);
1205     Drawing::Matrix accumulatedMatrix;
1206     RSRenderNode::SharedPtr hwcNodeParent = hwcNodePtr;
1207     while (hwcNodeParent && hwcNodeParent->GetType() != RSRenderNodeType::SCREEN_NODE &&
1208            hwcNodeParent->GetId() != rootNode.GetId()) {
1209         UpdateHwcNodeClipRect(hwcNodeParent, childRectMapped);
1210         if (hwcNodePtr->GetId() != hwcNodeParent->GetId()) {
1211             UpdateHwcNodeMatrix(hwcNodeParent, accumulatedMatrix);
1212         }
1213         auto cloneNodeParent = hwcNodeParent->GetCurCloneNodeParent().lock();
1214         hwcNodeParent = cloneNodeParent ? cloneNodeParent : hwcNodeParent->GetParent().lock();
1215     }
1216     Drawing::Rect absClipRect;
1217     matrix.MapRect(absClipRect, childRectMapped);
1218     Drawing::Rect prepareClipRect(uniRenderVisitor_.prepareClipRect_.left_,
1219                                   uniRenderVisitor_.prepareClipRect_.top_,
1220                                   uniRenderVisitor_.prepareClipRect_.GetRight(),
1221                                   uniRenderVisitor_.prepareClipRect_.GetBottom());
1222     RSUniHwcComputeUtil::IntersectRect(absClipRect, prepareClipRect);
1223     clipRect.left_ = static_cast<int>(std::floor(absClipRect.GetLeft()));
1224     clipRect.top_ = static_cast<int>(std::floor(absClipRect.GetTop()));
1225     clipRect.width_ = static_cast<int>(std::ceil(absClipRect.GetRight() - clipRect.left_));
1226     clipRect.height_ = static_cast<int>(std::ceil(absClipRect.GetBottom() - clipRect.top_));
1227     matrix.PreConcat(accumulatedMatrix);
1228 }
1229 
UpdatePrepareClip(RSRenderNode & node)1230 void RSUniHwcVisitor::UpdatePrepareClip(RSRenderNode& node)
1231 {
1232     const auto& property = node.GetRenderProperties();
1233     auto& geoPtr = property.GetBoundsGeometry();
1234     // Dirty Region use abstract coordinate, property of node use relative coordinate
1235     // BoundsRect(if exists) is mapped to absRect_ of RSObjAbsGeometry.
1236     if (property.GetClipToBounds()) {
1237         uniRenderVisitor_.prepareClipRect_ =
1238             uniRenderVisitor_.prepareClipRect_.IntersectRect(geoPtr->GetAbsRect());
1239     }
1240     // FrameRect(if exists) is mapped to rect using abstract coordinate explicitly by calling MapAbsRect.
1241     if (property.GetClipToFrame()) {
1242         // MapAbsRect do not handle the translation of OffsetX and OffsetY
1243         RectF frameRect{
1244             property.GetFrameOffsetX() * geoPtr->GetAbsMatrix().Get(Drawing::Matrix::SCALE_X),
1245             property.GetFrameOffsetY() * geoPtr->GetAbsMatrix().Get(Drawing::Matrix::SCALE_Y),
1246             property.GetFrameWidth(), property.GetFrameHeight()};
1247         uniRenderVisitor_.prepareClipRect_ =
1248             uniRenderVisitor_.prepareClipRect_.IntersectRect(geoPtr->MapAbsRect(frameRect));
1249     }
1250     if (property.GetClipToRRect()) {
1251         RectF rect = property.GetClipRRect().rect_;
1252         uniRenderVisitor_.prepareClipRect_ =
1253             uniRenderVisitor_.prepareClipRect_.IntersectRect(geoPtr->MapAbsRect(rect));
1254     }
1255 }
1256 
UpdateTopSurfaceSrcRect(RSSurfaceRenderNode & node,const Drawing::Matrix & absMatrix,const RectI & absRect)1257 void RSUniHwcVisitor::UpdateTopSurfaceSrcRect(RSSurfaceRenderNode& node,
1258     const Drawing::Matrix& absMatrix, const RectI& absRect)
1259 {
1260     auto canvas = std::make_unique<Rosen::Drawing::Canvas>(uniRenderVisitor_.curScreenNode_->GetScreenInfo().phyWidth,
1261                                                            uniRenderVisitor_.curScreenNode_->GetScreenInfo().phyHeight);
1262     canvas->ConcatMatrix(absMatrix);
1263 
1264     const auto& dstRect = node.GetDstRect();
1265     Drawing::RectI dst = { dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom() };
1266     node.UpdateSrcRect(*canvas.get(), dst);
1267     if (node.GetRSSurfaceHandler() && node.GetRSSurfaceHandler()->GetBuffer()) {
1268         RSUniHwcComputeUtil::UpdateRealSrcRect(node, absRect);
1269     }
1270 }
1271 
IsDisableHwcOnExpandScreen() const1272 bool RSUniHwcVisitor::IsDisableHwcOnExpandScreen() const
1273 {
1274     if (uniRenderVisitor_.curScreenNode_ == nullptr) {
1275         RS_LOGE("curScreenNode is null");
1276         return false;
1277     }
1278 
1279     // screenId > 0 means non-primary screen normally.
1280     return HWCParam::IsDisableHwcOnExpandScreen() &&
1281         uniRenderVisitor_.curScreenNode_->GetScreenId() > 0;
1282 }
1283 
UpdateHwcNodeInfo(RSSurfaceRenderNode & node,const Drawing::Matrix & absMatrix,const RectI & absRect,bool subTreeSkipped)1284 void RSUniHwcVisitor::UpdateHwcNodeInfo(RSSurfaceRenderNode& node,
1285     const Drawing::Matrix& absMatrix, const RectI& absRect, bool subTreeSkipped)
1286 {
1287     node.SetHardwareForcedDisabledState(node.HwcSurfaceRecorder().IsIntersectWithPreviousFilter());
1288     if (node.HwcSurfaceRecorder().IsIntersectWithPreviousFilter()) {
1289         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by node intersect with previous filter",
1290             node.GetName().c_str(), node.GetId());
1291     }
1292     node.HwcSurfaceRecorder().SetIntersectWithPreviousFilter(false);
1293     node.SetInFixedRotation(uniRenderVisitor_.displayNodeRotationChanged_ ||
1294                             uniRenderVisitor_.isScreenRotationAnimating_);
1295     bool isHardwareForcedDisabled = !node.GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED) &&
1296         (!uniRenderVisitor_.IsHardwareComposerEnabled() || !node.IsDynamicHardwareEnable() ||
1297          IsDisableHwcOnExpandScreen() || uniRenderVisitor_.curSurfaceNode_->GetVisibleRegion().IsEmpty() ||
1298          !node.GetRSSurfaceHandler() || !node.GetRSSurfaceHandler()->GetBuffer());
1299     if (isHardwareForcedDisabled) {
1300         auto parentNode = node.GetParent().lock();
1301         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " parentId:%" PRIu64 " disabled by "
1302             "param/invisible/no buffer, IsHardwareComposerEnabled[%d], IsDynamicHardwareEnable[%d], "
1303             "IsDisableHwcOnExpandScreen[%d], IsVisibleRegionEmpty[%d], HasBuffer[%d]", node.GetName().c_str(),
1304             node.GetId(), parentNode ? parentNode->GetId() : 0,
1305             uniRenderVisitor_.IsHardwareComposerEnabled(), node.IsDynamicHardwareEnable(),
1306             IsDisableHwcOnExpandScreen(), uniRenderVisitor_.curSurfaceNode_->GetVisibleRegion().IsEmpty(),
1307             node.GetRSSurfaceHandler() && node.GetRSSurfaceHandler()->GetBuffer());
1308         PrintHiperfLog(&node, "param/invisible/no buffer");
1309         node.SetHardwareForcedDisabledState(true);
1310         Statistics().UpdateHwcDisabledReasonForDFX(node.GetId(),
1311             HwcDisabledReasons::DISABLED_BY_INVALID_PARAM, node.GetName());
1312         if (!node.GetFixRotationByUser() && !subTreeSkipped) {
1313             return;
1314         }
1315     }
1316     UpdateSrcRect(node, absMatrix);
1317     UpdateHwcNodeEnableByBackgroundAlpha(node);
1318     UpdateHwcNodeByTransform(node, absMatrix);
1319     // dstRect transform to global position after UpdateHwcNodeByTransform
1320     UpdateDstRectByGlobalPosition(node);
1321     UpdateHwcNodeEnableByBufferSize(node);
1322 }
1323 
UpdateDstRectByGlobalPosition(RSSurfaceRenderNode & node)1324 void RSUniHwcVisitor::UpdateDstRectByGlobalPosition(RSSurfaceRenderNode& node)
1325 {
1326     // dstRect transform to globalposition when node is move
1327     if (node.GetHwcGlobalPositionEnabled()) {
1328         auto dstRect = node.GetDstRect();
1329         dstRect.left_ += uniRenderVisitor_.curScreenNode_->GetScreenOffsetX();
1330         dstRect.top_ += uniRenderVisitor_.curScreenNode_->GetScreenOffsetY();
1331         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " dstRect:[%s]",
1332             node.GetName().c_str(), node.GetId(), dstRect.ToString().c_str());
1333         node.SetDstRect(dstRect);
1334     }
1335 }
1336 
QuickPrepareChildrenOnlyOrder(RSRenderNode & node)1337 void RSUniHwcVisitor::QuickPrepareChildrenOnlyOrder(RSRenderNode& node)
1338 {
1339     const auto orderFunc = [this](const std::shared_ptr<RSRenderNode>& child) {
1340         if (!child) {
1341             return;
1342         }
1343         child->GetHwcRecorder().SetZOrderForHwcEnableByFilter(curZOrderForHwcEnableByFilter_++);
1344         QuickPrepareChildrenOnlyOrder(*child);
1345     };
1346 
1347     auto children = node.GetSortedChildren();
1348     if (uniRenderVisitor_.NeedPrepareChindrenInReverseOrder(node)) {
1349         std::for_each((*children).rbegin(), (*children).rend(), orderFunc);
1350     } else {
1351         std::for_each((*children).begin(), (*children).end(), orderFunc);
1352     }
1353 }
1354 
UpdateCrossInfoForProtectedHwcNode(RSSurfaceRenderNode & hwcNode)1355 void RSUniHwcVisitor::UpdateCrossInfoForProtectedHwcNode(RSSurfaceRenderNode& hwcNode)
1356 {
1357     if (hwcNode.GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED)) {
1358         auto firstLevelNode =
1359             RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(hwcNode.GetFirstLevelNode());
1360         if (firstLevelNode) {
1361             hwcNode.SetHwcGlobalPositionEnabled(firstLevelNode->GetGlobalPositionEnabled());
1362             hwcNode.SetHwcCrossNode(firstLevelNode->IsFirstLevelCrossNode());
1363         }
1364     }
1365 }
1366 
PrintHiperfCounterLog(const char * const counterContext,uint64_t counter)1367 void RSUniHwcVisitor::PrintHiperfCounterLog(const char* const counterContext, uint64_t counter)
1368 {
1369 #ifdef HIPERF_TRACE_ENABLE
1370     RS_LOGW("hiperf_surface_%{public}s %{public}" PRIu64, counterContext, counter);
1371 #endif
1372 }
1373 
PrintHiperfLog(RSSurfaceRenderNode * node,const char * const disabledContext)1374 void RSUniHwcVisitor::PrintHiperfLog(RSSurfaceRenderNode* node, const char* const disabledContext)
1375 {
1376 #ifdef HIPERF_TRACE_ENABLE
1377     RS_LOGW("hiperf_surface: name:%{public}s disabled by %{public}s "
1378         "surfaceRect:[%{public}d, %{public}d, %{public}d, %{public}d]->"
1379         "[%{public}d, %{public}d, %{public}d, %{public}d]",
1380         node->GetName().c_str(), disabledContext,
1381         node->GetSrcRect().GetLeft(), node->GetSrcRect().GetRight(),
1382         node->GetSrcRect().GetTop(), node->GetSrcRect().GetBottom(),
1383         node->GetDstRect().GetLeft(), node->GetDstRect().GetRight(),
1384         node->GetDstRect().GetTop(), node->GetDstRect().GetBottom());
1385 #endif
1386 }
1387 
PrintHiperfLog(const std::shared_ptr<RSSurfaceRenderNode> & node,const char * const disabledContext)1388 void RSUniHwcVisitor::PrintHiperfLog(const std::shared_ptr<RSSurfaceRenderNode>& node, const char* const disabledContext)
1389 {
1390     PrintHiperfLog(node.get(), disabledContext);
1391 }
1392 
1393 } // namespace Rosen
1394 } // namespace OHOS