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