• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 
16 #include "rs_render_thread_util.h"
17 
18 #include "platform/common/rs_log.h"
19 #include "utils/camera3d.h"
20 #ifdef ROSEN_OHOS
21 #include "bundle_mgr_interface.h"
22 #include "iservice_registry.h"
23 #include "system_ability_definition.h"
24 #endif
25 
26 namespace OHOS {
27 namespace Rosen {
SrcRectScaleDown(TextureExportBufferDrawParam & params,const RectF & localBounds)28 void RSRenderThreadUtil::SrcRectScaleDown(TextureExportBufferDrawParam& params, const RectF& localBounds)
29 {
30     uint32_t newWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
31     uint32_t newHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
32     // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
33     uint32_t boundsWidth = static_cast<uint32_t>(localBounds.GetWidth());
34     uint32_t boundsHeight = static_cast<uint32_t>(localBounds.GetHeight());
35 
36     uint32_t newWidthBoundsHeight = newWidth * boundsHeight;
37     uint32_t newHeightBoundsWidth = newHeight * boundsWidth;
38 
39     if (newWidthBoundsHeight > newHeightBoundsWidth) {
40         newWidth = boundsWidth * newHeight / boundsHeight;
41     } else if (newWidthBoundsHeight < newHeightBoundsWidth) {
42         newHeight = boundsHeight * newWidth / boundsWidth;
43     } else {
44         return;
45     }
46 
47     uint32_t currentWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
48     uint32_t currentHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
49     if (newWidth < currentWidth) {
50         // the crop is too wide
51         uint32_t dw = currentWidth - newWidth;
52         auto halfdw = dw / 2;
53         params.srcRect = Drawing::Rect(params.srcRect.GetLeft() + static_cast<int32_t>(halfdw), params.srcRect.GetTop(),
54             params.srcRect.GetLeft() + static_cast<int32_t>(halfdw) + static_cast<int32_t>(newWidth),
55             params.srcRect.GetTop() + params.srcRect.GetHeight());
56     } else {
57         // thr crop is too tall
58         uint32_t dh = currentHeight - newHeight;
59         auto halfdh = dh / 2;
60         params.srcRect = Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + static_cast<int32_t>(halfdh),
61             params.srcRect.GetLeft() + params.srcRect.GetWidth(),
62             params.srcRect.GetTop() + static_cast<int32_t>(halfdh) + static_cast<int32_t>(newHeight));
63     }
64 }
65 
SrcRectScaleFit(TextureExportBufferDrawParam & params,const RectF & localBounds)66 void RSRenderThreadUtil::SrcRectScaleFit(TextureExportBufferDrawParam& params, const RectF& localBounds)
67 {
68     uint32_t srcWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
69     uint32_t srcHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
70     float newWidth = 0.0f;
71     float newHeight = 0.0f;
72     // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
73     uint32_t boundsWidth = static_cast<uint32_t>(localBounds.GetWidth());
74     uint32_t boundsHeight = static_cast<uint32_t>(localBounds.GetHeight());
75     if (boundsWidth == 0 || boundsHeight == 0 || srcWidth == 0 || srcHeight == 0) {
76         return;
77     }
78 
79     if (srcWidth * boundsHeight > srcHeight * boundsWidth) {
80         newWidth = boundsWidth;
81         newHeight = srcHeight * newWidth / srcWidth;
82     } else if (srcWidth * boundsHeight < srcHeight * boundsWidth) {
83         newHeight = boundsHeight;
84         newWidth = newHeight * srcWidth / srcHeight;
85     } else {
86         newWidth = boundsWidth;
87         newHeight = boundsHeight;
88     }
89     newHeight = newHeight * srcHeight / boundsHeight;
90     newWidth = newWidth * srcWidth / boundsWidth;
91     if (newWidth < srcWidth) {
92         float halfdw = (srcWidth - newWidth) / 2;
93         params.dstRect = Drawing::Rect(params.srcRect.GetLeft() + halfdw, params.srcRect.GetTop(),
94             params.srcRect.GetLeft() + halfdw + newWidth, params.srcRect.GetTop() + params.srcRect.GetHeight());
95     } else if (newHeight < srcHeight) {
96         float halfdh = (srcHeight - newHeight) / 2;
97         params.dstRect = Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + halfdh,
98             params.srcRect.GetLeft() + params.srcRect.GetWidth(), params.srcRect.GetTop() + halfdh + newHeight);
99     }
100 }
101 
GetFlipTransform(GraphicTransformType transform)102 GraphicTransformType RSRenderThreadUtil::GetFlipTransform(GraphicTransformType transform)
103 {
104     switch (transform) {
105         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
106         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
107         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270: {
108             return GraphicTransformType::GRAPHIC_FLIP_H;
109         }
110         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90:
111         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180:
112         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
113             return GraphicTransformType::GRAPHIC_FLIP_V;
114         }
115         default: {
116             return transform;
117         }
118     }
119 }
120 
FlipMatrix(GraphicTransformType transform,TextureExportBufferDrawParam & params)121 void RSRenderThreadUtil::FlipMatrix(GraphicTransformType transform, TextureExportBufferDrawParam& params)
122 {
123     GraphicTransformType type = GetFlipTransform(transform);
124     if (type != GraphicTransformType::GRAPHIC_FLIP_H && type != GraphicTransformType::GRAPHIC_FLIP_V) {
125         return;
126     }
127 
128     const int angle = 180;
129     Drawing::Camera3D camera3D;
130     switch (type) {
131         case GraphicTransformType::GRAPHIC_FLIP_H: {
132             camera3D.RotateYDegrees(angle);
133             break;
134         }
135         case GraphicTransformType::GRAPHIC_FLIP_V: {
136             camera3D.RotateXDegrees(angle);
137             break;
138         }
139         default: {
140             return;
141         }
142     }
143     Drawing::Matrix flip;
144     camera3D.ApplyToMatrix(flip);
145     const float half = 0.5f;
146     flip.PreTranslate(-half * params.dstRect.GetWidth(), -half * params.dstRect.GetHeight());
147     flip.PostTranslate(half * params.dstRect.GetWidth(), half * params.dstRect.GetHeight());
148     params.matrix.PreConcat(flip);
149 }
150 
GetSurfaceTransformMatrix(GraphicTransformType rotationTransform,const RectF & bufferBounds)151 Drawing::Matrix RSRenderThreadUtil::GetSurfaceTransformMatrix(
152     GraphicTransformType rotationTransform, const RectF& bufferBounds)
153 {
154     Drawing::Matrix matrix;
155     const float bufferWidth = bufferBounds.GetWidth();
156     const float bufferHeight = bufferBounds.GetHeight();
157 
158     switch (rotationTransform) {
159         case GraphicTransformType::GRAPHIC_ROTATE_90: {
160             matrix.PreTranslate(0, bufferHeight);
161             matrix.PreRotate(-90);  // rotate 90 degrees anti-clockwise at last.
162             break;
163         }
164         case GraphicTransformType::GRAPHIC_ROTATE_180: {
165             matrix.PreTranslate(bufferWidth, bufferHeight);
166             matrix.PreRotate(-180);  // rotate 180 degrees anti-clockwise at last.
167             break;
168         }
169         case GraphicTransformType::GRAPHIC_ROTATE_270: {
170             matrix.PreTranslate(bufferWidth, 0);
171             matrix.PreRotate(-270); // rotate 270 degrees anti-clockwise at last.
172             break;
173         }
174         default:
175             break;
176     }
177     return matrix;
178 }
179 
GetGravityMatrix(Gravity gravity,const RectF & bufferBounds,const RectF & bounds)180 Drawing::Matrix RSRenderThreadUtil::GetGravityMatrix(
181     Gravity gravity, const RectF& bufferBounds, const RectF& bounds)
182 {
183     Drawing::Matrix gravityMatrix;
184     auto frameWidth = bufferBounds.GetWidth();
185     auto frameHeight = bufferBounds.GetHeight();
186     const float boundsWidth = bounds.GetWidth();
187     const float boundsHeight = bounds.GetHeight();
188     if (ROSEN_EQ(frameWidth, boundsWidth) && ROSEN_EQ(frameHeight, boundsHeight)) {
189         return gravityMatrix;
190     }
191 
192     if (!RSPropertiesPainter::GetGravityMatrix(gravity,
193         RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix)) {
194         RS_LOGD("RSRenderThreadUtil::DealWithNodeGravity did not obtain gravity matrix.");
195     }
196 
197     return gravityMatrix;
198 }
199 
GetRotateTransform(GraphicTransformType transform)200 GraphicTransformType RSRenderThreadUtil::GetRotateTransform(GraphicTransformType transform)
201 {
202     switch (transform) {
203         case GraphicTransformType::GRAPHIC_FLIP_H:
204         case GraphicTransformType::GRAPHIC_FLIP_V: {
205             return GraphicTransformType::GRAPHIC_ROTATE_NONE;
206         }
207         case GraphicTransformType::GRAPHIC_FLIP_H_ROT90:
208         case GraphicTransformType::GRAPHIC_FLIP_V_ROT90: {
209             return GraphicTransformType::GRAPHIC_ROTATE_90;
210         }
211         case GraphicTransformType::GRAPHIC_FLIP_H_ROT180:
212         case GraphicTransformType::GRAPHIC_FLIP_V_ROT180: {
213             return GraphicTransformType::GRAPHIC_ROTATE_180;
214         }
215         case GraphicTransformType::GRAPHIC_FLIP_H_ROT270:
216         case GraphicTransformType::GRAPHIC_FLIP_V_ROT270: {
217             return GraphicTransformType::GRAPHIC_ROTATE_270;
218         }
219         default: {
220             return transform;
221         }
222     }
223 }
224 
225 #ifdef ROSEN_OHOS
DealWithSurfaceRotationAndGravity(GraphicTransformType transform,Gravity gravity,RectF & localBounds,TextureExportBufferDrawParam & params)226 void RSRenderThreadUtil::DealWithSurfaceRotationAndGravity(GraphicTransformType transform, Gravity gravity,
227     RectF& localBounds, TextureExportBufferDrawParam& params)
228 {
229     auto rotationTransform = GetRotateTransform(transform);
230     RectF bufferBounds = {0.0f, 0.0f, 0.0f, 0.0f};
231     if (params.buffer != nullptr) {
232         bufferBounds = {0.0f, 0.0f, params.buffer->GetSurfaceBufferWidth(), params.buffer->GetSurfaceBufferHeight()};
233         if (rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_90 ||
234             rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_270) {
235             std::swap(bufferBounds.width_, bufferBounds.height_);
236         }
237     }
238     // deal with gravity
239     params.matrix.PreConcat(GetGravityMatrix(gravity, bufferBounds, localBounds));
240     // deal with transformType
241     params.matrix.PreConcat(GetSurfaceTransformMatrix(rotationTransform, bufferBounds));
242 
243     if (rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_90 ||
244         rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_270) {
245         // after rotate, we should swap dstRect and bound's width and height.
246         std::swap(localBounds.width_, localBounds.height_);
247     }
248     // because we use the gravity matrix above(which will implicitly includes scale effect),
249     // we must disable the scale effect that from srcRect to dstRect.
250     params.dstRect = params.srcRect;
251 }
252 
CreateTextureExportBufferDrawParams(RSSurfaceRenderNode & surfaceNode,GraphicTransformType graphicTransformType,sptr<OHOS::SurfaceBuffer> buffer)253 TextureExportBufferDrawParam RSRenderThreadUtil::CreateTextureExportBufferDrawParams(
254     RSSurfaceRenderNode& surfaceNode, GraphicTransformType graphicTransformType, sptr<OHOS::SurfaceBuffer> buffer)
255 {
256     TextureExportBufferDrawParam params;
257     if (buffer == nullptr) {
258         return params;
259     }
260     params.buffer = buffer;
261     params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
262     const auto& property = surfaceNode.GetRenderProperties();
263     const float boundsWidth = property.GetBoundsWidth();
264     const float boundsHeight = property.GetBoundsHeight();
265     params.dstRect = Drawing::Rect(0, 0, boundsWidth, boundsHeight);
266     RectF localBounds = {0.f, 0.f, boundsWidth, boundsHeight};
267     auto gravity = property.GetFrameGravity();
268     DealWithSurfaceRotationAndGravity(graphicTransformType, gravity, localBounds, params);
269     FlipMatrix(graphicTransformType, params);
270     ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
271     if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
272         SrcRectScaleDown(params, localBounds);
273     } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
274         SrcRectScaleFit(params, localBounds);
275     }
276     return params;
277 }
278 #endif
279 } // namespace Rosen
280 } // namespace OHOS