1 /*
2 * Copyright (c) 2022 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_uni_render_util.h"
17
18 #include <cstdint>
19 #include <memory>
20 #include <parameter.h>
21 #include <parameters.h>
22 #include <string>
23 #include <unordered_set>
24
25 #include "rs_trace.h"
26 #include "scene_board_judgement.h"
27
28 #include "common/rs_optional_trace.h"
29 #include "drawable/dfx/rs_dirty_rects_dfx.h"
30 #include "drawable/rs_display_render_node_drawable.h"
31 #include "drawable/rs_surface_render_node_drawable.h"
32 #include "info_collection/rs_gpu_dirty_region_collection.h"
33 #include "params/rs_display_render_params.h"
34 #include "params/rs_surface_render_params.h"
35 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
36 #include "pipeline/rs_base_render_util.h"
37 #include "pipeline/rs_main_thread.h"
38 #include "pipeline/rs_render_node.h"
39 #include "pipeline/rs_surface_render_node.h"
40 #include "platform/common/rs_log.h"
41 #include "property/rs_properties.h"
42 #include "render/rs_drawing_filter.h"
43 #include "render/rs_maskcolor_shader_filter.h"
44 #include "render/rs_material_filter.h"
45 #include "render/rs_path.h"
46
47 #ifdef RS_ENABLE_VK
48 #include "include/gpu/GrBackendSurface.h"
49 #include "platform/ohos/backend/native_buffer_utils.h"
50 #include "platform/ohos/backend/rs_surface_ohos_vulkan.h"
51 #include "platform/ohos/backend/rs_vulkan_context.h"
52 #endif
53
54 namespace OHOS {
55 namespace Rosen {
56 namespace {
57 constexpr const char* CAPTURE_WINDOW_NAME = "CapsuleWindow";
58 constexpr float GAMMA2_2 = 2.2f;
59 }
60
MergeDirtyHistory(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,ScreenInfo & screenInfo,RSDirtyRectsDfx & rsDirtyRectsDfx,RSDisplayRenderParams & params)61 std::vector<RectI> RSUniRenderUtil::MergeDirtyHistory(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable,
62 int32_t bufferAge, ScreenInfo& screenInfo, RSDirtyRectsDfx& rsDirtyRectsDfx, RSDisplayRenderParams& params)
63 {
64 // renderThreadParams/dirtyManager not null in caller
65 auto dirtyManager = displayDrawable.GetSyncDirtyManager();
66 auto& curAllSurfaceDrawables = params.GetAllMainAndLeashSurfaceDrawables();
67 RSUniRenderUtil::MergeDirtyHistoryForDrawable(displayDrawable, bufferAge, params, false);
68 Occlusion::Region dirtyRegion = RSUniRenderUtil::MergeVisibleDirtyRegion(
69 curAllSurfaceDrawables, RSUniRenderThread::Instance().GetDrawStatusVec(), false);
70 const auto clipRectThreshold = RSSystemProperties::GetClipRectThreshold();
71 if (clipRectThreshold < 1.f) {
72 Occlusion::Region allDirtyRegion{ Occlusion::Rect{ dirtyManager->GetDirtyRegion() } };
73 allDirtyRegion.OrSelf(dirtyRegion);
74 auto bound = allDirtyRegion.GetBound();
75 if (allDirtyRegion.GetSize() > 1 && !bound.IsEmpty() &&
76 allDirtyRegion.Area() > bound.Area() * clipRectThreshold) {
77 dirtyManager->MergeDirtyRectAfterMergeHistory(bound.ToRectI());
78 RS_OPTIONAL_TRACE_NAME_FMT("dirty expand: %s to %s",
79 allDirtyRegion.GetRegionInfo().c_str(), bound.GetRectInfo().c_str());
80 }
81 }
82 Occlusion::Region globalDirtyRegion{ Occlusion::Rect{ dirtyManager->GetDirtyRegion() } };
83 if (screenInfo.isSamplingOn && screenInfo.samplingScale > 0) {
84 Occlusion::Region allDirtyRegion{dirtyRegion.Or(globalDirtyRegion)};
85 Occlusion::Region expandedAllDirtyRegion;
86 constexpr int expandSizeByFloatRounding{1}; // Float rounding will additionally expand by 1 pixel
87 int expandSize = static_cast<int>(std::ceil(
88 (screenInfo.samplingDistance + expandSizeByFloatRounding) / screenInfo.samplingScale));
89 for (auto rect : allDirtyRegion.GetRegionRects()) {
90 rect.Expand(expandSize, expandSize, expandSize, expandSize);
91 Occlusion::Region expandedRegion{rect};
92 expandedAllDirtyRegion.OrSelf(expandedRegion);
93 }
94 RSUniRenderUtil::SetAllSurfaceDrawableGlobalDityRegion(curAllSurfaceDrawables,
95 expandedAllDirtyRegion);
96 rsDirtyRectsDfx.SetExpandedDirtyRegion(expandedAllDirtyRegion);
97 } else {
98 RSUniRenderUtil::SetAllSurfaceDrawableGlobalDityRegion(curAllSurfaceDrawables,
99 dirtyRegion.Or(globalDirtyRegion));
100 }
101
102 // DFX START
103 rsDirtyRectsDfx.SetDirtyRegion(dirtyRegion);
104 // DFX END
105
106 RectI rect = dirtyManager->GetDirtyRegionFlipWithinSurface();
107 auto rects = RSUniRenderUtil::ScreenIntersectDirtyRects(dirtyRegion, screenInfo);
108 if (!rect.IsEmpty()) {
109 rects.emplace_back(rect);
110 RectI screenRectI(0, 0, static_cast<int32_t>(screenInfo.phyWidth), static_cast<int32_t>(screenInfo.phyHeight));
111 GpuDirtyRegionCollection::GetInstance().UpdateGlobalDirtyInfoForDFX(rect.IntersectRect(screenRectI));
112 }
113 if (screenInfo.isSamplingOn && screenInfo.samplingScale > 0) {
114 std::vector<RectI> dstDamageRegionrects;
115 for (const auto& rect : rects) {
116 Drawing::Matrix scaleMatrix;
117 scaleMatrix.SetScaleTranslate(screenInfo.samplingScale, screenInfo.samplingScale,
118 screenInfo.samplingTranslateX, screenInfo.samplingTranslateY);
119 RectI mappedRect = RSObjAbsGeometry::MapRect(rect.ConvertTo<float>(), scaleMatrix);
120 const Vector4<int> expandSize{screenInfo.samplingDistance, screenInfo.samplingDistance,
121 screenInfo.samplingDistance, screenInfo.samplingDistance};
122 dstDamageRegionrects.emplace_back(mappedRect.MakeOutset(expandSize));
123 }
124 return dstDamageRegionrects;
125 }
126 return rects;
127 }
128
MergeDirtyHistoryInVirtual(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,ScreenInfo & screenInfo)129 std::vector<RectI> RSUniRenderUtil::MergeDirtyHistoryInVirtual(
130 DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable, int32_t bufferAge, ScreenInfo& screenInfo)
131 {
132 auto params = static_cast<RSDisplayRenderParams*>(displayDrawable.GetRenderParams().get());
133 auto& renderThreadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
134 if (!renderThreadParams || !params) {
135 return {};
136 }
137 auto& curAllSurfaceDrawables = params->GetAllMainAndLeashSurfaceDrawables();
138 auto dirtyManager = displayDrawable.GetSyncDirtyManager();
139 RSUniRenderUtil::MergeDirtyHistoryInVirtual(displayDrawable, bufferAge);
140 Occlusion::Region dirtyRegion = RSUniRenderUtil::MergeVisibleDirtyRegionInVirtual(curAllSurfaceDrawables);
141
142 RectI rect = dirtyManager->GetRectFlipWithinSurface(dirtyManager->GetDirtyRegionInVirtual());
143 auto rects = RSUniRenderUtil::ScreenIntersectDirtyRects(dirtyRegion, screenInfo);
144 if (!rect.IsEmpty()) {
145 rects.emplace_back(rect);
146 }
147
148 return rects;
149 }
150
MergeDirtyHistoryForDrawable(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,RSDisplayRenderParams & params,bool useAlignedDirtyRegion)151 void RSUniRenderUtil::MergeDirtyHistoryForDrawable(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable,
152 int32_t bufferAge, RSDisplayRenderParams& params, bool useAlignedDirtyRegion)
153 {
154 auto& curAllSurfaceDrawables = params.GetAllMainAndLeashSurfaceDrawables();
155 // update all child surfacenode history
156 for (auto it = curAllSurfaceDrawables.rbegin(); it != curAllSurfaceDrawables.rend(); ++it) {
157 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
158 if (surfaceNodeDrawable == nullptr) {
159 continue;
160 }
161 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
162 if (surfaceParams == nullptr || !surfaceParams->IsAppWindow()) {
163 continue;
164 }
165 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
166 if (surfaceDirtyManager == nullptr) {
167 continue;
168 }
169 RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderUtil::MergeDirtyHistory for surfaceNode %" PRIu64"",
170 surfaceParams->GetId());
171 if (!surfaceDirtyManager->SetBufferAge(bufferAge)) {
172 ROSEN_LOGW("RSUniRenderUtil::MergeDirtyHistory with invalid buffer age %{public}d", bufferAge);
173 }
174 surfaceDirtyManager->IntersectDirtyRect(surfaceParams->GetOldDirtyInSurface());
175 surfaceDirtyManager->UpdateDirty(useAlignedDirtyRegion);
176 }
177
178 // update display dirtymanager
179 if (auto dirtyManager = displayDrawable.GetSyncDirtyManager()) {
180 dirtyManager->SetBufferAge(bufferAge);
181 dirtyManager->UpdateDirty(useAlignedDirtyRegion);
182 }
183 }
184
MergeVisibleDirtyRegion(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceNodeDrawables,std::vector<NodeId> & hasVisibleDirtyRegionSurfaceVec,bool useAlignedDirtyRegion)185 Occlusion::Region RSUniRenderUtil::MergeVisibleDirtyRegion(
186 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceNodeDrawables,
187 std::vector<NodeId>& hasVisibleDirtyRegionSurfaceVec, bool useAlignedDirtyRegion)
188 {
189 Occlusion::Region allSurfaceVisibleDirtyRegion;
190 for (auto it = allSurfaceNodeDrawables.rbegin(); it != allSurfaceNodeDrawables.rend(); ++it) {
191 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
192 if (surfaceNodeDrawable == nullptr) {
193 RS_LOGI("MergeVisibleDirtyRegion surfaceNodeDrawable is nullptr");
194 continue;
195 }
196 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
197 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
198 if (!surfaceParams || !surfaceDirtyManager) {
199 RS_LOGI("RSUniRenderUtil::MergeVisibleDirtyRegion node(%{public}" PRIu64") params or "
200 "dirty manager is nullptr", surfaceNodeDrawable->GetId());
201 continue;
202 }
203 if (!surfaceParams->IsAppWindow() || surfaceParams->GetDstRect().IsEmpty()) {
204 continue;
205 }
206 auto surfaceDirtyRect = surfaceDirtyManager->GetDirtyRegion();
207 Occlusion::Rect dirtyRect { surfaceDirtyRect.left_, surfaceDirtyRect.top_, surfaceDirtyRect.GetRight(),
208 surfaceDirtyRect.GetBottom() };
209 auto visibleRegion = surfaceParams->GetVisibleRegion();
210 Occlusion::Region surfaceDirtyRegion { dirtyRect };
211 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
212
213 surfaceNodeDrawable->SetVisibleDirtyRegion(surfaceVisibleDirtyRegion);
214 if (!surfaceVisibleDirtyRegion.IsEmpty()) {
215 hasVisibleDirtyRegionSurfaceVec.emplace_back(surfaceParams->GetId());
216 }
217 if (useAlignedDirtyRegion) {
218 Occlusion::Region alignedRegion = AlignedDirtyRegion(surfaceVisibleDirtyRegion);
219 surfaceNodeDrawable->SetAlignedVisibleDirtyRegion(alignedRegion);
220 allSurfaceVisibleDirtyRegion.OrSelf(alignedRegion);
221 GpuDirtyRegionCollection::GetInstance().UpdateActiveDirtyInfoForDFX(surfaceParams->GetId(),
222 surfaceNodeDrawable->GetName(), alignedRegion.GetRegionRectIs());
223 } else {
224 allSurfaceVisibleDirtyRegion = allSurfaceVisibleDirtyRegion.Or(surfaceVisibleDirtyRegion);
225 GpuDirtyRegionCollection::GetInstance().UpdateActiveDirtyInfoForDFX(surfaceParams->GetId(),
226 surfaceNodeDrawable->GetName(), surfaceVisibleDirtyRegion.GetRegionRectIs());
227 }
228 }
229 return allSurfaceVisibleDirtyRegion;
230 }
231
MergeDirtyHistoryInVirtual(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,bool renderParallel)232 void RSUniRenderUtil::MergeDirtyHistoryInVirtual(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable,
233 int32_t bufferAge, bool renderParallel)
234 {
235 (void)renderParallel;
236 auto& params = displayDrawable.GetRenderParams();
237 if (!params) {
238 RS_LOGE("RSUniRenderUtil::MergeDirtyHistory params is nullptr");
239 return;
240 }
241 auto& curAllSurfaceDrawables = params->GetAllMainAndLeashSurfaceDrawables();
242 for (auto it = curAllSurfaceDrawables.rbegin(); it != curAllSurfaceDrawables.rend(); ++it) {
243 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
244 if (surfaceNodeDrawable == nullptr) {
245 continue;
246 }
247 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
248 if (surfaceParams == nullptr || !surfaceParams->IsAppWindow()) {
249 continue;
250 }
251 RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderUtil::MergeDirtyHistory for surfaceNode %" PRIu64"",
252 surfaceParams->GetId());
253 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
254 surfaceDirtyManager->MergeDirtyHistoryInVirtual(bufferAge);
255 }
256 // update display dirtymanager
257 auto displayDirtyManager = displayDrawable.GetSyncDirtyManager();
258 displayDirtyManager->MergeDirtyHistoryInVirtual(bufferAge);
259 }
260
MergeVisibleDirtyRegionInVirtual(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceNodeDrawables)261 Occlusion::Region RSUniRenderUtil::MergeVisibleDirtyRegionInVirtual(
262 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceNodeDrawables)
263 {
264 Occlusion::Region allSurfaceVisibleDirtyRegion;
265 for (auto it = allSurfaceNodeDrawables.rbegin(); it != allSurfaceNodeDrawables.rend(); ++it) {
266 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
267 if (surfaceNodeDrawable == nullptr) {
268 RS_LOGI("MergeVisibleDirtyRegion surfaceNodeDrawable is nullptr");
269 continue;
270 }
271 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
272 if (!surfaceParams) {
273 RS_LOGI("RSUniRenderUtil::MergeVisibleDirtyRegion surface params is nullptr");
274 continue;
275 }
276 if (!surfaceParams->IsAppWindow() || surfaceParams->GetDstRect().IsEmpty() ||
277 surfaceParams->GetName().find(CAPTURE_WINDOW_NAME) != std::string::npos ||
278 surfaceParams->GetIsSkipLayer()) {
279 continue;
280 }
281 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
282 auto surfaceDirtyRect = surfaceDirtyManager->GetDirtyRegionInVirtual();
283 Occlusion::Rect dirtyRect { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
284 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() };
285 auto visibleRegion = surfaceParams->GetVisibleRegionInVirtual();
286 Occlusion::Region surfaceDirtyRegion { dirtyRect };
287 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
288 allSurfaceVisibleDirtyRegion = allSurfaceVisibleDirtyRegion.Or(surfaceVisibleDirtyRegion);
289 }
290 return allSurfaceVisibleDirtyRegion;
291 }
292
SetAllSurfaceDrawableGlobalDityRegion(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceDrawables,const Occlusion::Region & globalDirtyRegion)293 void RSUniRenderUtil::SetAllSurfaceDrawableGlobalDityRegion(
294 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceDrawables,
295 const Occlusion::Region& globalDirtyRegion)
296 {
297 // Set Surface Global Dirty Region
298 for (auto it = allSurfaceDrawables.rbegin(); it != allSurfaceDrawables.rend(); ++it) {
299 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
300 if (surfaceNodeDrawable == nullptr) {
301 continue;
302 }
303 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
304 if (!surfaceParams) {
305 RS_LOGW("RSUniRenderUtil::MergeVisibleDirtyRegion surface params is nullptr");
306 continue;
307 }
308 if (!surfaceParams->IsMainWindowType()) {
309 continue;
310 }
311 // set display dirty region to surfaceNodeDrawable
312 surfaceNodeDrawable->SetGlobalDirtyRegion(globalDirtyRegion);
313 surfaceNodeDrawable->SetDirtyRegionAlignedEnable(false);
314 }
315 Occlusion::Region curVisibleDirtyRegion;
316 for (auto& it : allSurfaceDrawables) {
317 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(it);
318 if (surfaceNodeDrawable == nullptr) {
319 continue;
320 }
321 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
322 if (!surfaceParams) {
323 RS_LOGE("RSUniRenderUtil::MergeVisibleDirtyRegion surface params is nullptr");
324 continue;
325 }
326 if (!surfaceParams->IsMainWindowType()) {
327 continue;
328 }
329 // set display dirty region to surfaceNodeDrawable
330 surfaceNodeDrawable->SetDirtyRegionBelowCurrentLayer(curVisibleDirtyRegion);
331 auto visibleDirtyRegion = surfaceNodeDrawable->GetVisibleDirtyRegion();
332 curVisibleDirtyRegion = curVisibleDirtyRegion.Or(visibleDirtyRegion);
333 }
334 }
335
ScreenIntersectDirtyRects(const Occlusion::Region & region,ScreenInfo & screenInfo)336 std::vector<RectI> RSUniRenderUtil::ScreenIntersectDirtyRects(const Occlusion::Region ®ion, ScreenInfo& screenInfo)
337 {
338 const std::vector<Occlusion::Rect>& rects = region.GetRegionRects();
339 std::vector<RectI> retRects;
340 for (const Occlusion::Rect& rect : rects) {
341 // origin transformation
342 #ifdef RS_ENABLE_VK
343 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
344 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
345 retRects.emplace_back(RectI(rect.left_, rect.top_,
346 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
347 } else {
348 retRects.emplace_back(RectI(rect.left_, screenInfo.GetRotatedHeight() - rect.bottom_,
349 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
350 }
351 #else
352 retRects.emplace_back(RectI(rect.left_, screenInfo.GetRotatedHeight() - rect.bottom_,
353 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
354 #endif
355 }
356 RS_LOGD("ScreenIntersectDirtyRects size %{public}d %{public}s", region.GetSize(), region.GetRegionInfo().c_str());
357 return retRects;
358 }
359
GetFilpDirtyRects(const std::vector<RectI> & srcRects,const ScreenInfo & screenInfo)360 std::vector<RectI> RSUniRenderUtil::GetFilpDirtyRects(const std::vector<RectI>& srcRects, const ScreenInfo& screenInfo)
361 {
362 #ifdef RS_ENABLE_VK
363 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
364 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
365 return srcRects;
366 }
367 #endif
368
369 return FilpRects(srcRects, screenInfo);
370 }
371
FilpRects(const std::vector<RectI> & srcRects,const ScreenInfo & screenInfo)372 std::vector<RectI> RSUniRenderUtil::FilpRects(const std::vector<RectI>& srcRects, const ScreenInfo& screenInfo)
373 {
374 std::vector<RectI> retRects;
375 for (const RectI& rect : srcRects) {
376 retRects.emplace_back(RectI(rect.left_, screenInfo.GetRotatedHeight() - rect.top_ - rect.height_,
377 rect.width_, rect.height_));
378 }
379 return retRects;
380 }
381
SrcRectScaleFit(BufferDrawParam & params,const sptr<SurfaceBuffer> & buffer,const sptr<IConsumerSurface> & surface,RectF & localBounds)382 void RSUniRenderUtil::SrcRectScaleFit(BufferDrawParam& params, const sptr<SurfaceBuffer>& buffer,
383 const sptr<IConsumerSurface>& surface, RectF& localBounds)
384 {
385 if (buffer == nullptr || surface == nullptr) {
386 RS_LOGE("buffer or surface is nullptr");
387 return;
388 }
389 uint32_t srcWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
390 uint32_t srcHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
391 uint32_t newWidth = 0;
392 uint32_t newHeight = 0;
393 // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
394 uint32_t boundsWidth = static_cast<uint32_t>(localBounds.GetWidth());
395 uint32_t boundsHeight = static_cast<uint32_t>(localBounds.GetHeight());
396 if (boundsWidth == 0 || boundsHeight == 0 || srcWidth == 0 || srcHeight == 0) {
397 return;
398 }
399
400 if (srcWidth * boundsHeight > srcHeight * boundsWidth) {
401 newWidth = boundsWidth;
402 newHeight = srcHeight * newWidth / srcWidth;
403 } else if (srcWidth * boundsHeight < srcHeight * boundsWidth) {
404 newHeight = boundsHeight;
405 newWidth = newHeight * srcWidth / srcHeight;
406 } else {
407 newWidth = boundsWidth;
408 newHeight = boundsHeight;
409 }
410 newHeight = newHeight * srcHeight / boundsHeight;
411 newWidth = newWidth * srcWidth / boundsWidth;
412 if (newWidth < srcWidth) {
413 auto halfdw = (srcWidth - newWidth) / 2;
414 params.dstRect =
415 Drawing::Rect(params.srcRect.GetLeft() + static_cast<int32_t>(halfdw), params.srcRect.GetTop(),
416 params.srcRect.GetLeft() + static_cast<int32_t>(halfdw) + static_cast<int32_t>(newWidth),
417 params.srcRect.GetTop() + params.srcRect.GetHeight());
418 } else if (newHeight < srcHeight) {
419 auto halfdh = (srcHeight - newHeight) / 2;
420 params.dstRect =
421 Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + static_cast<int32_t>(halfdh),
422 params.srcRect.GetLeft() + params.srcRect.GetWidth(),
423 params.srcRect.GetTop() + static_cast<int32_t>(halfdh) + static_cast<int32_t>(newHeight));
424 }
425 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleFit name:%{public}s,"
426 " dstRect [%{public}f %{public}f %{public}f %{public}f]",
427 surface->GetName().c_str(), params.dstRect.GetLeft(), params.dstRect.GetTop(),
428 params.dstRect.GetWidth(), params.dstRect.GetHeight());
429 }
430
SrcRectScaleDown(BufferDrawParam & params,const sptr<SurfaceBuffer> & buffer,const sptr<IConsumerSurface> & surface,RectF & localBounds)431 void RSUniRenderUtil::SrcRectScaleDown(BufferDrawParam& params, const sptr<SurfaceBuffer>& buffer,
432 const sptr<IConsumerSurface>& surface, RectF& localBounds)
433 {
434 if (buffer == nullptr || surface == nullptr) {
435 return;
436 }
437 uint32_t newWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
438 uint32_t newHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
439 // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
440 uint32_t boundsWidth = static_cast<uint32_t>(localBounds.GetWidth());
441 uint32_t boundsHeight = static_cast<uint32_t>(localBounds.GetHeight());
442
443 uint32_t newWidthBoundsHeight = newWidth * boundsHeight;
444 uint32_t newHeightBoundsWidth = newHeight * boundsWidth;
445
446 if (newWidthBoundsHeight > newHeightBoundsWidth) {
447 newWidth = boundsWidth * newHeight / boundsHeight;
448 } else if (newWidthBoundsHeight < newHeightBoundsWidth) {
449 newHeight = boundsHeight * newWidth / boundsWidth;
450 } else {
451 return;
452 }
453
454 uint32_t currentWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
455 uint32_t currentHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
456 if (newWidth < currentWidth) {
457 // the crop is too wide
458 uint32_t dw = currentWidth - newWidth;
459 auto halfdw = dw / 2;
460 params.srcRect =
461 Drawing::Rect(params.srcRect.GetLeft() + static_cast<int32_t>(halfdw), params.srcRect.GetTop(),
462 params.srcRect.GetLeft() + static_cast<int32_t>(halfdw) + static_cast<int32_t>(newWidth),
463 params.srcRect.GetTop() + params.srcRect.GetHeight());
464 } else {
465 // thr crop is too tall
466 uint32_t dh = currentHeight - newHeight;
467 auto halfdh = dh / 2;
468 params.srcRect =
469 Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + static_cast<int32_t>(halfdh),
470 params.srcRect.GetLeft() + params.srcRect.GetWidth(),
471 params.srcRect.GetTop() + static_cast<int32_t>(halfdh) + static_cast<int32_t>(newHeight));
472 }
473 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleDown name:%{public}s,"
474 " srcRect [%{public}f %{public}f %{public}f %{public}f]",
475 surface->GetName().c_str(), params.srcRect.GetLeft(), params.srcRect.GetTop(),
476 params.srcRect.GetWidth(), params.srcRect.GetHeight());
477 }
478
SetSrcRect(BufferDrawParam & params,const sptr<SurfaceBuffer> & buffer)479 void RSUniRenderUtil::SetSrcRect(BufferDrawParam& params, const sptr<SurfaceBuffer>& buffer)
480 {
481 Rect crop = {0, 0, 0, 0};
482 params.hasCropMetadata = buffer->GetCropMetadata(crop);
483
484 if (UNLIKELY(params.hasCropMetadata)) {
485 RS_LOGD("buffer has crop metadata, "
486 "left = %{public}u, right = %{public}u, width = %{public}u, height = %{public}u",
487 crop.x, crop.y, crop.w, crop.h);
488 params.srcRect = Drawing::Rect(crop.x, crop.y, crop.x + crop.w, crop.y + crop.h);
489 } else {
490 params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
491 }
492 }
493
GetMatrixOfBufferToRelRect(const RSSurfaceRenderNode & node)494 Drawing::Matrix RSUniRenderUtil::GetMatrixOfBufferToRelRect(const RSSurfaceRenderNode& node)
495 {
496 const sptr<SurfaceBuffer> buffer = node.GetRSSurfaceHandler()->GetBuffer();
497 if (buffer == nullptr) {
498 return Drawing::Matrix();
499 }
500
501 auto consumer = node.GetRSSurfaceHandler()->GetConsumer();
502 if (consumer == nullptr) {
503 return Drawing::Matrix();
504 }
505
506 BufferDrawParam params;
507 params.buffer = buffer;
508 params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
509 const RSProperties& property = node.GetRenderProperties();
510 params.dstRect = Drawing::Rect(0, 0, property.GetBoundsWidth(), property.GetBoundsHeight());
511 auto transform = RSBaseRenderUtil::GetSurfaceBufferTransformType(consumer, buffer);
512 RectF localBounds = { 0.0f, 0.0f, property.GetBoundsWidth(), property.GetBoundsHeight() };
513 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, property.GetFrameGravity(), localBounds, params);
514 RSBaseRenderUtil::FlipMatrix(transform, params);
515 return params.matrix;
516 }
517
CreateBufferDrawParam(const RSSurfaceRenderNode & node,bool forceCPU,uint32_t threadIndex,bool useRenderParams)518 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(
519 const RSSurfaceRenderNode& node, bool forceCPU, uint32_t threadIndex, bool useRenderParams)
520 {
521 BufferDrawParam params;
522
523 auto drawable = node.GetRenderDrawable();
524 if (useRenderParams && !drawable) {
525 return params;
526 }
527 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
528 auto& nodeParams = surfaceDrawable->GetRenderParams();
529 if (useRenderParams && !nodeParams) {
530 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam RenderThread nodeParams is nullptr");
531 return params;
532 }
533 auto surfaceHandler = node.GetRSSurfaceHandler();
534 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(nodeParams.get());
535 const RSProperties& property = node.GetRenderProperties();
536
537 params.threadIndex = threadIndex;
538 params.useBilinearInterpolation = useRenderParams ?
539 surfaceParams->NeedBilinearInterpolation() : node.NeedBilinearInterpolation();
540 params.useCPU = forceCPU;
541 Drawing::Filter filter;
542 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
543 params.paint.SetFilter(filter);
544
545 auto boundWidth = useRenderParams ? nodeParams->GetBounds().GetWidth() : property.GetBoundsWidth();
546 auto boundHeight = useRenderParams ? nodeParams->GetBounds().GetHeight() : property.GetBoundsHeight();
547 params.dstRect = Drawing::Rect(0, 0, boundWidth, boundHeight);
548
549 const sptr<SurfaceBuffer> buffer = useRenderParams ? surfaceParams->GetBuffer() : surfaceHandler->GetBuffer();
550 if (buffer == nullptr) {
551 return params;
552 }
553 params.buffer = buffer;
554 params.acquireFence = useRenderParams ? nodeParams->GetAcquireFence() : surfaceHandler->GetAcquireFence();
555 SetSrcRect(params, buffer);
556 auto consumer = useRenderParams ? surfaceDrawable->GetConsumerOnDraw() : surfaceHandler->GetConsumer();
557 if (consumer == nullptr) {
558 return params;
559 }
560 auto transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
561 if (consumer->GetSurfaceBufferTransformType(buffer, &transform) != GSERROR_OK) {
562 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam GetSurfaceBufferTransformType failed");
563 }
564 RectF localBounds = { 0.0f, 0.0f, boundWidth, boundHeight };
565 auto gravity = useRenderParams ? nodeParams->GetFrameGravity() : property.GetFrameGravity();
566 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, gravity, localBounds, params, surfaceParams);
567 RSBaseRenderUtil::FlipMatrix(transform, params);
568 ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
569 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
570 SrcRectScaleDown(params, buffer, consumer, localBounds);
571 } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
572 SrcRectScaleFit(params, buffer, consumer, localBounds);
573 }
574 return params;
575 }
576
CreateBufferDrawParam(const DrawableV2::RSSurfaceRenderNodeDrawable & surfaceDrawable,bool forceCPU,uint32_t threadIndex)577 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(
578 const DrawableV2::RSSurfaceRenderNodeDrawable& surfaceDrawable, bool forceCPU, uint32_t threadIndex)
579 {
580 BufferDrawParam params;
581 auto& nodeParams = surfaceDrawable.GetRenderParams();
582 if (!nodeParams) {
583 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam RenderThread nodeParams is nullptr");
584 return params;
585 }
586 auto surfaceNodeParams = static_cast<RSSurfaceRenderParams*>(nodeParams.get());
587 params.threadIndex = threadIndex;
588 params.useBilinearInterpolation = surfaceNodeParams->NeedBilinearInterpolation();
589 params.useCPU = forceCPU;
590 Drawing::Filter filter;
591 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
592 params.paint.SetFilter(filter);
593
594 auto boundWidth = nodeParams->GetBounds().GetWidth();
595 auto boundHeight = nodeParams->GetBounds().GetHeight();
596 params.dstRect = Drawing::Rect(0, 0, boundWidth, boundHeight);
597
598 const sptr<SurfaceBuffer> buffer = nodeParams->GetBuffer();
599 if (buffer == nullptr) {
600 return params;
601 }
602 params.buffer = buffer;
603 params.acquireFence = nodeParams->GetAcquireFence();
604 SetSrcRect(params, buffer);
605 auto consumer = surfaceDrawable.GetConsumerOnDraw();
606 if (consumer == nullptr) {
607 return params;
608 }
609 auto transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
610 if (consumer->GetSurfaceBufferTransformType(buffer, &transform) != GSERROR_OK) {
611 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam GetSurfaceBufferTransformType failed");
612 }
613 RectF localBounds = { 0.0f, 0.0f, boundWidth, boundHeight };
614 auto gravity = nodeParams->GetFrameGravity();
615 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, gravity, localBounds, params, surfaceNodeParams);
616 RSBaseRenderUtil::FlipMatrix(transform, params);
617 ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
618 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
619 SrcRectScaleDown(params, buffer, consumer, localBounds);
620 } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
621 SrcRectScaleFit(params, buffer, consumer, localBounds);
622 }
623 return params;
624 }
625
CreateBufferDrawParamForRotationFixed(const DrawableV2::RSSurfaceRenderNodeDrawable & surfaceDrawable,RSSurfaceRenderParams & renderParams)626 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParamForRotationFixed(
627 const DrawableV2::RSSurfaceRenderNodeDrawable& surfaceDrawable, RSSurfaceRenderParams& renderParams)
628 {
629 BufferDrawParam params;
630 params.threadIndex = static_cast<uint32_t>(gettid());
631 params.useBilinearInterpolation = renderParams.NeedBilinearInterpolation();
632 params.useCPU = false;
633 params.targetColorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
634 #ifdef USE_VIDEO_PROCESSING_ENGINE
635 params.sdrNits = renderParams.GetSdrNit();
636 params.tmoNits = renderParams.GetDisplayNit();
637 params.displayNits = params.tmoNits / std::pow(renderParams.GetBrightnessRatio(), GAMMA2_2); // gamma 2.2
638 #endif
639
640 Drawing::Filter filter;
641 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
642 params.paint.SetFilter(filter);
643
644 auto buffer = renderParams.GetBuffer();
645 if (buffer == nullptr) {
646 return params;
647 }
648 params.buffer = buffer;
649 params.acquireFence = renderParams.GetAcquireFence();
650 auto srcRect = renderParams.GetLayerInfo().srcRect;
651 params.srcRect = Drawing::Rect(srcRect.x, srcRect.y, srcRect.x + srcRect.w, srcRect.y + srcRect.h);
652
653 auto dstRect = renderParams.GetLayerInfo().dstRect;
654 params.matrix = Drawing::Matrix();
655 params.matrix.PreTranslate(static_cast<float>(dstRect.x), static_cast<float>(dstRect.y));
656
657 auto layerTransform = renderParams.GetLayerInfo().transformType;
658 int realRotation = RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(layerTransform));
659 auto flip = RSBaseRenderUtil::GetFlipTransform(layerTransform);
660 // calculate transform in anti-clockwise
661 auto transform = RSBaseRenderUtil::RotateEnumToInt(realRotation, flip);
662
663 RectF localBounds = { 0.0f, 0.0f,
664 static_cast<float>(dstRect.w), static_cast<float>(dstRect.h) };
665 DealWithRotationAndGravityForRotationFixed(transform, renderParams.GetFrameGravity(), localBounds, params);
666 RSBaseRenderUtil::FlipMatrix(transform, params);
667 return params;
668 }
669
DealWithRotationAndGravityForRotationFixed(GraphicTransformType transform,Gravity gravity,RectF & localBounds,BufferDrawParam & params)670 void RSUniRenderUtil::DealWithRotationAndGravityForRotationFixed(GraphicTransformType transform, Gravity gravity,
671 RectF& localBounds, BufferDrawParam& params)
672 {
673 auto rotationTransform = RSBaseRenderUtil::GetRotateTransform(transform);
674 params.matrix.PreConcat(RSBaseRenderUtil::GetSurfaceTransformMatrixForRotationFixed(
675 rotationTransform, localBounds));
676 if (rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_90 ||
677 rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_270) {
678 // after rotate, we should swap dstRect and bound's width and height.
679 std::swap(localBounds.width_, localBounds.height_);
680 }
681 params.dstRect = Drawing::Rect(0, 0, params.srcRect.GetWidth(), params.srcRect.GetHeight());
682
683 Drawing::Matrix gravityMatrix;
684 if (!RSPropertiesPainter::GetGravityMatrix(gravity, localBounds,
685 params.srcRect.GetWidth(), params.srcRect.GetHeight(), gravityMatrix)) {
686 RS_LOGD("RSUniRenderUtil::DealWithRotationAndGravityForRotationFixed did not obtain gravity matrix.");
687 }
688 params.matrix.PreConcat(gravityMatrix);
689 }
690
CreateBufferDrawParam(const RSDisplayRenderNode & node,bool forceCPU)691 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(const RSDisplayRenderNode& node, bool forceCPU)
692 {
693 BufferDrawParam params;
694 params.useCPU = forceCPU;
695 Drawing::Filter filter;
696 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
697 params.paint.SetFilter(filter);
698
699 auto drawable = node.GetRenderDrawable();
700 if (!drawable) {
701 return params;
702 }
703 auto displayDrawable = std::static_pointer_cast<DrawableV2::RSDisplayRenderNodeDrawable>(drawable);
704 auto surfaceHandler = displayDrawable->GetRSSurfaceHandlerOnDraw();
705 const sptr<SurfaceBuffer> buffer = surfaceHandler->GetBuffer();
706 if (!buffer) {
707 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam buffer is null.");
708 return params;
709 }
710 params.buffer = buffer;
711 params.acquireFence = surfaceHandler->GetAcquireFence();
712 SetSrcRect(params, buffer);
713 params.dstRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
714 return params;
715 }
716
CreateBufferDrawParam(const RSSurfaceHandler & surfaceHandler,bool forceCPU)717 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(const RSSurfaceHandler& surfaceHandler, bool forceCPU)
718 {
719 BufferDrawParam bufferDrawParam;
720 bufferDrawParam.useCPU = forceCPU;
721 Drawing::Filter filter;
722 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
723 bufferDrawParam.paint.SetFilter(filter);
724
725 const sptr<SurfaceBuffer> buffer = surfaceHandler.GetBuffer();
726 if (!buffer) {
727 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam buffer is null.");
728 return bufferDrawParam;
729 }
730 bufferDrawParam.buffer = buffer;
731 bufferDrawParam.acquireFence = surfaceHandler.GetAcquireFence();
732 SetSrcRect(bufferDrawParam, buffer);
733 bufferDrawParam.dstRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
734 return bufferDrawParam;
735 }
736
CreateLayerBufferDrawParam(const LayerInfoPtr & layer,bool forceCPU)737 BufferDrawParam RSUniRenderUtil::CreateLayerBufferDrawParam(const LayerInfoPtr& layer, bool forceCPU)
738 {
739 BufferDrawParam params;
740 if (layer == nullptr) {
741 return params;
742 }
743 params.useCPU = forceCPU;
744 Drawing::Filter filter;
745 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
746 params.paint.SetFilter(filter);
747 params.paint.SetAlpha(layer->GetAlpha().gAlpha);
748 sptr<SurfaceBuffer> buffer = layer->GetBuffer();
749 if (buffer == nullptr) {
750 return params;
751 }
752 params.acquireFence = layer->GetAcquireFence();
753 params.buffer = buffer;
754 SetSrcRect(params, buffer);
755 auto boundRect = layer->GetBoundSize();
756 params.dstRect = Drawing::Rect(0, 0, boundRect.w, boundRect.h);
757
758 auto layerMatrix = layer->GetMatrix();
759 params.matrix = Drawing::Matrix();
760 bool rotationFixed = layer->GetRotationFixed();
761 auto dstRect = layer->GetLayerSize();
762 if (rotationFixed) {
763 // if rotation fixed, not use [total matrix + bounds] to draw buffer, use [src + dst + transform]
764 params.matrix.PreTranslate(static_cast<float>(dstRect.x), static_cast<float>(dstRect.y));
765 auto srcRect = layer->GetCropRect();
766 params.srcRect = Drawing::Rect(srcRect.x, srcRect.y, srcRect.x + srcRect.w, srcRect.y + srcRect.h);
767 } else {
768 params.matrix.SetMatrix(layerMatrix.scaleX, layerMatrix.skewX, layerMatrix.transX, layerMatrix.skewY,
769 layerMatrix.scaleY, layerMatrix.transY, layerMatrix.pers0, layerMatrix.pers1, layerMatrix.pers2);
770 }
771 // rotation degree anti-clockwise
772 int nodeRotation = rotationFixed ? 0 : RSUniRenderUtil::GetRotationFromMatrix(params.matrix);
773 auto layerTransform = layer->GetTransformType();
774 // calculate clockwise rotation degree excluded rotation in total matrix
775 int realRotation = (nodeRotation +
776 RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(layerTransform))) % 360;
777 auto flip = RSBaseRenderUtil::GetFlipTransform(layerTransform);
778 // calculate transform in anti-clockwise
779 auto transform = RSBaseRenderUtil::RotateEnumToInt(realRotation, flip);
780
781 RectF localBounds = { 0.0f, 0.0f,
782 rotationFixed ? static_cast<float>(dstRect.w) : static_cast<float>(boundRect.w),
783 rotationFixed ? static_cast<float>(dstRect.h) : static_cast<float>(boundRect.h) };
784 if (rotationFixed) {
785 DealWithRotationAndGravityForRotationFixed(transform, static_cast<Gravity>(layer->GetGravity()), localBounds,
786 params);
787 } else {
788 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, static_cast<Gravity>(layer->GetGravity()),
789 localBounds, params);
790 }
791 RSBaseRenderUtil::FlipMatrix(transform, params);
792 if (rotationFixed) {
793 // if rotation fixed, no need to calculate scaling mode, it is contained in dstRect
794 return params;
795 }
796 const auto& surface = layer->GetSurface();
797 if (surface == nullptr) {
798 RS_LOGE("buffer or surface is nullptr");
799 return params;
800 }
801
802 ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
803 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
804 SrcRectScaleDown(params, buffer, surface, localBounds);
805 } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
806 SrcRectScaleFit(params, buffer, surface, localBounds);
807 }
808 return params;
809 }
810
IsNeedClient(RSSurfaceRenderNode & node,const ComposeInfo & info)811 bool RSUniRenderUtil::IsNeedClient(RSSurfaceRenderNode& node, const ComposeInfo& info)
812 {
813 if (RSSystemProperties::IsForceClient()) {
814 RS_LOGD("RSUniRenderUtil::IsNeedClient: force client.");
815 return true;
816 }
817 const auto& property = node.GetRenderProperties();
818 if (!ROSEN_EQ(property.GetRotation(), 0.f) || !ROSEN_EQ(property.GetRotationX(), 0.f) ||
819 !ROSEN_EQ(property.GetRotationY(), 0.f) || property.GetQuaternion() != Quaternion()) {
820 RS_LOGD("RSUniRenderUtil::IsNeedClient need client with RSSurfaceRenderNode rotation");
821 return true;
822 }
823 return false;
824 }
825
AlignedDirtyRegion(const Occlusion::Region & dirtyRegion,int32_t alignedBits)826 Occlusion::Region RSUniRenderUtil::AlignedDirtyRegion(const Occlusion::Region& dirtyRegion, int32_t alignedBits)
827 {
828 Occlusion::Region alignedRegion;
829 if (alignedBits <= 1) {
830 return dirtyRegion;
831 }
832 for (const auto& dirtyRect : dirtyRegion.GetRegionRects()) {
833 int32_t left = (dirtyRect.left_ / alignedBits) * alignedBits;
834 int32_t top = (dirtyRect.top_ / alignedBits) * alignedBits;
835 int32_t width = ((dirtyRect.right_ + alignedBits - 1) / alignedBits) * alignedBits - left;
836 int32_t height = ((dirtyRect.bottom_ + alignedBits - 1) / alignedBits) * alignedBits - top;
837 Occlusion::Rect rect = { left, top, left + width, top + height };
838 Occlusion::Region singleAlignedRegion(rect);
839 alignedRegion.OrSelf(singleAlignedRegion);
840 }
841 return alignedRegion;
842 }
843
HandleSubThreadNode(RSSurfaceRenderNode & node,RSPaintFilterCanvas & canvas)844 bool RSUniRenderUtil::HandleSubThreadNode(RSSurfaceRenderNode& node, RSPaintFilterCanvas& canvas)
845 {
846 if (node.IsMainThreadNode()) {
847 RS_LOGE("RSUniRenderUtil::HandleSubThreadNode node.IsMainThreadNode()");
848 return false;
849 } else if (RSMainThread::Instance()->GetDeviceType() == DeviceType::PC &&
850 !node.QueryIfAllHwcChildrenForceDisabledByFilter()) {
851 return false; // this node should do DSS composition in mainThread although it is assigned to subThread
852 }
853 if (!node.HasCachedTexture()) {
854 RS_TRACE_NAME_FMT("HandleSubThreadNode wait %" PRIu64 "", node.GetId());
855 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
856 RSSubThreadManager::Instance()->WaitNodeTask(node.GetId());
857 node.UpdateCompletedCacheSurface();
858 #endif
859 }
860 RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderUtil::HandleSubThreadNode %" PRIu64 "", node.GetId());
861 node.DrawCacheSurface(canvas, UNI_MAIN_THREAD_INDEX, true);
862 return true;
863 }
864
HandleCaptureNode(RSRenderNode & node,RSPaintFilterCanvas & canvas)865 bool RSUniRenderUtil::HandleCaptureNode(RSRenderNode& node, RSPaintFilterCanvas& canvas)
866 {
867 auto surfaceNodePtr = node.ReinterpretCastTo<RSSurfaceRenderNode>();
868 if (surfaceNodePtr == nullptr ||
869 (!surfaceNodePtr->IsAppWindow() && !surfaceNodePtr->IsLeashWindow())) {
870 return false;
871 }
872
873 auto curNode = surfaceNodePtr;
874 if (surfaceNodePtr->IsAppWindow()) {
875 auto rsParent = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNodePtr->GetParent().lock());
876 if (rsParent && rsParent->IsLeashWindow()) {
877 curNode = rsParent;
878 }
879 }
880 if (!curNode->ShouldPaint()) {
881 return false;
882 }
883 if (curNode->IsOnTheTree()) {
884 return HandleSubThreadNode(*curNode, canvas);
885 } else {
886 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
887 if (curNode->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
888 RSSubThreadManager::Instance()->WaitNodeTask(curNode->GetId());
889 }
890 #endif
891 return false;
892 }
893 return false;
894 }
895
TransferToAntiClockwiseDegrees(int angle)896 int RSUniRenderUtil::TransferToAntiClockwiseDegrees(int angle)
897 {
898 static const std::map<int, int> supportedDegrees = { { 90, 270 }, { 180, 180 }, { -90, 90 }, { -180, 180 },
899 { 270, 90 }, { -270, 270 } };
900 auto iter = supportedDegrees.find(angle);
901 return iter != supportedDegrees.end() ? iter->second : 0;
902 }
903
GetRotationFromMatrix(Drawing::Matrix matrix)904 int RSUniRenderUtil::GetRotationFromMatrix(Drawing::Matrix matrix)
905 {
906 Drawing::Matrix::Buffer value;
907 matrix.GetAll(value);
908
909 int rAngle = static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::SKEW_X],
910 value[Drawing::Matrix::Index::SCALE_X]) * (180 / PI)));
911 // transfer the result to anti-clockwise degrees
912 // only rotation with 90°, 180°, 270° are composed through hardware,
913 // in which situation the transformation of the layer needs to be set.
914 return TransferToAntiClockwiseDegrees(rAngle);
915 }
916
GetRotationDegreeFromMatrix(Drawing::Matrix matrix)917 int RSUniRenderUtil::GetRotationDegreeFromMatrix(Drawing::Matrix matrix)
918 {
919 Drawing::Matrix::Buffer value;
920 matrix.GetAll(value);
921 return static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::SKEW_X],
922 value[Drawing::Matrix::Index::SCALE_X]) * (180 / PI)));
923 }
924
GetFloatRotationDegreeFromMatrix(Drawing::Matrix matrix)925 float RSUniRenderUtil::GetFloatRotationDegreeFromMatrix(Drawing::Matrix matrix)
926 {
927 Drawing::Matrix::Buffer value;
928 matrix.GetAll(value);
929 return atan2(value[Drawing::Matrix::Index::SKEW_X], value[Drawing::Matrix::Index::SCALE_X]) *
930 (RS_ROTATION_180 / PI);
931 }
932
Is3DRotation(Drawing::Matrix matrix)933 bool RSUniRenderUtil::Is3DRotation(Drawing::Matrix matrix)
934 {
935 Drawing::Matrix::Buffer value;
936 matrix.GetAll(value);
937 // ScaleX and ScaleY must have different sign
938 if (!(std::signbit(value[Drawing::Matrix::Index::SCALE_X]) ^
939 std::signbit(value[Drawing::Matrix::Index::SCALE_Y]))) {
940 return false;
941 }
942
943 int rotateX = static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::PERSP_1],
944 value[Drawing::Matrix::Index::SCALE_Y]) * (180 / PI)));
945 int rotateY = static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::PERSP_0],
946 value[Drawing::Matrix::Index::SCALE_X]) * (180 / PI)));
947 return (rotateX != 0) || (rotateY != 0);
948 }
949
IsNodeAssignSubThread(std::shared_ptr<RSSurfaceRenderNode> node,bool isDisplayRotation)950 bool RSUniRenderUtil::IsNodeAssignSubThread(std::shared_ptr<RSSurfaceRenderNode> node, bool isDisplayRotation)
951 {
952 if (node == nullptr) {
953 return false;
954 }
955 auto deviceType = RSMainThread::Instance()->GetDeviceType();
956 bool isNeedAssignToSubThread = false;
957 if (deviceType != DeviceType::PC && node->IsLeashWindow()) {
958 isNeedAssignToSubThread = (node->IsScale() || node->IsScaleInPreFrame()
959 || ROSEN_EQ(node->GetGlobalAlpha(), 0.0f) || node->GetForceUIFirst()) && !node->HasFilter();
960 RS_TRACE_NAME_FMT("Assign info: name[%s] id[%" PRIu64"]"
961 " status:%d filter:%d isScale:%d isScalePreFrame:%d forceUIFirst:%d isNeedAssign:%d",
962 node->GetName().c_str(), node->GetId(), node->GetCacheSurfaceProcessedStatus(), node->HasFilter(),
963 node->IsScale(), node->IsScaleInPreFrame(), node->GetForceUIFirst(), isNeedAssignToSubThread);
964 }
965 std::string surfaceName = node->GetName();
966 bool needFilterSCB = node->GetSurfaceWindowType() == SurfaceWindowType::SYSTEM_SCB_WINDOW;
967 RS_LOGI("RSUniRenderUtil::IsNodeAssignSubThread %s", surfaceName.c_str());
968
969 if (needFilterSCB || node->IsSelfDrawingType()) {
970 return false;
971 }
972 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) { // node exceed one vsync
973 return true;
974 }
975 if (deviceType != DeviceType::PC) {
976 return isNeedAssignToSubThread;
977 } else { // PC or TABLET
978 if ((node->IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
979 node->IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId())) &&
980 node->GetHasSharedTransitionNode()) {
981 return false;
982 }
983 return node->QuerySubAssignable(isDisplayRotation);
984 }
985 }
986
AssignWindowNodes(const std::shared_ptr<RSDisplayRenderNode> & displayNode,std::list<std::shared_ptr<RSSurfaceRenderNode>> & mainThreadNodes,std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)987 void RSUniRenderUtil::AssignWindowNodes(const std::shared_ptr<RSDisplayRenderNode>& displayNode,
988 std::list<std::shared_ptr<RSSurfaceRenderNode>>& mainThreadNodes,
989 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
990 {
991 if (displayNode == nullptr) {
992 ROSEN_LOGE("RSUniRenderUtil::AssignWindowNodes display node is null");
993 return;
994 }
995 bool isRotation = displayNode->IsRotationChanged();
996 std::vector<RSBaseRenderNode::SharedPtr> curAllSurfaces;
997 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
998 displayNode->CollectSurface(displayNode, curAllSurfaces, true, true);
999 } else {
1000 curAllSurfaces = *displayNode->GetSortedChildren();
1001 }
1002
1003 for (auto iter = curAllSurfaces.begin(); iter != curAllSurfaces.end(); iter++) {
1004 auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*iter);
1005 if (node == nullptr) {
1006 ROSEN_LOGE("RSUniRenderUtil::AssignWindowNodes nullptr found in sortedChildren, this should not happen");
1007 continue;
1008 }
1009 // release color picker resource when thread-switching between RS and subthread
1010 bool lastIsNeedAssignToSubThread = node->GetLastIsNeedAssignToSubThread();
1011 bool isNodeAssignSubThread = IsNodeAssignSubThread(node, isRotation);
1012 if (isNodeAssignSubThread != lastIsNeedAssignToSubThread) {
1013 auto renderNode = RSBaseRenderNode::ReinterpretCast<RSRenderNode>(node);
1014 node->SetLastIsNeedAssignToSubThread(isNodeAssignSubThread);
1015 }
1016 if (isNodeAssignSubThread) {
1017 AssignSubThreadNode(subThreadNodes, node);
1018 } else {
1019 AssignMainThreadNode(mainThreadNodes, node);
1020 }
1021 }
1022 SortSubThreadNodes(subThreadNodes);
1023 }
1024
AssignMainThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>> & mainThreadNodes,const std::shared_ptr<RSSurfaceRenderNode> & node)1025 void RSUniRenderUtil::AssignMainThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>>& mainThreadNodes,
1026 const std::shared_ptr<RSSurfaceRenderNode>& node)
1027 {
1028 if (node == nullptr) {
1029 ROSEN_LOGW("RSUniRenderUtil::AssignMainThreadNode node is nullptr");
1030 return;
1031 }
1032 mainThreadNodes.emplace_back(node);
1033 bool changeThread = !node->IsMainThreadNode();
1034 node->SetIsMainThreadNode(true);
1035 node->SetNeedSubmitSubThread(false);
1036 node->SetCacheType(CacheType::NONE);
1037 HandleHardwareNode(node);
1038 if (changeThread) {
1039 RS_LOGD("RSUniRenderUtil::AssignMainThreadNode clear cache surface:[%{public}s, %{public}" PRIu64 "]",
1040 node->GetName().c_str(), node->GetId());
1041 ClearCacheSurface(*node, UNI_MAIN_THREAD_INDEX);
1042 node->SetIsMainThreadNode(true);
1043 node->SetTextureValidFlag(false);
1044 }
1045
1046 if (RSMainThread::Instance()->GetDeviceType() == DeviceType::PC) {
1047 RS_TRACE_NAME_FMT("AssignMainThread: name: %s, id: %" PRIu64", [HasTransparentSurface: %d, "
1048 "ChildHasVisibleFilter: %d, HasFilter: %d, QueryIfAllHwcChildrenForceDisabledByFilter: %d]",
1049 node->GetName().c_str(), node->GetId(), node->GetHasTransparentSurface(),
1050 node->ChildHasVisibleFilter(), node->HasFilter(),
1051 node->QueryIfAllHwcChildrenForceDisabledByFilter());
1052 }
1053 }
1054
AssignSubThreadNode(std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes,const std::shared_ptr<RSSurfaceRenderNode> & node)1055 void RSUniRenderUtil::AssignSubThreadNode(
1056 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes, const std::shared_ptr<RSSurfaceRenderNode>& node)
1057 {
1058 if (node == nullptr) {
1059 ROSEN_LOGW("RSUniRenderUtil::AssignSubThreadNode node is nullptr");
1060 return;
1061 }
1062 node->SetCacheType(CacheType::CONTENT);
1063 node->SetIsMainThreadNode(false);
1064 auto deviceType = RSMainThread::Instance()->GetDeviceType();
1065 bool dirty = node->GetNeedDrawFocusChange()
1066 || (!node->IsCurFrameStatic(deviceType) && !node->IsVisibleDirtyEmpty(deviceType));
1067 // skip complete static window, DO NOT assign it to subthread.
1068 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DONE &&
1069 node->HasCachedTexture() && node->IsUIFirstSelfDrawCheck() && !dirty) {
1070 node->SetNeedSubmitSubThread(false);
1071 RS_OPTIONAL_TRACE_NAME_FMT("subThreadNodes : static skip %s", node->GetName().c_str());
1072 } else {
1073 node->SetNeedSubmitSubThread(true);
1074 node->SetNeedDrawFocusChange(false);
1075 node->UpdateCacheSurfaceDirtyManager(2); // 2 means buffer age
1076 }
1077 node->SetLastFrameChildrenCnt(node->GetChildren()->size());
1078 subThreadNodes.emplace_back(node);
1079 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1080 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DONE &&
1081 node->IsCacheSurfaceValid() && node->GetCacheSurfaceNeedUpdated()) {
1082 node->UpdateCompletedCacheSurface();
1083 if (node->IsAppWindow() &&
1084 !RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node->GetParent().lock())) {
1085 node->GetDirtyManager()->MergeDirtyRect(node->GetOldDirty());
1086 } else {
1087 for (auto& child : *node->GetSortedChildren()) {
1088 auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1089 if (surfaceNode && surfaceNode->IsAppWindow()) {
1090 surfaceNode->GetDirtyManager()->MergeDirtyRect(surfaceNode->GetOldDirty());
1091 break;
1092 }
1093 }
1094 }
1095 node->SetCacheSurfaceNeedUpdated(false);
1096 }
1097 #endif
1098 bool isFocus = node->IsFocusedNode(RSMainThread::Instance()->GetFocusNodeId()) ||
1099 (node->IsFocusedNode(RSMainThread::Instance()->GetFocusLeashWindowId()));
1100 if ((deviceType == DeviceType::PC || deviceType == DeviceType::TABLET) && isFocus) {
1101 node->SetPriority(NodePriorityType::SUB_FOCUSNODE_PRIORITY); // for resolving response latency
1102 return;
1103 }
1104 if (node->HasCachedTexture()) {
1105 node->SetPriority(NodePriorityType::SUB_LOW_PRIORITY);
1106 } else {
1107 node->SetPriority(NodePriorityType::SUB_HIGH_PRIORITY);
1108 }
1109 }
1110
SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)1111 void RSUniRenderUtil::SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
1112 {
1113 // sort subThreadNodes by priority and z-order
1114 subThreadNodes.sort([](const auto& first, const auto& second) -> bool {
1115 auto node1 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(first);
1116 auto node2 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(second);
1117 if (node1 == nullptr || node2 == nullptr) {
1118 ROSEN_LOGE(
1119 "RSUniRenderUtil::SortSubThreadNodes sort nullptr found in subThreadNodes, this should not happen");
1120 return false;
1121 }
1122 if (node1->GetPriority() == node2->GetPriority()) {
1123 return node2->GetRenderProperties().GetPositionZ() < node1->GetRenderProperties().GetPositionZ();
1124 } else {
1125 return node1->GetPriority() < node2->GetPriority();
1126 }
1127 });
1128 }
1129
CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & oldSubThreadNodes,std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)1130 void RSUniRenderUtil::CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& oldSubThreadNodes,
1131 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
1132 {
1133 std::unordered_set<std::shared_ptr<RSSurfaceRenderNode>> nodes(subThreadNodes.begin(), subThreadNodes.end());
1134 for (auto node : oldSubThreadNodes) {
1135 if (nodes.count(node) > 0) {
1136 continue;
1137 }
1138 // The node being processed by sub thread may have been removed.
1139 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
1140 subThreadNodes.emplace_back(node);
1141 }
1142 }
1143 oldSubThreadNodes.clear();
1144 oldSubThreadNodes = subThreadNodes;
1145 }
1146
HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode> & node)1147 void RSUniRenderUtil::HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode>& node)
1148 {
1149 if (node == nullptr || !node->HasHardwareNode()) {
1150 return;
1151 }
1152 auto appWindow = node;
1153 if (node->IsLeashWindow()) {
1154 for (auto& child : *node->GetSortedChildren()) {
1155 auto surfaceNodePtr = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1156 if (surfaceNodePtr && surfaceNodePtr->IsAppWindow()) {
1157 appWindow = surfaceNodePtr;
1158 break;
1159 }
1160 }
1161 }
1162 auto hardwareEnabledNodes = appWindow->GetChildHardwareEnabledNodes();
1163 for (auto& hardwareEnabledNode : hardwareEnabledNodes) {
1164 auto hardwareEnabledNodePtr = hardwareEnabledNode.lock();
1165 if (hardwareEnabledNodePtr) {
1166 hardwareEnabledNodePtr->SetHardwareDisabledByCache(false);
1167 }
1168 }
1169 }
1170
ClearSurfaceIfNeed(const RSRenderNodeMap & map,const std::shared_ptr<RSDisplayRenderNode> & displayNode,std::set<std::shared_ptr<RSBaseRenderNode>> & oldChildren,DeviceType deviceType)1171 void RSUniRenderUtil::ClearSurfaceIfNeed(const RSRenderNodeMap& map,
1172 const std::shared_ptr<RSDisplayRenderNode>& displayNode,
1173 std::set<std::shared_ptr<RSBaseRenderNode>>& oldChildren,
1174 DeviceType deviceType)
1175 {
1176 if (displayNode == nullptr) {
1177 return;
1178 }
1179 std::vector<RSBaseRenderNode::SharedPtr> curAllSurfaces;
1180 if (Rosen::SceneBoardJudgement::IsSceneBoardEnabled()) {
1181 curAllSurfaces = displayNode->GetCurAllSurfaces(true);
1182 } else {
1183 curAllSurfaces = *displayNode->GetSortedChildren();
1184 }
1185 std::set<std::shared_ptr<RSBaseRenderNode>> tmpSet(curAllSurfaces.begin(), curAllSurfaces.end());
1186 for (auto& child : oldChildren) {
1187 auto surface = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1188 if (!surface) {
1189 continue;
1190 }
1191 if (tmpSet.count(surface) == 0) {
1192 if (surface->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
1193 tmpSet.emplace(surface);
1194 continue;
1195 }
1196 if (map.GetRenderNode(surface->GetId()) != nullptr) {
1197 RS_LOGD("RSUniRenderUtil::ClearSurfaceIfNeed clear cache surface:[%{public}s, %{public}" PRIu64 "]",
1198 surface->GetName().c_str(), surface->GetId());
1199 if (deviceType == DeviceType::PHONE) {
1200 ClearCacheSurface(*surface, UNI_MAIN_THREAD_INDEX);
1201 surface->SetIsMainThreadNode(true);
1202 surface->SetTextureValidFlag(false);
1203 } else {
1204 if (RSMainThread::Instance()->IsPCThreeFingerScenesListScene()) {
1205 ClearCacheSurface(*surface, UNI_MAIN_THREAD_INDEX, false);
1206 } else {
1207 ClearCacheSurface(*surface, UNI_MAIN_THREAD_INDEX);
1208 }
1209 }
1210 }
1211 }
1212 }
1213 oldChildren.swap(tmpSet);
1214 }
1215
ClearCacheSurface(RSRenderNode & node,uint32_t threadIndex,bool isClearCompletedCacheSurface)1216 void RSUniRenderUtil::ClearCacheSurface(RSRenderNode& node, uint32_t threadIndex, bool isClearCompletedCacheSurface)
1217 {
1218 RS_LOGD("ClearCacheSurface node: [%{public}" PRIu64 "]", node.GetId());
1219 uint32_t cacheSurfaceThreadIndex = node.GetCacheSurfaceThreadIndex();
1220 uint32_t completedSurfaceThreadIndex = node.GetCompletedSurfaceThreadIndex();
1221 if (cacheSurfaceThreadIndex == threadIndex && completedSurfaceThreadIndex == threadIndex) {
1222 node.ClearCacheSurface(isClearCompletedCacheSurface);
1223 return;
1224 }
1225 std::shared_ptr<Drawing::Surface> completedCacheSurface = isClearCompletedCacheSurface ?
1226 node.GetCompletedCacheSurface(threadIndex, false, true) : nullptr;
1227 ClearNodeCacheSurface(node.GetCacheSurface(threadIndex, false, true),
1228 std::move(completedCacheSurface), cacheSurfaceThreadIndex, completedSurfaceThreadIndex);
1229 node.ClearCacheSurface(isClearCompletedCacheSurface);
1230 }
1231
ClearNodeCacheSurface(std::shared_ptr<Drawing::Surface> && cacheSurface,std::shared_ptr<Drawing::Surface> && cacheCompletedSurface,uint32_t cacheSurfaceThreadIndex,uint32_t completedSurfaceThreadIndex)1232 void RSUniRenderUtil::ClearNodeCacheSurface(std::shared_ptr<Drawing::Surface>&& cacheSurface,
1233 std::shared_ptr<Drawing::Surface>&& cacheCompletedSurface,
1234 uint32_t cacheSurfaceThreadIndex, uint32_t completedSurfaceThreadIndex)
1235 {
1236 PostReleaseSurfaceTask(std::move(cacheSurface), cacheSurfaceThreadIndex);
1237 PostReleaseSurfaceTask(std::move(cacheCompletedSurface), completedSurfaceThreadIndex);
1238 }
1239
PostReleaseSurfaceTask(std::shared_ptr<Drawing::Surface> && surface,uint32_t threadIndex)1240 void RSUniRenderUtil::PostReleaseSurfaceTask(std::shared_ptr<Drawing::Surface>&& surface, uint32_t threadIndex)
1241 {
1242 if (surface == nullptr) {
1243 return;
1244 }
1245
1246 if (threadIndex == UNI_MAIN_THREAD_INDEX || threadIndex == UNI_RENDER_THREAD_INDEX) {
1247 if (RSUniRenderJudgement::IsUniRender()) {
1248 auto instance = &(RSUniRenderThread::Instance());
1249 instance->AddToReleaseQueue(std::move(surface));
1250 instance->PostTask(([instance] () { instance->ReleaseSurface(); }),
1251 RELEASE_SURFACE_TASK, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1252 } else {
1253 auto instance = RSMainThread::Instance();
1254 instance->AddToReleaseQueue(std::move(surface));
1255 instance->PostTask(([instance] () { instance->ReleaseSurface(); }),
1256 RELEASE_SURFACE_TASK, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1257 }
1258 } else {
1259 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1260 auto instance = RSSubThreadManager::Instance();
1261 instance->AddToReleaseQueue(std::move(surface), threadIndex);
1262 instance->ReleaseSurface(threadIndex);
1263 #endif
1264 }
1265 }
1266
DrawRectForDfx(RSPaintFilterCanvas & canvas,const RectI & rect,Drawing::Color color,float alpha,const std::string & extraInfo)1267 void RSUniRenderUtil::DrawRectForDfx(RSPaintFilterCanvas& canvas, const RectI& rect, Drawing::Color color,
1268 float alpha, const std::string& extraInfo)
1269 {
1270 if (rect.width_ <= 0 || rect.height_ <= 0) {
1271 RS_LOGD("DrawRectForDfx rect is invalid.");
1272 return;
1273 }
1274 RS_LOGD("DrawRectForDfx current rect = %{public}s", rect.ToString().c_str());
1275 auto dstRect = Drawing::Rect(rect.left_, rect.top_,
1276 rect.left_ + rect.width_, rect.top_ + rect.height_);
1277
1278 std::string position = rect.ToString() + extraInfo;
1279
1280 const int defaultTextOffsetX = 6; // text position is 6 pixelSize right side of the Rect
1281 const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the Rect
1282 Drawing::Brush rectBrush;
1283 std::shared_ptr<Drawing::Typeface> typeFace = nullptr;
1284
1285 // font size: 24
1286 std::shared_ptr<Drawing::TextBlob> textBlob =
1287 Drawing::TextBlob::MakeFromString(position.c_str(), Drawing::Font(typeFace, 24.0f, 1.0f, 0.0f));
1288
1289 rectBrush.SetColor(color);
1290 rectBrush.SetAntiAlias(true);
1291 rectBrush.SetAlphaF(alpha);
1292 canvas.AttachBrush(rectBrush);
1293 canvas.DrawRect(dstRect);
1294 canvas.DetachBrush();
1295 canvas.AttachBrush(Drawing::Brush());
1296 canvas.DrawTextBlob(textBlob.get(), rect.left_ + defaultTextOffsetX, rect.top_ + defaultTextOffsetY);
1297 canvas.DetachBrush();
1298 }
1299
1300 #ifdef RS_ENABLE_VK
FindMemoryType(uint32_t typeFilter,VkMemoryPropertyFlags properties)1301 uint32_t RSUniRenderUtil::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
1302 {
1303 if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
1304 OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
1305 return UINT32_MAX;
1306 }
1307 auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton().GetRsVulkanInterface();
1308 VkPhysicalDevice physicalDevice = vkContext.GetPhysicalDevice();
1309
1310 VkPhysicalDeviceMemoryProperties memProperties;
1311 vkContext.vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
1312
1313 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
1314 if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
1315 return i;
1316 }
1317 }
1318
1319 return UINT32_MAX;
1320 }
1321
SetVkImageInfo(std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo,const VkImageCreateInfo & imageInfo)1322 void RSUniRenderUtil::SetVkImageInfo(std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo,
1323 const VkImageCreateInfo& imageInfo)
1324 {
1325 if (vkImageInfo == nullptr) {
1326 return;
1327 }
1328 vkImageInfo->imageTiling = imageInfo.tiling;
1329 vkImageInfo->imageLayout = imageInfo.initialLayout;
1330 vkImageInfo->format = imageInfo.format;
1331 vkImageInfo->imageUsageFlags = imageInfo.usage;
1332 vkImageInfo->levelCount = imageInfo.mipLevels;
1333 vkImageInfo->currentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
1334 vkImageInfo->ycbcrConversionInfo = {};
1335 vkImageInfo->sharingMode = imageInfo.sharingMode;
1336 }
1337
MakeBackendTexture(uint32_t width,uint32_t height,VkFormat format)1338 Drawing::BackendTexture RSUniRenderUtil::MakeBackendTexture(uint32_t width, uint32_t height, VkFormat format)
1339 {
1340 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
1341 VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1342 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1343 VkImageCreateInfo imageInfo {
1344 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1345 .pNext = nullptr,
1346 .flags = 0,
1347 .imageType = VK_IMAGE_TYPE_2D,
1348 .format = format,
1349 .extent = {width, height, 1},
1350 .mipLevels = 1,
1351 .arrayLayers = 1,
1352 .samples = VK_SAMPLE_COUNT_1_BIT,
1353 .tiling = tiling,
1354 .usage = usage,
1355 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1356 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
1357 };
1358
1359 auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton().GetRsVulkanInterface();
1360 VkDevice device = vkContext.GetDevice();
1361 VkImage image = VK_NULL_HANDLE;
1362 VkDeviceMemory memory = VK_NULL_HANDLE;
1363
1364 if (width * height > VKIMAGE_LIMIT_SIZE) {
1365 ROSEN_LOGE(
1366 "RSUniRenderUtil::MakeBackendTexture failed, image is too large, width:%{public}u, height::%{public}u",
1367 width, height);
1368 return {};
1369 }
1370
1371 if (vkContext.vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
1372 return {};
1373 }
1374
1375 VkMemoryRequirements memRequirements;
1376 vkContext.vkGetImageMemoryRequirements(device, image, &memRequirements);
1377
1378 VkMemoryAllocateInfo allocInfo{};
1379 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1380 allocInfo.allocationSize = memRequirements.size;
1381 allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1382 if (allocInfo.memoryTypeIndex == UINT32_MAX) {
1383 return {};
1384 }
1385
1386 if (vkContext.vkAllocateMemory(device, &allocInfo, nullptr, &memory) != VK_SUCCESS) {
1387 return {};
1388 }
1389
1390 vkContext.vkBindImageMemory(device, image, memory, 0);
1391
1392 OHOS::Rosen::Drawing::BackendTexture backendTexture(true);
1393 OHOS::Rosen::Drawing::TextureInfo textureInfo;
1394 textureInfo.SetWidth(width);
1395 textureInfo.SetHeight(height);
1396
1397 std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo =
1398 std::make_shared<OHOS::Rosen::Drawing::VKTextureInfo>();
1399 vkImageInfo->vkImage = image;
1400 vkImageInfo->vkAlloc.memory = memory;
1401 vkImageInfo->vkAlloc.size = memRequirements.size;
1402
1403 SetVkImageInfo(vkImageInfo, imageInfo);
1404 textureInfo.SetVKTextureInfo(vkImageInfo);
1405 backendTexture.SetTextureInfo(textureInfo);
1406 return backendTexture;
1407 }
1408 #endif
1409
GetRotateTransformForRotationFixed(RSSurfaceRenderNode & node,sptr<IConsumerSurface> consumer)1410 GraphicTransformType RSUniRenderUtil::GetRotateTransformForRotationFixed(RSSurfaceRenderNode& node,
1411 sptr<IConsumerSurface> consumer)
1412 {
1413 auto transformType = RSBaseRenderUtil::GetRotateTransform(RSBaseRenderUtil::GetSurfaceBufferTransformType(
1414 node.GetRSSurfaceHandler()->GetConsumer(), node.GetRSSurfaceHandler()->GetBuffer()));
1415 int extraRotation = 0;
1416 int degree = static_cast<int>(round(node.GetAbsRotation()));
1417 auto surfaceParams = node.GetStagingRenderParams() == nullptr
1418 ? nullptr
1419 : static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
1420 int32_t rotationDegree = RSBaseRenderUtil::GetScreenRotationOffset(surfaceParams);
1421 extraRotation = (degree - rotationDegree) % ROUND_ANGLE;
1422 transformType = static_cast<GraphicTransformType>(
1423 (transformType + extraRotation / RS_ROTATION_90 + SCREEN_ROTATION_NUM) % SCREEN_ROTATION_NUM);
1424 return transformType;
1425 }
1426
SrcRectRotateTransform(RSSurfaceRenderNode & node,GraphicTransformType transformType)1427 RectI RSUniRenderUtil::SrcRectRotateTransform(RSSurfaceRenderNode& node, GraphicTransformType transformType)
1428 {
1429 RectI srcRect = node.GetSrcRect();
1430 int left = srcRect.GetLeft();
1431 int top = srcRect.GetTop();
1432 int width = srcRect.GetWidth();
1433 int height = srcRect.GetHeight();
1434 int boundsWidth = static_cast<int>(node.GetRenderProperties().GetBoundsWidth());
1435 int boundsHeight = static_cast<int>(node.GetRenderProperties().GetBoundsHeight());
1436 // Left > 0 means move xComponent to the left outside of the screen
1437 // Top > 0 means move xComponent to the top outside of the screen
1438 // The left and top should recalculate when transformType is not GRAPHIC_ROTATE_NONEq
1439 // The width and height should exchange when transformType is GRAPHIC_ROTATE_270 and GRAPHIC_ROTATE_90
1440 switch (transformType) {
1441 case GraphicTransformType::GRAPHIC_ROTATE_270: {
1442 left = std::max(top, 0);
1443 top = std::max(boundsWidth - width - srcRect.GetLeft(), 0);
1444 srcRect = RectI {left, top, height, width};
1445 break;
1446 }
1447 case GraphicTransformType::GRAPHIC_ROTATE_180: {
1448 left = std::max(boundsWidth - width - left, 0);
1449 top = std::max(boundsHeight - height - top, 0);
1450 srcRect = RectI {left, top, width, height};
1451 break;
1452 }
1453 case GraphicTransformType::GRAPHIC_ROTATE_90: {
1454 left = std::max(boundsHeight - height - top, 0);
1455 top = std::max(srcRect.GetLeft(), 0);
1456 srcRect = RectI {left, top, height, width};
1457 break;
1458 }
1459 default: {
1460 break;
1461 }
1462 }
1463 return srcRect;
1464 }
1465
UpdateRealSrcRect(RSSurfaceRenderNode & node,const RectI & absRect)1466 void RSUniRenderUtil::UpdateRealSrcRect(RSSurfaceRenderNode& node, const RectI& absRect)
1467 {
1468 auto surfaceHandler = node.GetRSSurfaceHandler();
1469 auto consumer = surfaceHandler->GetConsumer();
1470 auto buffer = surfaceHandler->GetBuffer();
1471 if (!consumer || !buffer) {
1472 return;
1473 }
1474 auto transformType = GraphicTransformType::GRAPHIC_ROTATE_NONE;
1475 if (node.GetFixRotationByUser()) {
1476 transformType = RSUniRenderUtil::GetRotateTransformForRotationFixed(node, consumer);
1477 } else {
1478 transformType = RSBaseRenderUtil::GetRotateTransform(consumer->GetTransform());
1479 }
1480 auto srcRect = SrcRectRotateTransform(node, transformType);
1481 const auto& property = node.GetRenderProperties();
1482 const auto bufferWidth = buffer->GetSurfaceBufferWidth();
1483 const auto bufferHeight = buffer->GetSurfaceBufferHeight();
1484 auto boundsWidth = property.GetBoundsWidth();
1485 auto boundsHeight = property.GetBoundsHeight();
1486 if (transformType == GraphicTransformType::GRAPHIC_ROTATE_270 ||
1487 transformType == GraphicTransformType::GRAPHIC_ROTATE_90) {
1488 std::swap(boundsWidth, boundsHeight);
1489 }
1490 if ((bufferWidth != boundsWidth || bufferHeight != boundsHeight) &&
1491 node.GetRenderProperties().GetFrameGravity() != Gravity::TOP_LEFT) {
1492 float xScale = (ROSEN_EQ(boundsWidth, 0.0f) ? 1.0f : bufferWidth / boundsWidth);
1493 float yScale = (ROSEN_EQ(boundsHeight, 0.0f) ? 1.0f : bufferHeight / boundsHeight);
1494 // If the scaling mode is SCALING_MODE_SCALE_TO_WINDOW, the scale should use smaller one.
1495 if (buffer->GetSurfaceBufferScalingMode() == ScalingMode::SCALING_MODE_SCALE_CROP) {
1496 float scale = std::min(xScale, yScale);
1497 srcRect.left_ = srcRect.left_ * scale;
1498 srcRect.top_ = srcRect.top_ * scale;
1499 if (ROSEN_EQ(scale, 0.f)) {
1500 node.SetSrcRect(srcRect);
1501 return;
1502 }
1503 srcRect.width_ = (bufferWidth / scale - (boundsWidth - srcRect.width_)) * scale;
1504 srcRect.height_ = (bufferHeight / scale - (boundsHeight - srcRect.height_)) * scale;
1505 } else {
1506 if (absRect == node.GetDstRect()) {
1507 // If the SurfaceRenderNode is completely in the DisplayRenderNode,
1508 // we do not need to crop the buffer.
1509 srcRect.width_ = bufferWidth;
1510 srcRect.height_ = bufferHeight;
1511 } else {
1512 srcRect.left_ = srcRect.left_ * xScale;
1513 srcRect.top_ = srcRect.top_ * yScale;
1514 srcRect.width_ = std::min(static_cast<int32_t>(std::ceil(srcRect.width_ * xScale)), bufferWidth);
1515 srcRect.height_ = std::min(static_cast<int32_t>(std::ceil(srcRect.height_ * yScale)), bufferHeight);
1516 }
1517 }
1518 }
1519 RectI bufferRect(0, 0, bufferWidth, bufferHeight);
1520 RectI newSrcRect = srcRect.IntersectRect(bufferRect);
1521 node.SetSrcRect(newSrcRect);
1522 }
1523
DealWithNodeGravity(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1524 void RSUniRenderUtil::DealWithNodeGravity(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1525 {
1526 auto buffer = node.GetRSSurfaceHandler()->GetBuffer();
1527 if (!buffer) {
1528 return;
1529 }
1530 const auto& property = node.GetRenderProperties();
1531 const float frameWidth = buffer->GetSurfaceBufferWidth();
1532 const float frameHeight = buffer->GetSurfaceBufferHeight();
1533 const float boundsWidth = property.GetBoundsWidth();
1534 const float boundsHeight = property.GetBoundsHeight();
1535 const Gravity frameGravity = property.GetFrameGravity();
1536
1537 CheckForceHardwareAndUpdateDstRect(node);
1538 // we do not need to do additional works for Gravity::RESIZE and if frameSize == boundsSize.
1539 if (frameGravity == Gravity::RESIZE || frameGravity == Gravity::TOP_LEFT ||
1540 (ROSEN_EQ(frameWidth, boundsWidth) && ROSEN_EQ(frameHeight, boundsHeight))) {
1541 return;
1542 }
1543
1544 // get current node's translate matrix and calculate gravity matrix.
1545 auto translateMatrix = Drawing::Matrix();
1546 translateMatrix.Translate(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_X),
1547 std::ceil(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_Y)));
1548 Drawing::Matrix gravityMatrix;
1549 (void)RSPropertiesPainter::GetGravityMatrix(frameGravity,
1550 RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix);
1551 // create a canvas to calculate new dstRect and new srcRect
1552 int32_t screenWidth = screenInfo.phyWidth;
1553 int32_t screenHeight = screenInfo.phyHeight;
1554 const auto screenRotation = screenInfo.rotation;
1555 if (screenRotation == ScreenRotation::ROTATION_90 || screenRotation == ScreenRotation::ROTATION_270) {
1556 std::swap(screenWidth, screenHeight);
1557 }
1558
1559 auto canvas = std::make_unique<Drawing::Canvas>(screenWidth, screenHeight);
1560 canvas->ConcatMatrix(translateMatrix);
1561 canvas->ConcatMatrix(gravityMatrix);
1562 Drawing::Rect clipRect;
1563 gravityMatrix.MapRect(clipRect, Drawing::Rect(0, 0, frameWidth, frameHeight));
1564 canvas->ClipRect(Drawing::Rect(0, 0, clipRect.GetWidth(), clipRect.GetHeight()), Drawing::ClipOp::INTERSECT);
1565 Drawing::RectI newDstRect = canvas->GetDeviceClipBounds();
1566 auto dstRect = node.GetDstRect();
1567 // we make the newDstRect as the intersection of new and old dstRect,
1568 // to deal with the situation that frameSize > boundsSize.
1569 newDstRect.Intersect(Drawing::RectI(
1570 dstRect.left_, dstRect.top_, dstRect.width_ + dstRect.left_, dstRect.height_ + dstRect.top_));
1571 auto localRect = canvas->GetLocalClipBounds();
1572 int left = std::clamp<int>(localRect.GetLeft(), 0, frameWidth);
1573 int top = std::clamp<int>(localRect.GetTop(), 0, frameHeight);
1574 int width = std::clamp<int>(localRect.GetWidth(), 0, frameWidth - left);
1575 int height = std::clamp<int>(localRect.GetHeight(), 0, frameHeight - top);
1576
1577 node.SetDstRect({newDstRect.GetLeft(), newDstRect.GetTop(), newDstRect.GetWidth(), newDstRect.GetHeight()});
1578 node.SetSrcRect({left, top, width, height});
1579 }
1580
CheckForceHardwareAndUpdateDstRect(RSSurfaceRenderNode & node)1581 void RSUniRenderUtil::CheckForceHardwareAndUpdateDstRect(RSSurfaceRenderNode& node)
1582 {
1583 auto surfaceHandler = node.GetRSSurfaceHandler();
1584 if (!surfaceHandler->GetConsumer() || !node.IsInFixedRotation() || !surfaceHandler->GetBuffer()) {
1585 return;
1586 }
1587 node.SetSrcRect(node.GetOriginalSrcRect());
1588 auto dstRect = node.GetDstRect();
1589 auto originalDstRect = node.GetOriginalDstRect();
1590 dstRect.left_ += (dstRect.width_ - originalDstRect.width_) / 2;
1591 dstRect.top_ += (dstRect.height_ - originalDstRect.height_) / 2;
1592 dstRect.width_ = originalDstRect.width_;
1593 dstRect.height_ = originalDstRect.height_;
1594 node.SetDstRect(dstRect);
1595 }
1596
LayerRotate(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1597 void RSUniRenderUtil::LayerRotate(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1598 {
1599 const auto screenWidth = static_cast<int32_t>(screenInfo.width);
1600 const auto screenHeight = static_cast<int32_t>(screenInfo.height);
1601 const auto screenRotation = screenInfo.rotation;
1602 const auto rect = node.GetDstRect();
1603 switch (screenRotation) {
1604 case ScreenRotation::ROTATION_90: {
1605 node.SetDstRect({rect.top_, screenHeight - rect.left_ - rect.width_, rect.height_, rect.width_});
1606 break;
1607 }
1608 case ScreenRotation::ROTATION_180: {
1609 node.SetDstRect({screenWidth - rect.left_ - rect.width_, screenHeight - rect.top_ - rect.height_,
1610 rect.width_, rect.height_});
1611 break;
1612 }
1613 case ScreenRotation::ROTATION_270: {
1614 node.SetDstRect({screenWidth - rect.top_ - rect.height_, rect.left_, rect.height_, rect.width_});
1615 break;
1616 }
1617 default: {
1618 break;
1619 }
1620 }
1621 }
1622
GetLayerTransform(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1623 GraphicTransformType RSUniRenderUtil::GetLayerTransform(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1624 {
1625 auto surfaceHandler = node.GetRSSurfaceHandler();
1626 if (!surfaceHandler) {
1627 return GraphicTransformType::GRAPHIC_ROTATE_NONE;
1628 }
1629 auto consumer = surfaceHandler->GetConsumer();
1630 auto surfaceParams = node.GetStagingRenderParams() == nullptr
1631 ? nullptr
1632 : static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
1633 int32_t rotationDegree = RSBaseRenderUtil::GetScreenRotationOffset(surfaceParams);
1634 int surfaceNodeRotation = 0;
1635 if (node.GetFixRotationByUser()) {
1636 surfaceNodeRotation = -1 * rotationDegree;
1637 } else {
1638 surfaceNodeRotation =
1639 TransferToAntiClockwiseDegrees(static_cast<int>(round(node.GetAbsRotation())) % ROUND_ANGLE);
1640 }
1641 auto transformType = GraphicTransformType::GRAPHIC_ROTATE_NONE;
1642 auto buffer = node.GetRSSurfaceHandler()->GetBuffer();
1643 if (consumer != nullptr && buffer != nullptr) {
1644 if (consumer->GetSurfaceBufferTransformType(buffer, &transformType) != GSERROR_OK) {
1645 RS_LOGE("RSUniRenderUtil::GetLayerTransform GetSurfaceBufferTransformType failed");
1646 }
1647 }
1648 int consumerTransform = RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(transformType));
1649 GraphicTransformType consumerFlip = RSBaseRenderUtil::GetFlipTransform(transformType);
1650 int totalRotation =
1651 (RSBaseRenderUtil::RotateEnumToInt(screenInfo.rotation) + surfaceNodeRotation + consumerTransform + 360) % 360;
1652 GraphicTransformType rotateEnum = RSBaseRenderUtil::RotateEnumToInt(totalRotation, consumerFlip);
1653 return rotateEnum;
1654 }
1655
LayerCrop(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1656 void RSUniRenderUtil::LayerCrop(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1657 {
1658 auto dstRect = node.GetDstRect();
1659 auto srcRect = node.GetSrcRect();
1660 auto originSrcRect = srcRect;
1661
1662 RectI dstRectI(dstRect.left_, dstRect.top_, dstRect.width_, dstRect.height_);
1663 int32_t screenWidth = static_cast<int32_t>(screenInfo.phyWidth);
1664 int32_t screenHeight = static_cast<int32_t>(screenInfo.phyHeight);
1665 RectI screenRectI(0, 0, screenWidth, screenHeight);
1666 RectI resDstRect = dstRectI.IntersectRect(screenRectI);
1667 if (resDstRect == dstRectI) {
1668 return;
1669 }
1670 if (node.IsInFixedRotation()) {
1671 node.SetDstRect(resDstRect);
1672 return;
1673 }
1674 dstRect = {resDstRect.left_, resDstRect.top_, resDstRect.width_, resDstRect.height_};
1675 srcRect.left_ = (resDstRect.IsEmpty() || dstRectI.IsEmpty()) ? 0 : std::ceil((resDstRect.left_ - dstRectI.left_) *
1676 originSrcRect.width_ / dstRectI.width_);
1677 srcRect.top_ = (resDstRect.IsEmpty() || dstRectI.IsEmpty()) ? 0 : std::ceil((resDstRect.top_ - dstRectI.top_) *
1678 originSrcRect.height_ / dstRectI.height_);
1679 srcRect.width_ = dstRectI.IsEmpty() ? 0 : originSrcRect.width_ * resDstRect.width_ / dstRectI.width_;
1680 srcRect.height_ = dstRectI.IsEmpty() ? 0 : originSrcRect.height_ * resDstRect.height_ / dstRectI.height_;
1681 node.SetDstRect(dstRect);
1682 node.SetSrcRect(srcRect);
1683 }
1684
DealWithScalingMode(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1685 void RSUniRenderUtil::DealWithScalingMode(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1686 {
1687 const auto& buffer = node.GetRSSurfaceHandler()->GetBuffer();
1688 const auto& surface = node.GetRSSurfaceHandler()->GetConsumer();
1689 if (surface == nullptr || buffer == nullptr) {
1690 RS_LOGE("surface or buffer is nullptr");
1691 return;
1692 }
1693
1694 ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
1695 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
1696 RSUniRenderUtil::LayerScaleDown(node);
1697 } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
1698 // For scale fit, when aspect ratios of buffer and bounds of node are "dramatically" different,
1699 // moving node out of screen causes unexpected dstRect cropping problem. Disable HWC if this happens
1700 float bufferAspectRatio = buffer->GetSurfaceBufferHeight() == 0 ? 0.f :
1701 static_cast<float>(buffer->GetSurfaceBufferWidth()) / static_cast<float>(buffer->GetSurfaceBufferHeight());
1702 float boundsAspectRatio = ROSEN_EQ(node.GetRenderProperties().GetBoundsHeight(), 0.f, 1e-6f) ? 0.f :
1703 node.GetRenderProperties().GetBoundsWidth() / node.GetRenderProperties().GetBoundsHeight();
1704 // Aspect ratios should be "dramatically" different
1705 if (!ROSEN_EQ(bufferAspectRatio, boundsAspectRatio, 5e-3f)) {
1706 Drawing::Rect bounds = Drawing::Rect(
1707 0, 0, node.GetRenderProperties().GetBoundsWidth(), node.GetRenderProperties().GetBoundsHeight());
1708 Drawing::Rect absBoundsRect;
1709 node.GetTotalMatrix().MapRect(absBoundsRect, bounds);
1710 // Detect if node is out of screen by testing bounds
1711 if (absBoundsRect.GetLeft() < 0 || absBoundsRect.GetTop() < 0 ||
1712 absBoundsRect.GetLeft() + absBoundsRect.GetWidth() > screenInfo.width ||
1713 absBoundsRect.GetTop() + absBoundsRect.GetHeight() > screenInfo.height) {
1714 node.SetHardwareForcedDisabledState(true);
1715 RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: name %s id %llu disabled by scale fit bounds out of screen. "
1716 "bounds: %s, screenWidth: %u, screenHeight: %u bufferAspectRatio: %f, boundsAspectRatio: %f",
1717 node.GetName().c_str(), node.GetId(), absBoundsRect.ToString().c_str(), screenInfo.width,
1718 screenInfo.height, bufferAspectRatio, boundsAspectRatio);
1719 return;
1720 }
1721 }
1722
1723 int degree = RSUniRenderUtil::GetRotationDegreeFromMatrix(node.GetTotalMatrix());
1724 if (degree % RS_ROTATION_90 == 0) {
1725 RSUniRenderUtil::LayerScaleFit(node);
1726 }
1727 }
1728 }
1729
LayerScaleDown(RSSurfaceRenderNode & node)1730 void RSUniRenderUtil::LayerScaleDown(RSSurfaceRenderNode& node)
1731 {
1732 const auto& buffer = node.GetRSSurfaceHandler()->GetBuffer();
1733 const auto& surface = node.GetRSSurfaceHandler()->GetConsumer();
1734 if (buffer == nullptr || surface == nullptr) {
1735 return;
1736 }
1737 constexpr uint32_t FLAT_ANGLE = 180;
1738 auto dstRect = node.GetDstRect();
1739 auto srcRect = node.GetSrcRect();
1740
1741 uint32_t newWidth = static_cast<uint32_t>(srcRect.width_);
1742 uint32_t newHeight = static_cast<uint32_t>(srcRect.height_);
1743 uint32_t dstWidth = static_cast<uint32_t>(dstRect.width_);
1744 uint32_t dstHeight = static_cast<uint32_t>(dstRect.height_);
1745 if (newWidth == 0 || newHeight == 0 || dstWidth == 0 || dstHeight == 0) {
1746 return;
1747 }
1748
1749 // If surfaceRotation is not a multiple of 180, need to change the correspondence between width & height.
1750 // ScreenRotation has been processed in SetLayerSize, and do not change the width & height correspondence.
1751 int surfaceRotation = RSUniRenderUtil::GetRotationFromMatrix(node.GetTotalMatrix()) +
1752 RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(
1753 RSBaseRenderUtil::GetSurfaceBufferTransformType(surface, buffer)));
1754 if (surfaceRotation % FLAT_ANGLE != 0) {
1755 std::swap(dstWidth, dstHeight);
1756 }
1757
1758 uint32_t newWidthDstHeight = newWidth * dstHeight;
1759 uint32_t newHeightDstWidth = newHeight * dstWidth;
1760
1761 if (newWidthDstHeight > newHeightDstWidth) {
1762 // too wide
1763 newWidth = dstWidth * newHeight / dstHeight;
1764 } else if (newWidthDstHeight < newHeightDstWidth) {
1765 // too tall
1766 newHeight = dstHeight * newWidth / dstWidth;
1767 } else {
1768 return;
1769 }
1770
1771 uint32_t currentWidth = static_cast<uint32_t>(srcRect.width_);
1772 uint32_t currentHeight = static_cast<uint32_t>(srcRect.height_);
1773
1774 if (newWidth < currentWidth) {
1775 // the crop is too wide
1776 uint32_t dw = currentWidth - newWidth;
1777 auto halfdw = dw / 2;
1778 srcRect.left_ += static_cast<int32_t>(halfdw);
1779 srcRect.width_ = static_cast<int32_t>(newWidth);
1780 } else {
1781 // thr crop is too tall
1782 uint32_t dh = currentHeight - newHeight;
1783 auto halfdh = dh / 2;
1784 srcRect.top_ += static_cast<int32_t>(halfdh);
1785 srcRect.height_ = static_cast<int32_t>(newHeight);
1786 }
1787 node.SetSrcRect(srcRect);
1788 }
1789
LayerScaleFit(RSSurfaceRenderNode & node)1790 void RSUniRenderUtil::LayerScaleFit(RSSurfaceRenderNode& node)
1791 {
1792 const auto& buffer = node.GetRSSurfaceHandler()->GetBuffer();
1793 const auto& surface = node.GetRSSurfaceHandler()->GetConsumer();
1794 if (buffer == nullptr || surface == nullptr) {
1795 return;
1796 }
1797 constexpr uint32_t FLAT_ANGLE = 180;
1798 auto dstRect = node.GetDstRect();
1799 auto srcRect = node.GetSrcRect();
1800
1801 // If surfaceRotation is not a multiple of 180, need to change the correspondence between width & height.
1802 // ScreenRotation has been processed in SetLayerSize, and do not change the width & height correspondence.
1803 int surfaceRotation = RSUniRenderUtil::GetRotationFromMatrix(node.GetTotalMatrix()) +
1804 RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(
1805 RSBaseRenderUtil::GetSurfaceBufferTransformType(surface, buffer)));
1806 if (surfaceRotation % FLAT_ANGLE != 0) {
1807 std::swap(srcRect.width_, srcRect.height_);
1808 }
1809
1810 uint32_t newWidth = static_cast<uint32_t>(srcRect.width_);
1811 uint32_t newHeight = static_cast<uint32_t>(srcRect.height_);
1812 uint32_t dstWidth = static_cast<uint32_t>(dstRect.width_);
1813 uint32_t dstHeight = static_cast<uint32_t>(dstRect.height_);
1814
1815 if (newWidth == 0 || newHeight == 0 || dstWidth == 0 || dstHeight == 0) {
1816 return;
1817 }
1818
1819 uint32_t newWidthDstHeight = newWidth * dstHeight;
1820 uint32_t newHeightDstWidth = newHeight * dstWidth;
1821
1822 if (newWidthDstHeight > newHeightDstWidth) {
1823 newHeight = newHeight * dstWidth / newWidth;
1824 newWidth = dstWidth;
1825 } else if (newWidthDstHeight < newHeightDstWidth) {
1826 newWidth = newWidth * dstHeight / newHeight;
1827 newHeight = dstHeight;
1828 } else {
1829 newHeight = dstHeight;
1830 newWidth = dstWidth;
1831 }
1832
1833 if (newWidth < dstWidth) {
1834 uint32_t dw = dstWidth - newWidth;
1835 auto halfdw = dw / 2;
1836 dstRect.left_ += static_cast<int32_t>(halfdw);
1837 } else if (newHeight < dstHeight) {
1838 uint32_t dh = dstHeight - newHeight;
1839 auto halfdh = dh / 2;
1840 dstRect.top_ += static_cast<int32_t>(halfdh);
1841 }
1842 dstRect.height_ = static_cast<int32_t>(newHeight);
1843 dstRect.width_ = static_cast<int32_t>(newWidth);
1844 node.SetDstRect(dstRect);
1845
1846 RS_LOGD("RsDebug RSUniRenderUtil::LayerScaleFit layer has been scalefit dst[%{public}d %{public}d"
1847 " %{public}d %{public}d] src[%{public}d %{public}d %{public}d %{public}d]",
1848 dstRect.left_, dstRect.top_, dstRect.width_, dstRect.height_, srcRect.left_,
1849 srcRect.top_, srcRect.width_, srcRect.height_);
1850 }
1851
OptimizedFlushAndSubmit(std::shared_ptr<Drawing::Surface> & surface,Drawing::GPUContext * const grContext,bool optFenceWait)1852 void RSUniRenderUtil::OptimizedFlushAndSubmit(std::shared_ptr<Drawing::Surface>& surface,
1853 Drawing::GPUContext* const grContext, bool optFenceWait)
1854 {
1855 if (!surface || !grContext) {
1856 RS_LOGE("RSUniRenderUtil::OptimizedFlushAndSubmit cacheSurface or grContext are nullptr");
1857 return;
1858 }
1859 RS_TRACE_NAME_FMT("Render surface flush and submit");
1860 RS_LOGD("RSUniRenderUtil::optimized flush and submit GpuApiType:%{public}d",
1861 RSSystemProperties::GetGpuApiType());
1862 #ifdef RS_ENABLE_VK
1863 if ((RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
1864 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) && optFenceWait) {
1865 auto& vkContext = RsVulkanContext::GetSingleton().GetRsVulkanInterface();
1866
1867 VkExportSemaphoreCreateInfo exportSemaphoreCreateInfo;
1868 exportSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
1869 exportSemaphoreCreateInfo.pNext = nullptr;
1870 exportSemaphoreCreateInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
1871
1872 VkSemaphoreCreateInfo semaphoreInfo;
1873 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
1874 semaphoreInfo.pNext = &exportSemaphoreCreateInfo;
1875 semaphoreInfo.flags = 0;
1876 VkSemaphore semaphore;
1877 vkContext.vkCreateSemaphore(vkContext.GetDevice(), &semaphoreInfo, nullptr, &semaphore);
1878 GrBackendSemaphore backendSemaphore;
1879 backendSemaphore.initVulkan(semaphore);
1880
1881 DestroySemaphoreInfo* destroyInfo =
1882 new DestroySemaphoreInfo(vkContext.vkDestroySemaphore, vkContext.GetDevice(), semaphore);
1883
1884 Drawing::FlushInfo drawingFlushInfo;
1885 drawingFlushInfo.backendSurfaceAccess = true;
1886 drawingFlushInfo.numSemaphores = 1;
1887 drawingFlushInfo.backendSemaphore = static_cast<void*>(&backendSemaphore);
1888 drawingFlushInfo.finishedProc = [](void *context) {
1889 DestroySemaphoreInfo::DestroySemaphore(context);
1890 };
1891 drawingFlushInfo.finishedContext = destroyInfo;
1892 surface->Flush(&drawingFlushInfo);
1893 grContext->Submit();
1894 DestroySemaphoreInfo::DestroySemaphore(destroyInfo);
1895 } else {
1896 surface->FlushAndSubmit(true);
1897 }
1898 #else
1899 surface->FlushAndSubmit(true);
1900 #endif
1901 }
1902
AccumulateMatrixAndAlpha(std::shared_ptr<RSSurfaceRenderNode> & hwcNode,Drawing::Matrix & matrix,float & alpha)1903 void RSUniRenderUtil::AccumulateMatrixAndAlpha(std::shared_ptr<RSSurfaceRenderNode>& hwcNode,
1904 Drawing::Matrix& matrix, float& alpha)
1905 {
1906 if (hwcNode == nullptr) {
1907 return;
1908 }
1909 const auto& property = hwcNode->GetRenderProperties();
1910 alpha = property.GetAlpha();
1911 matrix = property.GetBoundsGeometry()->GetMatrix();
1912 auto parent = hwcNode->GetParent().lock();
1913 while (parent && parent->GetType() != RSRenderNodeType::DISPLAY_NODE) {
1914 const auto& curProperty = parent->GetRenderProperties();
1915 alpha *= curProperty.GetAlpha();
1916 matrix.PostConcat(curProperty.GetBoundsGeometry()->GetMatrix());
1917 parent = parent->GetParent().lock();
1918 }
1919 if (!parent) {
1920 return;
1921 }
1922 const auto& parentProperty = parent->GetRenderProperties();
1923 alpha *= parentProperty.GetAlpha();
1924 matrix.PostConcat(parentProperty.GetBoundsGeometry()->GetMatrix());
1925 }
1926
GenerateSecRectInfoFromNode(RSRenderNode & node,RectI rect)1927 SecRectInfo RSUniRenderUtil::GenerateSecRectInfoFromNode(RSRenderNode& node, RectI rect)
1928 {
1929 SecRectInfo uiExtensionRectInfo;
1930 uiExtensionRectInfo.relativeCoords = rect;
1931 uiExtensionRectInfo.scale = node.GetRenderProperties().GetScale();
1932 return uiExtensionRectInfo;
1933 }
1934
GenerateSecSurfaceInfoFromNode(NodeId uiExtensionId,NodeId hostId,SecRectInfo uiExtensionRectInfo)1935 SecSurfaceInfo RSUniRenderUtil::GenerateSecSurfaceInfoFromNode(
1936 NodeId uiExtensionId, NodeId hostId, SecRectInfo uiExtensionRectInfo)
1937 {
1938 SecSurfaceInfo secSurfaceInfo;
1939 secSurfaceInfo.uiExtensionRectInfo = uiExtensionRectInfo;
1940 secSurfaceInfo.uiExtensionPid = ExtractPid(uiExtensionId);
1941 secSurfaceInfo.hostPid = ExtractPid(hostId);
1942 secSurfaceInfo.uiExtensionNodeId = uiExtensionId;
1943 secSurfaceInfo.hostNodeId = hostId;
1944 return secSurfaceInfo;
1945 }
1946
UIExtensionFindAndTraverseAncestor(const RSRenderNodeMap & nodeMap,UIExtensionCallbackData & callbackData,bool isUnobscured)1947 void RSUniRenderUtil::UIExtensionFindAndTraverseAncestor(
1948 const RSRenderNodeMap& nodeMap, UIExtensionCallbackData& callbackData, bool isUnobscured)
1949 {
1950 const auto& secUIExtensionNodes = RSSurfaceRenderNode::GetSecUIExtensionNodes();
1951 for (auto it = secUIExtensionNodes.begin(); it != secUIExtensionNodes.end(); ++it) {
1952 currentUIExtensionIndex_ = -1;
1953 // only traverse host node one time, even if it has multiple uiextension children.
1954 if (callbackData.find(it->second) != callbackData.end()) {
1955 continue;
1956 }
1957 auto hostNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(nodeMap.GetRenderNode(it->second));
1958 if (!hostNode || !hostNode->GetSortedChildren()) {
1959 RS_LOGE("RSUniRenderUtil::UIExtensionFindAndTraverseAncestor failed to get host node or its children.");
1960 return;
1961 }
1962 for (const auto& child : *hostNode->GetSortedChildren()) {
1963 TraverseAndCollectUIExtensionInfo(child, Drawing::Matrix(), hostNode->GetId(), callbackData, isUnobscured);
1964 }
1965 }
1966 }
1967
TraverseAndCollectUIExtensionInfo(std::shared_ptr<RSRenderNode> node,Drawing::Matrix parentMatrix,NodeId hostId,UIExtensionCallbackData & callbackData,bool isUnobscured)1968 void RSUniRenderUtil::TraverseAndCollectUIExtensionInfo(std::shared_ptr<RSRenderNode> node,
1969 Drawing::Matrix parentMatrix, NodeId hostId, UIExtensionCallbackData& callbackData, bool isUnobscured)
1970 {
1971 if (!node) {
1972 return;
1973 }
1974 // update position relative to host app window node.
1975 std::optional<Drawing::Point> offset;
1976 auto parent = node->GetParent().lock();
1977 if (parent && !(node->IsInstanceOf<RSSurfaceRenderNode>())) {
1978 const auto& parentRenderProperties = parent->GetRenderProperties();
1979 offset = Drawing::Point { parentRenderProperties.GetFrameOffsetX(), parentRenderProperties.GetFrameOffsetY() };
1980 }
1981 const auto& nodeRenderProperties = node->GetRenderProperties();
1982 RSObjAbsGeometry boundsGeo = nodeRenderProperties.GetBoundsGeometry() == nullptr ?
1983 RSObjAbsGeometry() : *(nodeRenderProperties.GetBoundsGeometry());
1984 boundsGeo.UpdateMatrix(&parentMatrix, offset);
1985 auto rect = boundsGeo.MapAbsRect(node->GetSelfDrawRect().JoinRect(node->GetChildrenRect().ConvertTo<float>()));
1986 // if node is UIExtension type, update its own info, and skip its children.
1987 if (auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node)) {
1988 if ((surfaceNode->IsSecureUIExtension() && !isUnobscured) ||
1989 (surfaceNode->IsUnobscuredUIExtensionNode() && isUnobscured)) {
1990 currentUIExtensionIndex_++;
1991 // if host node is not recorded in callbackData, insert it.
1992 auto [iter, inserted] = callbackData.insert(std::pair(hostId, std::vector<SecSurfaceInfo>{}));
1993 if (iter != callbackData.end()) {
1994 iter->second.push_back(GenerateSecSurfaceInfoFromNode(
1995 surfaceNode->GetId(), hostId, GenerateSecRectInfoFromNode(*surfaceNode, rect)));
1996 }
1997 if (surfaceNode->ChildrenHasUIExtension()) {
1998 RS_LOGW("RSUniRenderUtil::TraverseAndCollectUIExtensionInfo UIExtension node [%{public}" PRIu64 "]"
1999 " has children UIExtension, not surpported!", surfaceNode->GetId());
2000 }
2001 return;
2002 }
2003 }
2004 // if the node is traversed after a UIExtension, collect it and skip its children (except it has UIExtension child.)
2005 auto iter = callbackData.find(hostId);
2006 if (iter != callbackData.end() && currentUIExtensionIndex_ != -1 &&
2007 currentUIExtensionIndex_ < static_cast<int>((iter->second).size())) {
2008 (iter->second)[currentUIExtensionIndex_].upperNodes.push_back(GenerateSecRectInfoFromNode(*node, rect));
2009 if (!node->ChildrenHasUIExtension()) {
2010 return;
2011 }
2012 }
2013 // continue to traverse.
2014 for (const auto& child : *node->GetSortedChildren()) {
2015 TraverseAndCollectUIExtensionInfo(child, boundsGeo.GetAbsMatrix(), hostId, callbackData);
2016 }
2017 }
2018
ProcessCacheImage(RSPaintFilterCanvas & canvas,Drawing::Image & cacheImageProcessed)2019 void RSUniRenderUtil::ProcessCacheImage(RSPaintFilterCanvas& canvas, Drawing::Image& cacheImageProcessed)
2020 {
2021 Drawing::Brush brush;
2022 brush.SetAntiAlias(true);
2023 canvas.AttachBrush(brush);
2024 // Be cautious when changing FilterMode and MipmapMode that may affect clarity
2025 auto sampling = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NEAREST);
2026 canvas.DrawImage(cacheImageProcessed, 0, 0, sampling);
2027 canvas.DetachBrush();
2028 }
2029
GetMatrix(std::shared_ptr<RSRenderNode> hwcNode)2030 std::optional<Drawing::Matrix> RSUniRenderUtil::GetMatrix(
2031 std::shared_ptr<RSRenderNode> hwcNode)
2032 {
2033 if (!hwcNode) {
2034 return std::nullopt;
2035 }
2036 auto relativeMat = Drawing::Matrix();
2037 auto& property = hwcNode->GetRenderProperties();
2038 if (auto geo = property.GetBoundsGeometry()) {
2039 if (LIKELY(!property.GetSandBox().has_value())) {
2040 relativeMat = geo->GetMatrix();
2041 } else {
2042 auto parent = hwcNode->GetParent().lock();
2043 if (!parent) {
2044 return std::nullopt;
2045 }
2046 if (auto parentGeo = parent->GetRenderProperties().GetBoundsGeometry()) {
2047 auto invertAbsParentMatrix = Drawing::Matrix();
2048 parentGeo->GetAbsMatrix().Invert(invertAbsParentMatrix);
2049 relativeMat = geo->GetAbsMatrix();
2050 relativeMat.PostConcat(invertAbsParentMatrix);
2051 }
2052 }
2053 } else {
2054 return std::nullopt;
2055 }
2056 return relativeMat;
2057 }
2058
CheckRenderSkipIfScreenOff(bool extraFrame,std::optional<ScreenId> screenId)2059 bool RSUniRenderUtil::CheckRenderSkipIfScreenOff(bool extraFrame, std::optional<ScreenId> screenId)
2060 {
2061 if (!RSSystemProperties::GetSkipDisplayIfScreenOffEnabled() || RSSystemProperties::IsPcType()) {
2062 return false;
2063 }
2064 auto screenManager = CreateOrGetScreenManager();
2065 if (!screenManager) {
2066 RS_LOGE("RSUniRenderUtil::CheckRenderSkipIfScreenOff, failed to get screen manager!");
2067 return false;
2068 }
2069 // in certain cases such as wireless display, render skipping may be disabled.
2070 auto disableRenderControlScreensCount = screenManager->GetDisableRenderControlScreensCount();
2071 auto isScreenOff = screenId.has_value() ?
2072 screenManager->IsScreenPowerOff(screenId.value()) : screenManager->IsAllScreensPowerOff();
2073 RS_TRACE_NAME_FMT("CheckRenderSkipIfScreenOff disableRenderControl:[%d], PowerOff:[%d]",
2074 disableRenderControlScreensCount, isScreenOff);
2075 if (disableRenderControlScreensCount != 0 || !isScreenOff) {
2076 return false;
2077 }
2078 if (extraFrame && screenManager->GetPowerOffNeedProcessOneFrame()) {
2079 RS_LOGI("RSUniRenderUtil::CheckRenderSkipIfScreenOff screen power off, one more frame.");
2080 screenManager->ResetPowerOffNeedProcessOneFrame();
2081 return false;
2082 } else {
2083 return !screenManager->GetPowerOffNeedProcessOneFrame();
2084 }
2085 }
2086 } // namespace Rosen
2087 } // namespace OHOS
2088