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