• 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 "rs_uni_hwc_compute_util.h"
16 
17 #include "hwc/rs_hwc_recorder.h"
18 #include "modifier/rs_render_property.h"
19 #include "property/rs_properties_painter.h"
20 
21 #include "common/rs_optional_trace.h"
22 
23 #undef LOG_TAG
24 #define LOG_TAG "RSUniHwcComputeUtil"
25 
26 namespace OHOS {
27 namespace Rosen {
28 // Only can be used by smart pointer and raw pointer
29 // If any nullptr is found, it will return immediately
30 #define CHECK_NULL_VOID(...)                                    \
31     do {                                                        \
32         if (RSUniHwcComputeUtil::IS_ANY_NULLPTR(__VA_ARGS__)) { \
33             return;                                             \
34         }                                                       \
35     } while (0)
36 
GetRotateTransformForRotationFixed(RSSurfaceRenderNode & node,sptr<IConsumerSurface> consumer)37 GraphicTransformType RSUniHwcComputeUtil::GetRotateTransformForRotationFixed(RSSurfaceRenderNode& node,
38     sptr<IConsumerSurface> consumer)
39 {
40     auto transformType = RSBaseRenderUtil::GetRotateTransform(RSBaseRenderUtil::GetSurfaceBufferTransformType(
41         node.GetRSSurfaceHandler()->GetConsumer(), node.GetRSSurfaceHandler()->GetBuffer()));
42     int extraRotation = 0;
43     int degree = static_cast<int>(round(node.GetAbsRotation()));
44     auto surfaceParams = node.GetStagingRenderParams() == nullptr
45                              ? nullptr
46                              : static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
47     int32_t rotationDegree = RSBaseRenderUtil::GetScreenRotationOffset(surfaceParams);
48     extraRotation = (degree - rotationDegree) % ROUND_ANGLE;
49     transformType = static_cast<GraphicTransformType>(
50         (transformType + extraRotation / RS_ROTATION_90 + SCREEN_ROTATION_NUM) % SCREEN_ROTATION_NUM);
51     return transformType;
52 }
53 
GetConsumerTransform(const RSSurfaceRenderNode & node,const sptr<SurfaceBuffer> & buffer,const sptr<IConsumerSurface> & consumer)54 GraphicTransformType RSUniHwcComputeUtil::GetConsumerTransform(const RSSurfaceRenderNode& node,
55     const sptr<SurfaceBuffer>& buffer, const sptr<IConsumerSurface>& consumer)
56 {
57     auto transformType = GraphicTransformType::GRAPHIC_ROTATE_NONE;
58     if (consumer != nullptr && buffer != nullptr) {
59         if (consumer->GetSurfaceBufferTransformType(buffer, &transformType) != GSERROR_OK) {
60             RS_LOGE("GetConsumerTransform GetSurfaceBufferTransformType failed");
61         }
62     }
63     GraphicTransformType consumerTransform = RSBaseRenderUtil::GetRotateTransform(transformType);
64     return consumerTransform;
65 }
66 
IsHwcEnabledByGravity(RSSurfaceRenderNode & node,const Gravity frameGravity)67 bool RSUniHwcComputeUtil::IsHwcEnabledByGravity(RSSurfaceRenderNode& node, const Gravity frameGravity)
68 {
69     // When renderfit mode is not Gravity::RESIZE or Gravity::TOP_LEFT,
70     // we currently disable hardware composer.
71     if (frameGravity != Gravity::RESIZE && frameGravity != Gravity::TOP_LEFT &&
72         !node.GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED)) {
73         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by frameGravity[%d]",
74             node.GetName().c_str(), node.GetId(), static_cast<int32_t>(frameGravity));
75         node.SetHardwareForcedDisabledState(true);
76         return false;
77     }
78     return true;
79 }
80 
CalcSrcRectByBufferRotation(const SurfaceBuffer & buffer,const GraphicTransformType consumerTransformType,Drawing::Rect newSrcRect)81 Drawing::Rect RSUniHwcComputeUtil::CalcSrcRectByBufferRotation(const SurfaceBuffer& buffer,
82     const GraphicTransformType consumerTransformType, Drawing::Rect newSrcRect)
83 {
84     const auto frameWidth = buffer.GetSurfaceBufferWidth();
85     const auto frameHeight = buffer.GetSurfaceBufferHeight();
86     auto left = newSrcRect.left_;
87     auto top = newSrcRect.top_;
88     auto width = newSrcRect.right_ - newSrcRect.left_;
89     auto height = newSrcRect.bottom_ - newSrcRect.top_;
90     switch (consumerTransformType) {
91         case GraphicTransformType::GRAPHIC_ROTATE_90: {
92             newSrcRect = Drawing::Rect(frameWidth - width - left, top, frameWidth - left, top + height);
93             break;
94         }
95         case GraphicTransformType::GRAPHIC_ROTATE_180: {
96             newSrcRect = Drawing::Rect(frameWidth - width - left, frameHeight - height - top,
97                 frameWidth - left, frameHeight - top);
98             break;
99         }
100         case GraphicTransformType::GRAPHIC_ROTATE_270: {
101             newSrcRect = Drawing::Rect(left, frameHeight - height - top, left + width, frameHeight - top);
102             break;
103         }
104         default:
105             break;
106     }
107     newSrcRect.left_ = std::clamp<int32_t>(std::floor(newSrcRect.GetLeft()), 0, frameWidth);
108     newSrcRect.top_ = std::clamp<int32_t>(std::floor(newSrcRect.GetTop()), 0, frameHeight);
109     newSrcRect.right_ = std::clamp<int32_t>(std::ceil(newSrcRect.GetRight()), newSrcRect.left_, frameWidth);
110     newSrcRect.bottom_ = std::clamp<int32_t>(std::ceil(newSrcRect.GetBottom()), newSrcRect.top_, frameHeight);
111     return newSrcRect;
112 }
113 
DealWithNodeGravity(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix)114 void RSUniHwcComputeUtil::DealWithNodeGravity(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix)
115 {
116     auto surfaceHandler = node.GetRSSurfaceHandler();
117     if (!surfaceHandler) {
118         return;
119     }
120     const auto buffer = surfaceHandler->GetBuffer();
121     const auto consumer = surfaceHandler->GetConsumer();
122     if (!consumer || !buffer) {
123         return;
124     }
125     float bufferWidth = buffer->GetSurfaceBufferWidth();
126     float bufferHeight = buffer->GetSurfaceBufferHeight();
127     const float boundsWidth = node.GetRenderProperties().GetBoundsWidth();
128     const float boundsHeight = node.GetRenderProperties().GetBoundsHeight();
129     const Gravity frameGravity = node.GetRenderProperties().GetFrameGravity();
130     const GraphicTransformType consumerTransformType = node.GetFixRotationByUser() ?
131         GetRotateTransformForRotationFixed(node, consumer) : GetConsumerTransform(node, buffer, consumer);
132     CheckForceHardwareAndUpdateDstRect(node);
133     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
134         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
135         std::swap(bufferWidth, bufferHeight);
136     }
137     Drawing::Matrix gravityMatrix;
138     RSPropertiesPainter::GetGravityMatrix(frameGravity,
139         {0.f, 0.f, boundsWidth, boundsHeight}, bufferWidth, bufferHeight, gravityMatrix);
140     Drawing::Matrix inverseTotalMatrix;
141     Drawing::Matrix inverseGravityMatrix;
142     // We don't have to do additional works when renderfit mode is Gravity::RESIZE or frameSize == boundsSize.
143     if (frameGravity == Gravity::RESIZE ||
144         (ROSEN_EQ(bufferWidth, boundsWidth) && ROSEN_EQ(bufferHeight, boundsHeight)) ||
145         !totalMatrix.Invert(inverseTotalMatrix) || !gravityMatrix.Invert(inverseGravityMatrix)) {
146         return;
147     }
148     Drawing::Rect bound = Drawing::Rect(0.f, 0.f, boundsWidth, boundsHeight);
149     Drawing::Rect frame = Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight);
150     Drawing::Rect localIntersectRect;
151     gravityMatrix.MapRect(localIntersectRect, frame);
152     IntersectRect(localIntersectRect, bound);
153     Drawing::Rect absIntersectRect;
154     totalMatrix.MapRect(absIntersectRect, localIntersectRect);
155     const RectI dstRect = node.GetDstRect();
156     Drawing::Rect newDstRect(dstRect.left_, dstRect.top_, dstRect.GetRight(), dstRect.GetBottom());
157     IntersectRect(newDstRect, absIntersectRect);
158     node.SetDstRect({std::floor(newDstRect.GetLeft()), std::floor(newDstRect.GetTop()),
159         std::ceil(newDstRect.GetWidth()), std::ceil(newDstRect.GetHeight())});
160     Drawing::Rect newSrcRect;
161     DealWithNewSrcRect(newSrcRect, newDstRect, inverseTotalMatrix, inverseGravityMatrix, consumerTransformType);
162     newSrcRect = CalcSrcRectByBufferRotation(*buffer, consumerTransformType, newSrcRect);
163     node.SetSrcRect({newSrcRect.GetLeft(), newSrcRect.GetTop(), newSrcRect.GetWidth(), newSrcRect.GetHeight()});
164 }
165 
DealWithNewSrcRect(Drawing::Rect & newSrcRect,Drawing::Rect newDstRect,Drawing::Matrix inverseTotalMatrix,Drawing::Matrix inverseGravityMatrix,const GraphicTransformType consumerTransformType)166 void RSUniHwcComputeUtil::DealWithNewSrcRect(Drawing::Rect& newSrcRect, Drawing::Rect newDstRect,
167     Drawing::Matrix inverseTotalMatrix, Drawing::Matrix inverseGravityMatrix,
168     const GraphicTransformType consumerTransformType)
169 {
170     inverseTotalMatrix.MapRect(newSrcRect, newDstRect);
171     inverseGravityMatrix.MapRect(newSrcRect, newSrcRect);
172     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
173         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
174         std::swap(newSrcRect.left_, newSrcRect.top_);
175         std::swap(newSrcRect.right_, newSrcRect.bottom_);
176     }
177 }
178 
DealWithNodeGravityOldVersion(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)179 void RSUniHwcComputeUtil::DealWithNodeGravityOldVersion(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
180 {
181     auto buffer = node.GetRSSurfaceHandler()->GetBuffer();
182     if (!buffer) {
183         return;
184     }
185     const auto& property = node.GetRenderProperties();
186     const float frameWidth = buffer->GetSurfaceBufferWidth();
187     const float frameHeight = buffer->GetSurfaceBufferHeight();
188     const float boundsWidth = property.GetBoundsWidth();
189     const float boundsHeight = property.GetBoundsHeight();
190     const Gravity frameGravity = property.GetFrameGravity();
191 
192     CheckForceHardwareAndUpdateDstRect(node);
193     // we do not need to do additional works for Gravity::RESIZE and if frameSize == boundsSize.
194     if (frameGravity == Gravity::RESIZE || (ROSEN_EQ(frameWidth, boundsWidth) && ROSEN_EQ(frameHeight, boundsHeight)) ||
195         frameGravity == Gravity::TOP_LEFT) {
196         return;
197     }
198 
199     // get current node's translate matrix and calculate gravity matrix.
200     auto translateMatrix = Drawing::Matrix();
201     translateMatrix.Translate(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_X),
202         std::ceil(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_Y)));
203     Drawing::Matrix gravityMatrix;
204     (void)RSPropertiesPainter::GetGravityMatrix(frameGravity,
205         RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix);
206     // create a canvas to calculate new dstRect and new srcRect
207     int32_t screenWidth = screenInfo.phyWidth;
208     int32_t screenHeight = screenInfo.phyHeight;
209     const auto screenRotation = screenInfo.rotation;
210     if (screenRotation == ScreenRotation::ROTATION_90 || screenRotation == ScreenRotation::ROTATION_270) {
211         std::swap(screenWidth, screenHeight);
212     }
213 
214     auto canvas = std::make_unique<Drawing::Canvas>(screenWidth, screenHeight);
215     canvas->ConcatMatrix(translateMatrix);
216     canvas->ConcatMatrix(gravityMatrix);
217     Drawing::Rect clipRect;
218     gravityMatrix.MapRect(clipRect, Drawing::Rect(0, 0, frameWidth, frameHeight));
219     canvas->ClipRect(Drawing::Rect(0, 0, clipRect.GetWidth(), clipRect.GetHeight()), Drawing::ClipOp::INTERSECT);
220     Drawing::RectI newDstRect = canvas->GetDeviceClipBounds();
221     auto dstRect = node.GetDstRect();
222     // we make the newDstRect as the intersection of new and old dstRect,
223     // to deal with the situation that frameSize > boundsSize.
224     newDstRect.Intersect(Drawing::RectI(
225         dstRect.left_, dstRect.top_, dstRect.width_ + dstRect.left_, dstRect.height_ + dstRect.top_));
226     auto localRect = canvas->GetLocalClipBounds();
227     int32_t left = std::clamp<int32_t>(localRect.GetLeft(), 0, frameWidth);
228     int32_t top = std::clamp<int32_t>(localRect.GetTop(), 0, frameHeight);
229     int32_t width = std::clamp<int32_t>(localRect.GetWidth(), 0, frameWidth - left);
230     int32_t height = std::clamp<int32_t>(localRect.GetHeight(), 0, frameHeight - top);
231 
232     node.SetDstRect({newDstRect.GetLeft(), newDstRect.GetTop(), newDstRect.GetWidth(), newDstRect.GetHeight()});
233     node.SetSrcRect({left, top, width, height});
234 }
235 
CheckForceHardwareAndUpdateDstRect(RSSurfaceRenderNode & node)236 void RSUniHwcComputeUtil::CheckForceHardwareAndUpdateDstRect(RSSurfaceRenderNode& node)
237 {
238     auto surfaceHandler = node.GetRSSurfaceHandler();
239     if (!surfaceHandler->GetConsumer() || !node.IsInFixedRotation() || !surfaceHandler->GetBuffer()) {
240         return;
241     }
242     node.SetSrcRect(node.GetOriginalSrcRect());
243     auto dstRect = node.GetDstRect();
244     auto originalDstRect = node.GetOriginalDstRect();
245     int fixedConstant = 2;
246     dstRect.left_ += (dstRect.width_ - originalDstRect.width_) / fixedConstant;
247     dstRect.top_ += (dstRect.height_ - originalDstRect.height_) / fixedConstant;
248     dstRect.width_ = originalDstRect.width_;
249     dstRect.height_ = originalDstRect.height_;
250     node.SetDstRect(dstRect);
251 }
252 
DealWithScalingMode(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix)253 void RSUniHwcComputeUtil::DealWithScalingMode(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix)
254 {
255     auto surfaceHandler = node.GetRSSurfaceHandler();
256     if (!surfaceHandler) {
257         return;
258     }
259     const auto buffer = surfaceHandler->GetBuffer();
260     const auto consumer = surfaceHandler->GetConsumer();
261     if (!consumer || !buffer) {
262         return;
263     }
264     float bufferWidth = buffer->GetSurfaceBufferWidth();
265     float bufferHeight = buffer->GetSurfaceBufferHeight();
266     const float boundsWidth = node.GetRenderProperties().GetBoundsWidth();
267     const float boundsHeight = node.GetRenderProperties().GetBoundsHeight();
268     const GraphicTransformType consumerTransformType = node.GetFixRotationByUser() ?
269         GetRotateTransformForRotationFixed(node, consumer) : GetConsumerTransform(node, buffer, consumer);
270     const Gravity frameGravity = node.GetRenderProperties().GetFrameGravity();
271     const ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
272     if (scalingMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW || !IsHwcEnabledByScalingMode(node, scalingMode) ||
273         !IsHwcEnabledByGravity(node, frameGravity)) {
274         return;
275     }
276     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
277         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
278         std::swap(bufferWidth, bufferHeight);
279     }
280     Drawing::Matrix gravityMatrix;
281     RSPropertiesPainter::GetGravityMatrix(frameGravity,
282         {0.f, 0.f, boundsWidth, boundsHeight}, bufferWidth, bufferHeight, gravityMatrix);
283     Drawing::Matrix rawScalingModeMatrix;
284     RSPropertiesPainter::GetScalingModeMatrix(scalingMode,
285         {0.f, 0.f, boundsWidth, boundsHeight}, bufferWidth, bufferHeight, rawScalingModeMatrix);
286     Drawing::Rect rawSrcRect;
287     rawScalingModeMatrix.MapRect(rawSrcRect, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
288     float xScale = ROSEN_EQ(boundsWidth, 0.f) ? 1.0f :
289         rawSrcRect.GetWidth() / (boundsWidth == 0.0f ? 1.0f : boundsWidth);
290     float yScale = ROSEN_EQ(boundsHeight, 0.f) ? 1.0f :
291         rawSrcRect.GetHeight() / (boundsHeight == 0.0f ? 1.0f : boundsHeight);
292     Drawing::Matrix scalingModeMatrix;
293     scalingModeMatrix.PostScale(xScale, yScale);
294     Drawing::Rect adjustedSrcRect;
295     scalingModeMatrix.MapRect(adjustedSrcRect, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
296     float xTranslate = (bufferWidth - adjustedSrcRect.GetWidth()) / 2.0f;
297     float yTranslate = (bufferHeight - adjustedSrcRect.GetHeight()) / 2.0f;
298     scalingModeMatrix.PostTranslate(xTranslate, yTranslate);
299     UpdateHwcNodeByScalingMode(node, totalMatrix, gravityMatrix, scalingModeMatrix);
300 }
301 
LayerRotate(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)302 void RSUniHwcComputeUtil::LayerRotate(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
303 {
304     const auto screenWidth = static_cast<int32_t>(screenInfo.width);
305     const auto screenHeight = static_cast<int32_t>(screenInfo.height);
306     const auto screenRotation = screenInfo.rotation;
307     const auto rect = node.GetDstRect();
308     switch (screenRotation) {
309         case ScreenRotation::ROTATION_90: {
310             node.SetDstRect({rect.top_, screenHeight - rect.left_ - rect.width_, rect.height_, rect.width_});
311             break;
312         }
313         case ScreenRotation::ROTATION_180: {
314             node.SetDstRect({screenWidth - rect.left_ - rect.width_, screenHeight - rect.top_ - rect.height_,
315                 rect.width_, rect.height_});
316             break;
317         }
318         case ScreenRotation::ROTATION_270: {
319             node.SetDstRect({screenWidth - rect.top_ - rect.height_, rect.left_, rect.height_, rect.width_});
320             break;
321         }
322         default:  {
323             break;
324         }
325     }
326 }
327 
LayerCrop(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)328 void RSUniHwcComputeUtil::LayerCrop(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
329 {
330     if (node.GetHwcGlobalPositionEnabled()) {
331         return;
332     }
333     auto dstRect = node.GetDstRect();
334     auto srcRect = node.GetSrcRect();
335     auto originSrcRect = srcRect;
336 
337     RectI dstRectI(dstRect.left_, dstRect.top_, dstRect.width_, dstRect.height_);
338     int32_t screenWidth = static_cast<int32_t>(screenInfo.phyWidth);
339     int32_t screenHeight = static_cast<int32_t>(screenInfo.phyHeight);
340     if (node.GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED)) {
341         screenWidth = static_cast<int32_t>(screenInfo.width);
342         screenHeight = static_cast<int32_t>(screenInfo.height);
343     }
344     RectI screenRectI(0, 0, screenWidth, screenHeight);
345     RectI resDstRect = dstRectI.IntersectRect(screenRectI);
346     if (resDstRect == dstRectI) {
347         return;
348     }
349     if (node.IsInFixedRotation()) {
350         node.SetDstRect(resDstRect);
351         return;
352     }
353     dstRect = {resDstRect.left_, resDstRect.top_, resDstRect.width_, resDstRect.height_};
354     srcRect.left_ = (resDstRect.IsEmpty() || dstRectI.IsEmpty()) ? 0 : std::floor((resDstRect.left_ - dstRectI.left_) *
355         originSrcRect.width_ / dstRectI.width_);
356     srcRect.top_ = (resDstRect.IsEmpty() || dstRectI.IsEmpty()) ? 0 : std::floor((resDstRect.top_ - dstRectI.top_) *
357         originSrcRect.height_ / dstRectI.height_);
358     srcRect.width_ = dstRectI.IsEmpty() ? 0 : std::ceil(originSrcRect.width_ * resDstRect.width_ / dstRectI.width_);
359     srcRect.height_ = dstRectI.IsEmpty() ? 0 : std::ceil(originSrcRect.height_ * resDstRect.height_ / dstRectI.height_);
360     node.SetDstRect(dstRect);
361     node.SetSrcRect(srcRect);
362 }
363 
CalcSrcRectByBufferFlip(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)364 void RSUniHwcComputeUtil::CalcSrcRectByBufferFlip(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
365 {
366     auto surfaceHandler = node.GetRSSurfaceHandler();
367     auto consumer = surfaceHandler->GetConsumer();
368     auto buffer = surfaceHandler->GetBuffer();
369     if (!consumer || !buffer) {
370         return;
371     }
372     const auto bufferWidth = buffer->GetSurfaceBufferWidth();
373     const auto bufferHeight = buffer->GetSurfaceBufferHeight();
374     const auto dstRect = node.GetDstRect();
375     RectI srcRect = node.GetSrcRect();
376     auto bufferFlipTransformType =
377         RSBaseRenderUtil::GetFlipTransform(RSBaseRenderUtil::GetSurfaceBufferTransformType(consumer, buffer));
378     switch (bufferFlipTransformType) {
379         case GraphicTransformType::GRAPHIC_FLIP_H: {
380             if (srcRect.left_ >= 0) {
381                 srcRect.left_ = bufferWidth - srcRect.left_ - srcRect.width_;
382             } else if (dstRect.left_ + dstRect.width_ >= static_cast<int32_t>(screenInfo.width)) {
383                 srcRect.left_ = bufferWidth - srcRect.width_;
384             }
385             break;
386         }
387         case GraphicTransformType::GRAPHIC_FLIP_V: {
388             if (srcRect.top_ >= 0) {
389                 srcRect.top_ = bufferHeight - srcRect.top_ - srcRect.height_;
390             } else if (dstRect.top_ + dstRect.height_ >= static_cast<int32_t>(screenInfo.height)) {
391                 srcRect.top_ = bufferHeight - srcRect.height_;
392             }
393             break;
394         }
395         default:
396             break;
397     }
398     node.SetSrcRect(srcRect);
399 }
400 
IsHwcEnabledByScalingMode(RSSurfaceRenderNode & node,const ScalingMode scalingMode)401 bool RSUniHwcComputeUtil::IsHwcEnabledByScalingMode(RSSurfaceRenderNode& node, const ScalingMode scalingMode)
402 {
403     // We temporarily disabled HWC when scalingMode is freeze or no_scale_crop
404     if (!node.GetSpecialLayerMgr().Find(SpecialLayerType::PROTECTED) &&
405         (scalingMode == ScalingMode::SCALING_MODE_FREEZE || scalingMode == ScalingMode::SCALING_MODE_NO_SCALE_CROP)) {
406         RS_OPTIONAL_TRACE_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by scalingMode[%d]",
407             node.GetName().c_str(), node.GetId(), static_cast<int32_t>(scalingMode));
408         node.SetHardwareForcedDisabledState(true);
409         return false;
410     }
411     return true;
412 }
413 
UpdateHwcNodeByScalingMode(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix,const Drawing::Matrix & gravityMatrix,const Drawing::Matrix & scalingModeMatrix)414 void RSUniHwcComputeUtil::UpdateHwcNodeByScalingMode(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix,
415     const Drawing::Matrix& gravityMatrix, const Drawing::Matrix& scalingModeMatrix)
416 {
417     auto surfaceHandler = node.GetRSSurfaceHandler();
418     const auto& property = node.GetRenderProperties();
419     const auto buffer = surfaceHandler->GetBuffer();
420     const auto consumer = surfaceHandler->GetConsumer();
421     float bufferWidth = buffer->GetSurfaceBufferWidth();
422     float bufferHeight = buffer->GetSurfaceBufferHeight();
423     const GraphicTransformType consumerTransformType = node.GetFixRotationByUser() ?
424         GetRotateTransformForRotationFixed(node, consumer) : GetConsumerTransform(node, buffer, consumer);
425     Drawing::Matrix inverseScalingModeMatrix;
426     Drawing::Matrix inverseGravityMatrix;
427     Drawing::Matrix inverseTotalMatrix;
428     if (!totalMatrix.Invert(inverseTotalMatrix) || !scalingModeMatrix.Invert(inverseScalingModeMatrix) ||
429         !gravityMatrix.Invert(inverseGravityMatrix)) {
430         return;
431     }
432     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
433         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
434         std::swap(bufferWidth, bufferHeight);
435     }
436     Drawing::Rect newDstRect;
437     scalingModeMatrix.MapRect(newDstRect, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
438     gravityMatrix.MapRect(newDstRect, newDstRect);
439     totalMatrix.MapRect(newDstRect, newDstRect);
440     Drawing::Rect dstRectWithoutScaling;
441     gravityMatrix.MapRect(dstRectWithoutScaling, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
442     totalMatrix.MapRect(dstRectWithoutScaling, dstRectWithoutScaling);
443     IntersectRect(newDstRect, dstRectWithoutScaling);
444     Drawing::Rect bounds = node.GetDstRectWithoutRenderFit();
445     IntersectRect(newDstRect, bounds);
446     node.SetDstRect({std::floor(newDstRect.GetLeft()), std::floor(newDstRect.GetTop()),
447         std::ceil(newDstRect.GetWidth()), std::ceil(newDstRect.GetHeight())});
448     Drawing::Rect newSrcRect;
449     inverseTotalMatrix.MapRect(newSrcRect, newDstRect);
450     inverseGravityMatrix.MapRect(newSrcRect, newSrcRect);
451     inverseScalingModeMatrix.MapRect(newSrcRect, newSrcRect);
452     if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
453         consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
454         std::swap(newSrcRect.left_, newSrcRect.top_);
455         std::swap(newSrcRect.right_, newSrcRect.bottom_);
456     }
457     newSrcRect = CalcSrcRectByBufferRotation(*buffer, consumerTransformType, newSrcRect);
458     node.SetSrcRect({newSrcRect.GetLeft(), newSrcRect.GetTop(), newSrcRect.GetWidth(), newSrcRect.GetHeight()});
459 }
460 
SrcRectRotateTransform(const SurfaceBuffer & buffer,const GraphicTransformType bufferRotateTransformType,const RectI & newSrcRect)461 RectI RSUniHwcComputeUtil::SrcRectRotateTransform(const SurfaceBuffer& buffer,
462     const GraphicTransformType bufferRotateTransformType, const RectI& newSrcRect)
463 {
464     const auto bufferWidth = buffer.GetSurfaceBufferWidth();
465     const auto bufferHeight = buffer.GetSurfaceBufferHeight();
466     int32_t left = newSrcRect.GetLeft();
467     int32_t top = newSrcRect.GetTop();
468     int32_t width = newSrcRect.GetWidth();
469     int32_t height = newSrcRect.GetHeight();
470     RectI srcRect(newSrcRect);
471     switch (bufferRotateTransformType) {
472         case GraphicTransformType::GRAPHIC_ROTATE_90: {
473             srcRect = RectI {bufferWidth - width - left, top, width, height};
474             break;
475         }
476         case GraphicTransformType::GRAPHIC_ROTATE_180: {
477             srcRect = RectI {bufferWidth - width - left, bufferHeight - height - top, width, height};
478             break;
479         }
480         case GraphicTransformType::GRAPHIC_ROTATE_270: {
481             srcRect = RectI {left, bufferHeight - height - top, width, height};
482             break;
483         }
484         default:
485             break;
486     }
487     return srcRect;
488 }
489 
UpdateRealSrcRect(RSSurfaceRenderNode & node,const RectI & absRect)490 void RSUniHwcComputeUtil::UpdateRealSrcRect(RSSurfaceRenderNode& node, const RectI& absRect)
491 {
492     auto surfaceHandler = node.GetRSSurfaceHandler();
493     auto consumer = surfaceHandler->GetConsumer();
494     auto buffer = surfaceHandler->GetBuffer();
495     if (!consumer || !buffer) {
496         return;
497     }
498     auto bufferRotateTransformType = node.GetFixRotationByUser() ?
499         GetRotateTransformForRotationFixed(node, consumer) :
500         RSBaseRenderUtil::GetRotateTransform(RSBaseRenderUtil::GetSurfaceBufferTransformType(consumer, buffer));
501     const auto& property = node.GetRenderProperties();
502     auto bufferWidth = buffer->GetSurfaceBufferWidth();
503     auto bufferHeight = buffer->GetSurfaceBufferHeight();
504     const auto boundsWidth = property.GetBoundsWidth();
505     const auto boundsHeight = property.GetBoundsHeight();
506     auto srcRect = node.GetSrcRect();
507     if (bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
508         bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
509         std::swap(bufferWidth, bufferHeight);
510     }
511     if ((bufferWidth != boundsWidth || bufferHeight != boundsHeight) &&
512         node.GetRenderProperties().GetFrameGravity() != Gravity::TOP_LEFT) {
513         float xScale = (ROSEN_EQ(boundsWidth, 0.0f) ? 1.0f : bufferWidth / (boundsWidth == 0.0f ? 1.f : boundsWidth));
514         float yScale = (ROSEN_EQ(boundsHeight, 0.0f) ? 1.0f : bufferHeight /
515             (boundsHeight == 0.0f ? 1.0f : boundsHeight));
516         if (absRect == node.GetDstRect()) {
517             // If the SurfaceRenderNode is completely in the ScreenRenderNode,
518             // we do not need to crop the buffer.
519             srcRect.width_ = bufferWidth;
520             srcRect.height_ = bufferHeight;
521         } else {
522             srcRect.left_ = srcRect.left_ * xScale;
523             srcRect.top_ = srcRect.top_ * yScale;
524             srcRect.width_ = std::min(static_cast<int32_t>(std::ceil(srcRect.width_ * xScale)), bufferWidth);
525             srcRect.height_ = std::min(static_cast<int32_t>(std::ceil(srcRect.height_ * yScale)), bufferHeight);
526         }
527     }
528     RectI bufferRect(0, 0, bufferWidth, bufferHeight);
529     RectI calibratedSrcRect = srcRect.IntersectRect(bufferRect);
530     if (bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
531         bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
532         std::swap(calibratedSrcRect.left_, calibratedSrcRect.top_);
533         std::swap(calibratedSrcRect.width_, calibratedSrcRect.height_);
534     }
535     auto newSrcRect = SrcRectRotateTransform(*buffer, bufferRotateTransformType, calibratedSrcRect);
536     node.SetSrcRect(newSrcRect);
537 }
538 
UpdateHwcNodeDrawingCache(const std::shared_ptr<RSRenderNode> & parent,HwcPropertyContext & ctx)539 inline void RSUniHwcComputeUtil::UpdateHwcNodeDrawingCache(const std::shared_ptr<RSRenderNode>& parent,
540     HwcPropertyContext& ctx)
541 {
542     bool& isNodeRenderByDrawingCache = ctx.isNodeRenderByDrawingCache;
543     if (isNodeRenderByDrawingCache) {
544         return;
545     }
546     // If parentNode of hwcNode is marked as freeze or nodegroup, RS will disable hwcNode's hardware composer
547     isNodeRenderByDrawingCache |= parent->IsStaticCached() ||
548         parent->GetNodeGroupType() != RSRenderNode::NodeGroupType::NONE;
549 }
550 
UpdateHwcNodeBlendNeedChildNode(const std::shared_ptr<RSRenderNode> & parent,HwcPropertyContext & ctx)551 inline void RSUniHwcComputeUtil::UpdateHwcNodeBlendNeedChildNode(const std::shared_ptr<RSRenderNode>& parent,
552     HwcPropertyContext& ctx)
553 {
554     bool& isNodeRenderByChildNode = ctx.isNodeRenderByChildNode;
555     if (isNodeRenderByChildNode) {
556         return;
557     }
558     isNodeRenderByChildNode |= IsBlendNeedChildNode(*parent);
559 }
560 
UpdateHwcNodeAlpha(const std::shared_ptr<RSRenderNode> & parent,HwcPropertyContext & ctx)561 inline void RSUniHwcComputeUtil::UpdateHwcNodeAlpha(const std::shared_ptr<RSRenderNode>& parent,
562     HwcPropertyContext& ctx)
563 {
564     auto& parentProperty = parent->GetRenderProperties();
565     ctx.alpha *= parentProperty.GetAlpha();
566 }
567 
UpdateHwcNodeTotalMatrix(const std::shared_ptr<RSRenderNode> & parent,HwcPropertyContext & ctx)568 inline void RSUniHwcComputeUtil::UpdateHwcNodeTotalMatrix(const std::shared_ptr<RSRenderNode>& parent,
569     HwcPropertyContext& ctx)
570 {
571     if (auto opt = GetMatrix(parent)) {
572         ctx.totalMatrix.PostConcat(opt.value());
573     }
574 }
575 
UpdateHwcNodeAbsRotation(const std::shared_ptr<RSRenderNode> & parent,HwcPropertyContext & ctx)576 void RSUniHwcComputeUtil::UpdateHwcNodeAbsRotation(const std::shared_ptr<RSRenderNode>& parent, HwcPropertyContext& ctx)
577 {
578     if (!parent->GetRenderProperties().GetQuaternion().IsIdentity()) {
579         ctx.absRotation += RSUniRenderUtil::GetYawFromQuaternion(parent->GetRenderProperties().GetQuaternion());
580     } else {
581         ctx.absRotation += parent->GetRenderProperties().GetRotation();
582     }
583 }
584 
UpdateHwcNodeProperty(const std::shared_ptr<RSSurfaceRenderNode> & hwcNode)585 void RSUniHwcComputeUtil::UpdateHwcNodeProperty(const std::shared_ptr<RSSurfaceRenderNode>& hwcNode)
586 {
587     if (hwcNode == nullptr) {
588         RS_LOGE("hwcNode is null.");
589         return;
590     }
591     std::vector<RectI> currIntersectedRoundCornerAABBs = {};
592     bool hasCornerRadius = !hwcNode->GetRenderProperties().GetCornerRadius().IsZero();
593     const auto& hwcNodeGeo = hwcNode->GetRenderProperties().GetBoundsGeometry();
594     auto hwcNodeRect = hwcNodeGeo->GetAbsRect();
595     HwcPropertyContext ctx;
596     ctx.alpha = hwcNode->GetRenderProperties().GetAlpha();
597     ctx.totalMatrix = hwcNodeGeo->GetMatrix();
598     ctx.absRotation = hwcNode->GetRenderProperties().GetRotation();
599     RSUniHwcComputeUtil::TraverseParentNodeAndReduce(
600         hwcNode,
601         [&ctx](const std::shared_ptr<RSRenderNode>& parent) { UpdateHwcNodeDrawingCache(parent, ctx); },
602         [&ctx](const std::shared_ptr<RSRenderNode>& parent) { UpdateHwcNodeBlendNeedChildNode(parent, ctx); },
603         [&ctx](const std::shared_ptr<RSRenderNode>& parent) { UpdateHwcNodeAlpha(parent, ctx); },
604         [&ctx](const std::shared_ptr<RSRenderNode>& parent) { UpdateHwcNodeTotalMatrix(parent, ctx); },
605         [&ctx](const std::shared_ptr<RSRenderNode>& parent) { UpdateHwcNodeAbsRotation(parent, ctx); },
606         [&currIntersectedRoundCornerAABBs, hwcNodeRect](std::shared_ptr<RSRenderNode> parent) {
607             auto& parentProperty = parent->GetRenderProperties();
608             auto cornerRadius = parentProperty.GetCornerRadius();
609             auto maxCornerRadius = *std::max_element(std::begin(cornerRadius.data_), std::end(cornerRadius.data_));
610             auto parentGeo = parentProperty.GetBoundsGeometry();
611             static const std::array offsetVecs {
612                 UIPoint { 0, 0 },
613                 UIPoint { 1, 0 },
614                 UIPoint { 0, 1 },
615                 UIPoint { 1, 1 }
616             };
617 
618             // The logic here is to calculate whether the HWC Node affects
619             // the round corner property of the parent node.
620             // The method is calculating the rounded AABB of each HWC node
621             // with respect to all parent nodes above it and storing the results.
622             // When a HWC node is found below, the AABBs and the HWC node
623             // are checked for intersection. If there is an intersection,
624             // the node above it is disabled from taking the HWC pipeline.
625             auto checkIntersectWithRoundCorner = [&currIntersectedRoundCornerAABBs, hwcNodeRect](
626                 const RectI& rect, float radiusX, float radiusY) {
627                 if (radiusX <= 0 || radiusY <= 0) {
628                     return;
629                 }
630                 UIPoint offset { rect.GetWidth() - radiusX, rect.GetHeight() - radiusY };
631                 UIPoint anchorPoint { rect.GetLeft(), rect.GetTop() };
632                 std::for_each(std::begin(offsetVecs), std::end(offsetVecs),
633                     [&currIntersectedRoundCornerAABBs, hwcNodeRect, offset,
634                      radiusX, radiusY, anchorPoint](auto offsetVec) {
635                         auto res = anchorPoint + offset * offsetVec;
636                         auto roundCornerAABB = RectI(res.x_, res.y_, radiusX, radiusY);
637                         if (!roundCornerAABB.IntersectRect(hwcNodeRect).IsEmpty()) {
638                             currIntersectedRoundCornerAABBs.push_back(roundCornerAABB);
639                         }
640                     }
641                 );
642             };
643             if (parentGeo) {
644                 auto parentRect = parentGeo->GetAbsRect();
645                 checkIntersectWithRoundCorner(parentRect, maxCornerRadius, maxCornerRadius);
646 
647                 if (parentProperty.GetClipToRRect()) {
648                     RRect parentClipRRect = parentProperty.GetClipRRect();
649                     RectI parentClipRect = parentGeo->MapAbsRect(parentClipRRect.rect_);
650                     float maxClipRRectCornerRadiusX = 0;
651                     float maxClipRRectCornerRadiusY = 0;
652                     constexpr size_t radiusVecSize = 4;
653                     for (size_t i = 0; i < radiusVecSize; ++i) {
654                         maxClipRRectCornerRadiusX = std::max(maxClipRRectCornerRadiusX, parentClipRRect.radius_[i].x_);
655                         maxClipRRectCornerRadiusY = std::max(maxClipRRectCornerRadiusY, parentClipRRect.radius_[i].y_);
656                     }
657                     checkIntersectWithRoundCorner(parentClipRect, maxClipRRectCornerRadiusX, maxClipRRectCornerRadiusY);
658                 }
659             }
660         });
661     if (ctx.isNodeRenderByDrawingCache || ctx.isNodeRenderByChildNode) {
662         RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by drawing cache or need blend with "
663             "childNode, isNodeRenderByDrawingCache[%d], isNodeRenderByChildNode[%d]",
664             hwcNode->GetName().c_str(), hwcNode->GetId(), ctx.isNodeRenderByDrawingCache, ctx.isNodeRenderByChildNode);
665         hwcNode->SetHardwareForcedDisabledState(true);
666     }
667     hwcNode->SetTotalMatrix(ctx.totalMatrix);
668     hwcNode->SetGlobalAlpha(ctx.alpha);
669     hwcNode->SetAbsRotation(ctx.absRotation);
670     hwcNode->SetIntersectedRoundCornerAABBs(std::move(currIntersectedRoundCornerAABBs));
671 }
672 
HasNonZRotationTransform(const Drawing::Matrix & matrix)673 bool RSUniHwcComputeUtil::HasNonZRotationTransform(const Drawing::Matrix& matrix)
674 {
675     Drawing::Matrix::Buffer value;
676     matrix.GetAll(value);
677     if (!ROSEN_EQ(value[Drawing::Matrix::Index::PERSP_0], 0.f) ||
678         !ROSEN_EQ(value[Drawing::Matrix::Index::PERSP_1], 0.f)) {
679         return true;
680     }
681     int rotation = static_cast<int>(round(value[Drawing::Matrix::Index::SCALE_X] *
682         value[Drawing::Matrix::Index::SKEW_Y] +
683         value[Drawing::Matrix::Index::SCALE_Y] *
684         value[Drawing::Matrix::Index::SKEW_X]));
685     if (rotation != 0) {
686         return true;
687     }
688     int vectorZ = value[Drawing::Matrix::Index::SCALE_X] * value[Drawing::Matrix::Index::SCALE_Y] -
689         value[Drawing::Matrix::Index::SKEW_Y] * value[Drawing::Matrix::Index::SKEW_X];
690     return vectorZ < 0;
691 }
692 
GetLayerTransform(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)693 GraphicTransformType RSUniHwcComputeUtil::GetLayerTransform(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
694 {
695     auto surfaceHandler = node.GetRSSurfaceHandler();
696     if (!surfaceHandler) {
697         return GraphicTransformType::GRAPHIC_ROTATE_NONE;
698     }
699     auto consumer = surfaceHandler->GetConsumer();
700     auto surfaceParams = node.GetStagingRenderParams() == nullptr
701                              ? nullptr
702                              : static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
703     int32_t rotationDegree = RSBaseRenderUtil::GetScreenRotationOffset(surfaceParams);
704     int surfaceNodeRotation = 0;
705     if (node.GetFixRotationByUser()) {
706         surfaceNodeRotation = -1 * rotationDegree;
707     } else {
708         surfaceNodeRotation = RSUniRenderUtil::TransferToAntiClockwiseDegrees(
709                                 static_cast<int>(round(node.GetAbsRotation())) % ROUND_ANGLE);
710     }
711     auto transformType = GraphicTransformType::GRAPHIC_ROTATE_NONE;
712     auto buffer = node.GetRSSurfaceHandler()->GetBuffer();
713     if (consumer != nullptr && buffer != nullptr) {
714         if (consumer->GetSurfaceBufferTransformType(buffer, &transformType) != GSERROR_OK) {
715             RS_LOGE("GetLayerTransform GetSurfaceBufferTransformType failed");
716         }
717     }
718     int consumerTransform = RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(transformType));
719     GraphicTransformType consumerFlip = RSBaseRenderUtil::GetFlipTransform(transformType);
720     int totalRotation =
721         (RSBaseRenderUtil::RotateEnumToInt(screenInfo.rotation) + surfaceNodeRotation + consumerTransform + 360) % 360;
722     GraphicTransformType rotateEnum = RSBaseRenderUtil::RotateEnumToInt(totalRotation, consumerFlip);
723 
724     RS_OPTIONAL_TRACE_NAME_FMT("RSUniHwcComputeUtil::GetLayerTransform nodeId:[%llu] fixRotationByUser:[%s] "
725                                "surfaceNodeRotation:[%d] consumerTransform:[%d] rotateEnum:[%d]",
726                                node.GetId(), std::to_string(node.GetFixRotationByUser()).c_str(),
727                                surfaceNodeRotation, consumerTransform, rotateEnum);
728 
729     return rotateEnum;
730 }
731 
GetMatrix(const std::shared_ptr<RSRenderNode> & hwcNode)732 std::optional<Drawing::Matrix> RSUniHwcComputeUtil::GetMatrix(
733     const std::shared_ptr<RSRenderNode>& hwcNode)
734 {
735     if (!hwcNode) {
736         return std::nullopt;
737     }
738     const auto& property = hwcNode->GetRenderProperties();
739     auto geo = property.GetBoundsGeometry();
740     if (LIKELY(!property.GetSandBox().has_value())) {
741         return geo->GetMatrix();
742     } else {
743         auto parent = hwcNode->GetParent().lock();
744         if (!parent) {
745             return std::nullopt;
746         }
747         auto parentGeo = parent->GetRenderProperties().GetBoundsGeometry();
748         Drawing::Matrix invertAbsParentMatrix;
749         parentGeo->GetAbsMatrix().Invert(invertAbsParentMatrix);
750         Drawing::Matrix relativeMat = geo->GetAbsMatrix();
751         relativeMat.PostConcat(invertAbsParentMatrix);
752         return relativeMat;
753     }
754 }
755 
IntersectRect(Drawing::Rect & result,const Drawing::Rect & other)756 bool RSUniHwcComputeUtil::IntersectRect(Drawing::Rect& result, const Drawing::Rect& other)
757 {
758     float left = std::max(result.left_, other.left_);
759     float top = std::max(result.top_, other.top_);
760     float right = std::min(result.right_, other.right_);
761     float bottom = std::min(result.bottom_, other.bottom_);
762     Drawing::Rect intersectedRect(left, top, right, bottom);
763     if (!intersectedRect.IsValid()) {
764         result = Drawing::Rect();
765         return false;
766     }
767     result = intersectedRect;
768     return true;
769 }
770 
IsBlendNeedFilter(RSRenderNode & node)771 bool RSUniHwcComputeUtil::IsBlendNeedFilter(RSRenderNode& node)
772 {
773     const auto& property = node.GetRenderProperties();
774     return property.NeedFilter() || node.GetHwcRecorder().IsBlendWithBackground() ||
775         IsForegroundColorStrategyValid(node);
776 }
777 
IsBlendNeedBackground(RSRenderNode & node)778 bool RSUniHwcComputeUtil::IsBlendNeedBackground(RSRenderNode& node)
779 {
780     const auto& property = node.GetRenderProperties();
781     return property.NeedHwcFilter() || node.GetHwcRecorder().IsBlendWithBackground() ||
782         IsForegroundColorStrategyValid(node);
783 }
784 
IsBlendNeedChildNode(RSRenderNode & node)785 bool RSUniHwcComputeUtil::IsBlendNeedChildNode(RSRenderNode& node)
786 {
787     const auto& property = node.GetRenderProperties();
788     return (property.IsColorBlendApplyTypeOffscreen() && !property.IsColorBlendModeNone()) ||
789         IsDangerousBlendMode(
790             property.GetColorBlendMode(), property.GetColorBlendApplyType()) ||
791         property.GetForegroundFilter() != nullptr ||
792         property.GetForegroundFilterCache() != nullptr ||
793         property.GetMask() != nullptr ||
794         property.GetShadowColorStrategy() != SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE ||
795         property.GetFilter() != nullptr ||
796         property.IsLightUpEffectValid() ||
797         property.GetLinearGradientBlurPara() != nullptr ||
798         property.IsDynamicDimValid() ||
799         property.IsFgBrightnessValid() ||
800         property.IsWaterRippleValid() ||
801         property.GetColorFilter() != nullptr;
802 }
803 
804 template<typename T>
GetPropertyFromModifier(const RSRenderNode & node,ModifierNG::RSModifierType modifierType,ModifierNG::RSPropertyType propertyType)805 std::shared_ptr<RSRenderProperty<T>> RSUniHwcComputeUtil::GetPropertyFromModifier(
806     const RSRenderNode& node, ModifierNG::RSModifierType modifierType, ModifierNG::RSPropertyType propertyType)
807 {
808     if (auto modifier = node.GetModifierNG(modifierType)) {
809         return std::static_pointer_cast<RSRenderProperty<T>>(modifier->GetProperty(propertyType));
810     }
811     return nullptr;
812 }
813 
IsForegroundColorStrategyValid(RSRenderNode & node)814 bool RSUniHwcComputeUtil::IsForegroundColorStrategyValid(RSRenderNode& node)
815 {
816     auto property = GetPropertyFromModifier<ForegroundColorStrategyType>(node,
817         ModifierNG::RSModifierType::ENV_FOREGROUND_COLOR, ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR_STRATEGY);
818     return (property == nullptr) ? false : property->Get() != ForegroundColorStrategyType::INVALID;
819 }
820 
IsDangerousBlendMode(int32_t blendMode,int32_t blendApplyType)821 bool RSUniHwcComputeUtil::IsDangerousBlendMode(int32_t blendMode, int32_t blendApplyType)
822 {
823     // The NONE blend mode does not create an offscreen buffer
824     if (blendMode == static_cast<int32_t>(RSColorBlendMode::NONE)) {
825         return false;
826     }
827     return RSPropertiesPainter::IsDangerousBlendMode(blendMode - 1, blendApplyType);
828 }
829 
GetFloatRotationDegreeFromMatrix(const Drawing::Matrix & matrix)830 float RSUniHwcComputeUtil::GetFloatRotationDegreeFromMatrix(const Drawing::Matrix& matrix)
831 {
832     Drawing::Matrix::Buffer value;
833     matrix.GetAll(value);
834     return std::atan2(value[Drawing::Matrix::Index::SKEW_X], value[Drawing::Matrix::Index::SCALE_X]) *
835         (RS_ROTATION_180 / PI);
836 }
837 
838 #undef CHECK_NULL_VOID
839 } // namespace Rosen
840 } // namespace OHOS