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 "common/rs_rectangles_merger.h"
30 #include "drawable/dfx/rs_dirty_rects_dfx.h"
31 #include "drawable/rs_display_render_node_drawable.h"
32 #include "drawable/rs_surface_render_node_drawable.h"
33 #include "feature/uifirst/rs_sub_thread_manager.h"
34 #ifdef RS_ENABLE_OVERLAY_DISPLAY
35 #include "feature/overlay_display/rs_overlay_display_manager.h"
36 #endif
37 #include "info_collection/rs_gpu_dirty_region_collection.h"
38 #include "params/rs_display_render_params.h"
39 #include "params/rs_surface_render_params.h"
40 #include "rs_base_render_util.h"
41 #include "pipeline/main_thread/rs_main_thread.h"
42 #include "pipeline/rs_render_node.h"
43 #include "pipeline/rs_surface_render_node.h"
44 #include "platform/common/rs_log.h"
45 #include "property/rs_properties.h"
46 #include "render/rs_drawing_filter.h"
47 #include "render/rs_maskcolor_shader_filter.h"
48 #include "render/rs_material_filter.h"
49 #include "render/rs_path.h"
50
51 #ifdef RS_ENABLE_VK
52 #include "include/gpu/GrBackendSurface.h"
53 #include "platform/ohos/backend/native_buffer_utils.h"
54 #include "platform/ohos/backend/rs_surface_ohos_vulkan.h"
55 #include "platform/ohos/backend/rs_vulkan_context.h"
56 #endif
57
58 #ifdef SOC_PERF_ENABLE
59 #include "socperf_client.h"
60 #endif
61 #include "render_frame_trace.h"
62
63 namespace OHOS {
64 namespace Rosen {
65 namespace {
66 constexpr const char* CAPTURE_WINDOW_NAME = "CapsuleWindow";
67 constexpr float GAMMA2_2 = 2.2f;
68 constexpr int64_t PERF_TIME_OUT = 950;
69 constexpr uint32_t PERF_LEVEL_INTERVAL = 10;
70 constexpr uint32_t PERF_LAYER_START_NUM = 12;
71 constexpr uint32_t PERF_LEVEL_0 = 0;
72 constexpr uint32_t PERF_LEVEL_1 = 1;
73 constexpr uint32_t PERF_LEVEL_2 = 2;
74 constexpr int32_t PERF_LEVEL_1_REQUESTED_CODE = 10013;
75 constexpr int32_t PERF_LEVEL_2_REQUESTED_CODE = 10014;
76 constexpr int32_t PERF_LEVEL_3_REQUESTED_CODE = 10015;
77 constexpr int MAX_DIRTY_ALIGNMENT_SIZE = 128;
PerfRequest(int32_t perfRequestCode,bool onOffTag)78 void PerfRequest(int32_t perfRequestCode, bool onOffTag)
79 {
80 #ifdef SOC_PERF_ENABLE
81 OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequestEx(perfRequestCode, onOffTag, "");
82 RS_LOGD("RSProcessor::soc perf info [%{public}d %{public}d]", perfRequestCode, onOffTag);
83 #endif
84 }
85 }
MergeDirtyRectAfterMergeHistory(std::shared_ptr<RSDirtyRegionManager> dirtyManager,Occlusion::Region & dirtyRegion)86 void RSUniRenderUtil::MergeDirtyRectAfterMergeHistory(
87 std::shared_ptr<RSDirtyRegionManager> dirtyManager, Occlusion::Region& dirtyRegion)
88 {
89 const auto clipRectThreshold = RSSystemProperties::GetClipRectThreshold();
90 if (clipRectThreshold < 1.f) {
91 Occlusion::Region allDirtyRegion{ Occlusion::Rect{ dirtyManager->GetDirtyRegion() } };
92 allDirtyRegion.OrSelf(dirtyRegion);
93 auto bound = allDirtyRegion.GetBound();
94 if (allDirtyRegion.GetSize() > 1 && !bound.IsEmpty() &&
95 allDirtyRegion.Area() > bound.Area() * clipRectThreshold) {
96 dirtyManager->MergeDirtyRectAfterMergeHistory(bound.ToRectI());
97 RS_OPTIONAL_TRACE_NAME_FMT("dirty expand: %s to %s",
98 allDirtyRegion.GetRegionInfo().c_str(), bound.GetRectInfo().c_str());
99 }
100 }
101 }
102
MergeDirtyHistory(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,ScreenInfo & screenInfo,RSDirtyRectsDfx & rsDirtyRectsDfx,RSDisplayRenderParams & params)103 std::vector<RectI> RSUniRenderUtil::MergeDirtyHistory(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable,
104 int32_t bufferAge, ScreenInfo& screenInfo, RSDirtyRectsDfx& rsDirtyRectsDfx, RSDisplayRenderParams& params)
105 {
106 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
107 // renderThreadParams/dirtyManager not null in caller
108 auto dirtyManager = displayDrawable.GetSyncDirtyManager();
109 auto& curAllSurfaceDrawables = params.GetAllMainAndLeashSurfaceDrawables();
110 RSUniRenderUtil::MergeDirtyHistoryForDrawable(displayDrawable, bufferAge, params, false);
111 Occlusion::Region dirtyRegion = RSUniRenderUtil::MergeVisibleAdvancedDirtyRegion(
112 curAllSurfaceDrawables, RSUniRenderThread::Instance().GetDrawStatusVec());
113 if (uniParam->GetAdvancedDirtyType() == AdvancedDirtyRegionType::DISABLED &&
114 !uniParam->IsDirtyAlignEnabled()) {
115 MergeDirtyRectAfterMergeHistory(dirtyManager, dirtyRegion);
116 }
117 RectI screenRectI(0, 0, static_cast<int32_t>(screenInfo.phyWidth), static_cast<int32_t>(screenInfo.phyHeight));
118 #ifdef RS_ENABLE_OVERLAY_DISPLAY
119 // overlay display expand dirty region
120 RSOverlayDisplayManager::Instance().ExpandDirtyRegion(*dirtyManager, screenInfo, dirtyRegion);
121 #endif
122 Occlusion::Region globalDirtyRegion;
123 for (const auto& rect : dirtyManager->GetAdvancedDirtyRegion()) {
124 Occlusion::Region region = Occlusion::Region(Occlusion::Rect(rect));
125 globalDirtyRegion.OrSelf(region);
126 GpuDirtyRegionCollection::GetInstance().UpdateGlobalDirtyInfoForDFX(rect.IntersectRect(screenRectI));
127 }
128 Occlusion::Region damageRegion;
129 switch (uniParam->GetAdvancedDirtyType()) {
130 case AdvancedDirtyRegionType::DISABLED:
131 damageRegion = dirtyRegion.Or(globalDirtyRegion);
132 break;
133 case AdvancedDirtyRegionType::SET_ADVANCED_SURFACE_AND_DISPLAY:
134 damageRegion = RSUniRenderUtil::MergeDirtyRects(dirtyRegion.Or(globalDirtyRegion));
135 break;
136 case AdvancedDirtyRegionType::SET_ADVANCED_DISPLAY:
137 damageRegion = RSUniRenderUtil::MergeDirtyRects(globalDirtyRegion);
138 damageRegion.OrSelf(dirtyRegion);
139 break;
140 default:
141 damageRegion = dirtyRegion.Or(globalDirtyRegion);
142 RS_LOGI("RSUniRenderUtil::MergeDirtyHistory unsupported advanced dirty region type");
143 RS_TRACE_NAME_FMT("RSUniRenderUtil::MergeDirtyHistory unsupported advanced dirty region type");
144 break;
145 }
146 Occlusion::Region drawnRegion;
147 if (screenInfo.isSamplingOn && screenInfo.samplingScale > 0) {
148 GetSampledDamageAndDrawnRegion(screenInfo, damageRegion, uniParam->IsDirtyAlignEnabled(),
149 damageRegion, drawnRegion);
150 } else {
151 drawnRegion = uniParam->IsDirtyAlignEnabled() ?
152 damageRegion.GetAlignedRegion(MAX_DIRTY_ALIGNMENT_SIZE) : damageRegion;
153 }
154 RSUniRenderUtil::SetDrawRegionForQuickReject(curAllSurfaceDrawables, drawnRegion);
155 rsDirtyRectsDfx.SetDirtyRegion(drawnRegion);
156 auto damageRegionRects = RSUniRenderUtil::ScreenIntersectDirtyRects(damageRegion, screenInfo);
157 if (damageRegionRects.empty()) {
158 // When damageRegionRects is empty, SetDamageRegion function will not take effect and buffer will
159 // full screen refresh. Therefore, we need to insert an empty rect into the damageRegionRects array
160 damageRegionRects.emplace_back(RectI(0, 0, 0, 0));
161 }
162 return damageRegionRects;
163 }
164
MergeDirtyHistoryInVirtual(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,ScreenInfo & screenInfo)165 std::vector<RectI> RSUniRenderUtil::MergeDirtyHistoryInVirtual(
166 DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable, int32_t bufferAge, ScreenInfo& screenInfo)
167 {
168 auto params = static_cast<RSDisplayRenderParams*>(displayDrawable.GetRenderParams().get());
169 auto& renderThreadParams = RSUniRenderThread::Instance().GetRSRenderThreadParams();
170 if (!renderThreadParams || !params) {
171 return {};
172 }
173 auto& curAllSurfaceDrawables = params->GetAllMainAndLeashSurfaceDrawables();
174 auto dirtyManager = displayDrawable.GetSyncDirtyManager();
175 RSUniRenderUtil::MergeDirtyHistoryInVirtual(displayDrawable, bufferAge);
176 Occlusion::Region dirtyRegion = RSUniRenderUtil::MergeVisibleDirtyRegionInVirtual(curAllSurfaceDrawables);
177
178 RectI rect = dirtyManager->GetRectFlipWithinSurface(dirtyManager->GetDirtyRegionInVirtual());
179 auto rects = RSUniRenderUtil::ScreenIntersectDirtyRects(dirtyRegion, screenInfo);
180 if (!rect.IsEmpty()) {
181 rects.emplace_back(rect);
182 }
183 if (screenInfo.isSamplingOn && screenInfo.samplingScale > 0) {
184 std::vector<RectI> dstDamageRegionrects;
185 for (const auto& rect : rects) {
186 Drawing::Matrix scaleMatrix;
187 scaleMatrix.SetScaleTranslate(screenInfo.samplingScale, screenInfo.samplingScale,
188 screenInfo.samplingTranslateX, screenInfo.samplingTranslateY);
189 RectI mappedRect = RSObjAbsGeometry::MapRect(rect.ConvertTo<float>(), scaleMatrix);
190 const Vector4<int> expandSize{screenInfo.samplingDistance, screenInfo.samplingDistance,
191 screenInfo.samplingDistance, screenInfo.samplingDistance};
192 dstDamageRegionrects.emplace_back(mappedRect.MakeOutset(expandSize));
193 }
194 return dstDamageRegionrects;
195 }
196 return rects;
197 }
198
MergeDirtyHistoryForDrawable(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,RSDisplayRenderParams & params,bool useAlignedDirtyRegion)199 void RSUniRenderUtil::MergeDirtyHistoryForDrawable(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable,
200 int32_t bufferAge, RSDisplayRenderParams& params, bool useAlignedDirtyRegion)
201 {
202 auto& curAllSurfaceDrawables = params.GetAllMainAndLeashSurfaceDrawables();
203 // update all child surfacenode history
204 for (auto it = curAllSurfaceDrawables.rbegin(); it != curAllSurfaceDrawables.rend(); ++it) {
205 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
206 if (surfaceNodeDrawable == nullptr) {
207 continue;
208 }
209 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
210 if (surfaceParams == nullptr || !surfaceParams->IsAppWindow()) {
211 continue;
212 }
213 // for cross-display surface, only merge dirty history once.
214 if (surfaceParams->IsFirstLevelCrossNode() && !params.IsFirstVisitCrossNodeDisplay()) {
215 continue;
216 }
217 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
218 if (surfaceDirtyManager == nullptr) {
219 continue;
220 }
221 RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderUtil::MergeDirtyHistory for surfaceNode %" PRIu64"",
222 surfaceParams->GetId());
223 if (!surfaceDirtyManager->SetBufferAge(bufferAge)) {
224 ROSEN_LOGW("RSUniRenderUtil::MergeDirtyHistory with invalid buffer age %{public}d", bufferAge);
225 }
226 surfaceDirtyManager->IntersectDirtyRect(surfaceParams->GetOldDirtyInSurface());
227 surfaceDirtyManager->UpdateDirty(useAlignedDirtyRegion);
228 }
229
230 // update display dirtymanager
231 if (auto dirtyManager = displayDrawable.GetSyncDirtyManager()) {
232 dirtyManager->SetBufferAge(bufferAge);
233 dirtyManager->UpdateDirty(useAlignedDirtyRegion);
234 }
235 }
236
MergeVisibleDirtyRegion(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceNodeDrawables,std::vector<NodeId> & hasVisibleDirtyRegionSurfaceVec,bool useAlignedDirtyRegion)237 Occlusion::Region RSUniRenderUtil::MergeVisibleDirtyRegion(
238 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceNodeDrawables,
239 std::vector<NodeId>& hasVisibleDirtyRegionSurfaceVec, bool useAlignedDirtyRegion)
240 {
241 Occlusion::Region allSurfaceVisibleDirtyRegion;
242 for (auto it = allSurfaceNodeDrawables.rbegin(); it != allSurfaceNodeDrawables.rend(); ++it) {
243 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
244 if (surfaceNodeDrawable == nullptr) {
245 RS_LOGI("MergeVisibleDirtyRegion surfaceNodeDrawable is nullptr");
246 continue;
247 }
248 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
249 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
250 if (!surfaceParams || !surfaceDirtyManager) {
251 RS_LOGI("RSUniRenderUtil::MergeVisibleDirtyRegion node(%{public}" PRIu64") params or "
252 "dirty manager is nullptr", surfaceNodeDrawable->GetId());
253 continue;
254 }
255 if (!surfaceParams->IsAppWindow() || surfaceParams->GetDstRect().IsEmpty()) {
256 continue;
257 }
258 // for cross-display surface, only consider the dirty region on the first display (use global dirty for others).
259 if (surfaceParams->IsFirstLevelCrossNode() &&
260 !RSUniRenderThread::Instance().GetRSRenderThreadParams()->IsFirstVisitCrossNodeDisplay()) {
261 continue;
262 }
263 auto surfaceDirtyRect = surfaceDirtyManager->GetDirtyRegion();
264 Occlusion::Rect dirtyRect { surfaceDirtyRect.left_, surfaceDirtyRect.top_, surfaceDirtyRect.GetRight(),
265 surfaceDirtyRect.GetBottom() };
266 auto visibleRegion = surfaceParams->GetVisibleRegion();
267 Occlusion::Region surfaceDirtyRegion { dirtyRect };
268 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
269
270 surfaceNodeDrawable->SetVisibleDirtyRegion(surfaceVisibleDirtyRegion);
271 if (!surfaceVisibleDirtyRegion.IsEmpty()) {
272 hasVisibleDirtyRegionSurfaceVec.emplace_back(surfaceParams->GetId());
273 }
274 if (useAlignedDirtyRegion) {
275 Occlusion::Region alignedRegion = AlignedDirtyRegion(surfaceVisibleDirtyRegion);
276 surfaceNodeDrawable->SetAlignedVisibleDirtyRegion(alignedRegion);
277 allSurfaceVisibleDirtyRegion.OrSelf(alignedRegion);
278 GpuDirtyRegionCollection::GetInstance().UpdateActiveDirtyInfoForDFX(surfaceParams->GetId(),
279 surfaceNodeDrawable->GetName(), alignedRegion.GetRegionRectIs());
280 } else {
281 allSurfaceVisibleDirtyRegion = allSurfaceVisibleDirtyRegion.Or(surfaceVisibleDirtyRegion);
282 GpuDirtyRegionCollection::GetInstance().UpdateActiveDirtyInfoForDFX(surfaceParams->GetId(),
283 surfaceNodeDrawable->GetName(), surfaceVisibleDirtyRegion.GetRegionRectIs());
284 }
285 }
286 return allSurfaceVisibleDirtyRegion;
287 }
288
MergeVisibleAdvancedDirtyRegion(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceNodeDrawables,std::vector<NodeId> & hasVisibleDirtyRegionSurfaceVec)289 Occlusion::Region RSUniRenderUtil::MergeVisibleAdvancedDirtyRegion(
290 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceNodeDrawables,
291 std::vector<NodeId>& hasVisibleDirtyRegionSurfaceVec)
292 {
293 Occlusion::Region allSurfaceVisibleDirtyRegion;
294 for (auto it = allSurfaceNodeDrawables.rbegin(); it != allSurfaceNodeDrawables.rend(); ++it) {
295 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
296 if (surfaceNodeDrawable == nullptr) {
297 RS_LOGI("RSUniRenderUtil::MergeVisibleDirtyRegion surfaceNodeDrawable is nullptr");
298 continue;
299 }
300 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
301 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
302 if (!surfaceParams || !surfaceDirtyManager) {
303 RS_LOGI("RSUniRenderUtil::MergeVisibleDirtyRegion node(%{public}" PRIu64") params or"
304 "dirty manager is nullptr", surfaceNodeDrawable->GetId());
305 continue;
306 }
307 if (!surfaceParams->IsAppWindow() || surfaceParams->GetDstRect().IsEmpty()) {
308 continue;
309 }
310 //for cross-display surface, only consider the dirty region on the first display (use global dirty for others).
311 if (surfaceParams->IsFirstLevelCrossNode() &&
312 !RSUniRenderThread::Instance().GetRSRenderThreadParams()->IsFirstVisitCrossNodeDisplay()) {
313 continue;
314 }
315 Occlusion::Region surfaceAdvancedDirtyRegion = Occlusion::Region();
316 for (const auto& rect : surfaceDirtyManager->GetAdvancedDirtyRegion()) {
317 Occlusion::Region region = Occlusion::Region(Occlusion::Rect(rect));
318 surfaceAdvancedDirtyRegion.OrSelf(region);
319 }
320 auto visibleRegion = surfaceParams->GetVisibleRegion();
321 Occlusion::Region surfaceVisibleDirtyRegion = surfaceAdvancedDirtyRegion.And(visibleRegion);
322 surfaceNodeDrawable->SetVisibleDirtyRegion(surfaceVisibleDirtyRegion);
323 if (!surfaceVisibleDirtyRegion.IsEmpty()) {
324 hasVisibleDirtyRegionSurfaceVec.emplace_back(surfaceParams->GetId());
325 }
326 allSurfaceVisibleDirtyRegion = allSurfaceVisibleDirtyRegion.Or(surfaceVisibleDirtyRegion);
327 GpuDirtyRegionCollection::GetInstance().UpdateActiveDirtyInfoForDFX(surfaceParams->GetId(),
328 surfaceNodeDrawable->GetName(), surfaceVisibleDirtyRegion.GetRegionRectIs());
329 }
330 return allSurfaceVisibleDirtyRegion;
331 }
332
MergeDirtyRects(Occlusion::Region dirtyRegion)333 Occlusion::Region RSUniRenderUtil::MergeDirtyRects(Occlusion::Region dirtyRegion)
334 {
335 RectsMerger merger(RSAdvancedDirtyConfig::RECT_NUM_MERGING_ALL, RSAdvancedDirtyConfig::RECT_NUM_MERGING_BY_LEVEL);
336 auto mergedRects = merger.MergeAllRects(dirtyRegion.GetRegionRects(),
337 RSAdvancedDirtyConfig::EXPECTED_OUTPUT_NUM, RSAdvancedDirtyConfig::MAX_TOLERABLE_COST);
338 Occlusion::Region results = {};
339 for (const auto& rect : mergedRects) {
340 Occlusion::Region region = Occlusion::Region(rect);
341 results.OrSelf(region);
342 }
343 return results;
344 }
345
SetDrawRegionForQuickReject(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceDrawables,const Occlusion::Region mergedDirtyRects)346 void RSUniRenderUtil::SetDrawRegionForQuickReject(
347 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceDrawables,
348 const Occlusion::Region mergedDirtyRects)
349 {
350 auto rectsForQuickReject = mergedDirtyRects.GetRegionRectIs();
351 for (const auto& rect : mergedDirtyRects.GetRegionRects()) {
352 rectsForQuickReject.push_back(rect.ToRectI());
353 }
354 for (auto it = allSurfaceDrawables.rbegin(); it != allSurfaceDrawables.rend(); ++it) {
355 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
356 if (surfaceNodeDrawable == nullptr) {
357 continue;
358 }
359 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
360 if (!surfaceParams || !surfaceParams->IsMainWindowType()) {
361 continue;
362 }
363 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
364 if (surfaceDirtyManager == nullptr) {
365 continue;
366 }
367 surfaceDirtyManager->SetDirtyRegionForQuickReject(rectsForQuickReject);
368 }
369 }
370
MergeDirtyHistoryInVirtual(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,int32_t bufferAge,bool renderParallel)371 void RSUniRenderUtil::MergeDirtyHistoryInVirtual(DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable,
372 int32_t bufferAge, bool renderParallel)
373 {
374 (void)renderParallel;
375 auto& params = displayDrawable.GetRenderParams();
376 if (!params) {
377 RS_LOGE("RSUniRenderUtil::MergeDirtyHistory params is nullptr");
378 return;
379 }
380 auto& curAllSurfaceDrawables = params->GetAllMainAndLeashSurfaceDrawables();
381 for (auto it = curAllSurfaceDrawables.rbegin(); it != curAllSurfaceDrawables.rend(); ++it) {
382 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
383 if (surfaceNodeDrawable == nullptr) {
384 continue;
385 }
386 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
387 if (surfaceParams == nullptr || !surfaceParams->IsAppWindow()) {
388 continue;
389 }
390 RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderUtil::MergeDirtyHistory for surfaceNode %" PRIu64"",
391 surfaceParams->GetId());
392 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
393 surfaceDirtyManager->MergeDirtyHistoryInVirtual(bufferAge);
394 }
395 // update display dirtymanager
396 auto displayDirtyManager = displayDrawable.GetSyncDirtyManager();
397 displayDirtyManager->MergeDirtyHistoryInVirtual(bufferAge);
398 }
399
MergeVisibleDirtyRegionInVirtual(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceNodeDrawables)400 Occlusion::Region RSUniRenderUtil::MergeVisibleDirtyRegionInVirtual(
401 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceNodeDrawables)
402 {
403 Occlusion::Region allSurfaceVisibleDirtyRegion;
404 for (auto it = allSurfaceNodeDrawables.rbegin(); it != allSurfaceNodeDrawables.rend(); ++it) {
405 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
406 if (surfaceNodeDrawable == nullptr) {
407 RS_LOGI("MergeVisibleDirtyRegion surfaceNodeDrawable is nullptr");
408 continue;
409 }
410 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
411 if (!surfaceParams) {
412 RS_LOGI("RSUniRenderUtil::MergeVisibleDirtyRegion surface params is nullptr");
413 continue;
414 }
415 if (!surfaceParams->IsAppWindow() || surfaceParams->GetDstRect().IsEmpty() ||
416 surfaceParams->GetName().find(CAPTURE_WINDOW_NAME) != std::string::npos ||
417 surfaceParams->GetSpecialLayerMgr().Find(SpecialLayerType::SKIP)) {
418 continue;
419 }
420 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
421 auto surfaceDirtyRect = surfaceDirtyManager->GetDirtyRegionInVirtual();
422 Occlusion::Rect dirtyRect { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
423 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() };
424 auto visibleRegion = surfaceParams->GetVisibleRegionInVirtual();
425 Occlusion::Region surfaceDirtyRegion { dirtyRect };
426 Occlusion::Region surfaceVisibleDirtyRegion = surfaceDirtyRegion.And(visibleRegion);
427 allSurfaceVisibleDirtyRegion = allSurfaceVisibleDirtyRegion.Or(surfaceVisibleDirtyRegion);
428 }
429 return allSurfaceVisibleDirtyRegion;
430 }
431
GetCurrentFrameVisibleDirty(DrawableV2::RSDisplayRenderNodeDrawable & displayDrawable,ScreenInfo & screenInfo,RSDisplayRenderParams & params)432 std::vector<RectI> RSUniRenderUtil::GetCurrentFrameVisibleDirty(
433 DrawableV2::RSDisplayRenderNodeDrawable& displayDrawable, ScreenInfo& screenInfo, RSDisplayRenderParams& params)
434 {
435 Occlusion::Region damageRegions;
436 auto& curAllSurfaceDrawables = params.GetAllMainAndLeashSurfaceDrawables();
437 // update all child surfacenode history
438 for (auto it = curAllSurfaceDrawables.rbegin(); it != curAllSurfaceDrawables.rend(); ++it) {
439 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
440 if (surfaceNodeDrawable == nullptr) {
441 RS_LOGI("GetCurrentFrameVisibleDirty surfaceNodeDrawable is nullptr");
442 continue;
443 }
444 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
445 auto surfaceDirtyManager = surfaceNodeDrawable->GetSyncDirtyManager();
446 if (!surfaceParams || !surfaceDirtyManager) {
447 RS_LOGI("RSUniRenderUtil::GetCurrentFrameVisibleDirty node(%{public}" PRIu64") params or "
448 "dirty manager is nullptr", surfaceNodeDrawable->GetId());
449 continue;
450 }
451 if (!surfaceParams->IsAppWindow() || surfaceParams->GetDstRect().IsEmpty()) {
452 continue;
453 }
454 // for cross-display surface, only consider the dirty region on the first display (use global dirty for others).
455 if (surfaceParams->IsFirstLevelCrossNode() &&
456 !RSUniRenderThread::Instance().GetRSRenderThreadParams()->IsFirstVisitCrossNodeDisplay()) {
457 continue;
458 }
459 auto visibleRegion = surfaceParams->GetVisibleRegion();
460 auto surfaceCurrentFrameDirtyRegion = surfaceDirtyManager->GetCurrentFrameDirtyRegion();
461 Occlusion::Region currentFrameDirtyRegion { Occlusion::Rect {
462 surfaceCurrentFrameDirtyRegion.left_, surfaceCurrentFrameDirtyRegion.top_,
463 surfaceCurrentFrameDirtyRegion.GetRight(), surfaceCurrentFrameDirtyRegion.GetBottom() } };
464 Occlusion::Region damageRegion = currentFrameDirtyRegion.And(visibleRegion);
465 damageRegions.OrSelf(damageRegion);
466 }
467 auto rects = RSUniRenderUtil::ScreenIntersectDirtyRects(damageRegions, screenInfo);
468 RectI rect = displayDrawable.GetSyncDirtyManager()->GetDirtyRegionFlipWithinSurface();
469 if (!rect.IsEmpty()) {
470 rects.emplace_back(rect);
471 }
472 return rects;
473 }
474
SetAllSurfaceDrawableGlobalDirtyRegion(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & allSurfaceDrawables,const Occlusion::Region & globalDirtyRegion)475 void RSUniRenderUtil::SetAllSurfaceDrawableGlobalDirtyRegion(
476 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& allSurfaceDrawables,
477 const Occlusion::Region& globalDirtyRegion)
478 {
479 // Set Surface Global Dirty Region
480 for (auto it = allSurfaceDrawables.rbegin(); it != allSurfaceDrawables.rend(); ++it) {
481 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
482 if (surfaceNodeDrawable == nullptr) {
483 continue;
484 }
485 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
486 if (!surfaceParams) {
487 RS_LOGW("RSUniRenderUtil::MergeVisibleDirtyRegion surface params is nullptr");
488 continue;
489 }
490 if (!surfaceParams->IsMainWindowType()) {
491 continue;
492 }
493 // set display dirty region to surfaceNodeDrawable
494 surfaceNodeDrawable->SetGlobalDirtyRegion(globalDirtyRegion);
495 surfaceNodeDrawable->SetDirtyRegionAlignedEnable(false);
496 }
497 Occlusion::Region curVisibleDirtyRegion;
498 for (auto& it : allSurfaceDrawables) {
499 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(it);
500 if (surfaceNodeDrawable == nullptr) {
501 continue;
502 }
503 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
504 if (!surfaceParams) {
505 RS_LOGE("RSUniRenderUtil::MergeVisibleDirtyRegion surface params is nullptr");
506 continue;
507 }
508 if (!surfaceParams->IsMainWindowType()) {
509 continue;
510 }
511 // set display dirty region to surfaceNodeDrawable
512 surfaceNodeDrawable->SetDirtyRegionBelowCurrentLayer(curVisibleDirtyRegion);
513 auto visibleDirtyRegion = surfaceNodeDrawable->GetVisibleDirtyRegion();
514 curVisibleDirtyRegion = curVisibleDirtyRegion.Or(visibleDirtyRegion);
515 }
516 }
517
ScreenIntersectDirtyRects(const Occlusion::Region & region,ScreenInfo & screenInfo)518 std::vector<RectI> RSUniRenderUtil::ScreenIntersectDirtyRects(const Occlusion::Region ®ion, ScreenInfo& screenInfo)
519 {
520 const std::vector<Occlusion::Rect>& rects = region.GetRegionRects();
521 std::vector<RectI> retRects;
522 for (const Occlusion::Rect& rect : rects) {
523 // origin transformation
524 #ifdef RS_ENABLE_VK
525 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
526 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
527 retRects.emplace_back(RectI(rect.left_, rect.top_,
528 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
529 } else {
530 retRects.emplace_back(RectI(rect.left_, screenInfo.GetRotatedHeight() - rect.bottom_,
531 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
532 }
533 #else
534 retRects.emplace_back(RectI(rect.left_, screenInfo.GetRotatedHeight() - rect.bottom_,
535 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
536 #endif
537 }
538 RS_LOGD("ScreenIntersectDirtyRects size %{public}d %{public}s", region.GetSize(), region.GetRegionInfo().c_str());
539 return retRects;
540 }
541
GetFilpDirtyRects(const std::vector<RectI> & srcRects,const ScreenInfo & screenInfo)542 std::vector<RectI> RSUniRenderUtil::GetFilpDirtyRects(const std::vector<RectI>& srcRects, const ScreenInfo& screenInfo)
543 {
544 #ifdef RS_ENABLE_VK
545 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
546 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
547 return srcRects;
548 }
549 #endif
550
551 return FilpRects(srcRects, screenInfo);
552 }
553
FilpRects(const std::vector<RectI> & srcRects,const ScreenInfo & screenInfo)554 std::vector<RectI> RSUniRenderUtil::FilpRects(const std::vector<RectI>& srcRects, const ScreenInfo& screenInfo)
555 {
556 std::vector<RectI> retRects;
557 for (const RectI& rect : srcRects) {
558 retRects.emplace_back(RectI(rect.left_, screenInfo.GetRotatedHeight() - rect.top_ - rect.height_,
559 rect.width_, rect.height_));
560 }
561 return retRects;
562 }
563
IntersectRect(const GraphicIRect & first,const GraphicIRect & second)564 GraphicIRect RSUniRenderUtil::IntersectRect(const GraphicIRect& first, const GraphicIRect& second)
565 {
566 int left = std::max(first.x, second.x);
567 int top = std::max(first.y, second.y);
568 int right = std::min(first.x + first.w, second.x + second.w);
569 int bottom = std::min(first.y + first.h, second.y + second.h);
570 int width = right - left;
571 int height = bottom - top;
572
573 if (width <= 0 || height <= 0) {
574 return GraphicIRect { 0, 0, 0, 0 };
575 } else {
576 return GraphicIRect { left, top, width, height };
577 }
578 }
579
SrcRectScaleFit(BufferDrawParam & params,const sptr<SurfaceBuffer> & buffer,const sptr<IConsumerSurface> & surface,RectF & localBounds)580 void RSUniRenderUtil::SrcRectScaleFit(BufferDrawParam& params, const sptr<SurfaceBuffer>& buffer,
581 const sptr<IConsumerSurface>& surface, RectF& localBounds)
582 {
583 if (buffer == nullptr || surface == nullptr) {
584 RS_LOGE("buffer or surface is nullptr");
585 return;
586 }
587 uint32_t srcWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
588 uint32_t srcHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
589 float newWidth = 0.0f;
590 float newHeight = 0.0f;
591 // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
592 uint32_t boundsWidth = static_cast<uint32_t>(localBounds.GetWidth());
593 uint32_t boundsHeight = static_cast<uint32_t>(localBounds.GetHeight());
594 if (boundsWidth == 0 || boundsHeight == 0 || srcWidth == 0 || srcHeight == 0) {
595 return;
596 }
597
598 if (srcWidth * boundsHeight > srcHeight * boundsWidth) {
599 newWidth = boundsWidth;
600 newHeight = srcHeight * newWidth / srcWidth;
601 } else if (srcWidth * boundsHeight < srcHeight * boundsWidth) {
602 newHeight = boundsHeight;
603 newWidth = newHeight * srcWidth / srcHeight;
604 } else {
605 newWidth = boundsWidth;
606 newHeight = boundsHeight;
607 }
608 newHeight = newHeight * srcHeight / boundsHeight;
609 newWidth = newWidth * srcWidth / boundsWidth;
610 if (newWidth < srcWidth) {
611 float halfdw = (srcWidth - newWidth) / 2;
612 params.dstRect =
613 Drawing::Rect(params.srcRect.GetLeft() + halfdw, params.srcRect.GetTop(),
614 params.srcRect.GetLeft() + halfdw + newWidth,
615 params.srcRect.GetTop() + params.srcRect.GetHeight());
616 } else if (newHeight < srcHeight) {
617 float halfdh = (srcHeight - newHeight) / 2;
618 params.dstRect =
619 Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + halfdh,
620 params.srcRect.GetLeft() + params.srcRect.GetWidth(),
621 params.srcRect.GetTop() + halfdh + newHeight);
622 }
623 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleFit name:%{public}s,"
624 " dstRect [%{public}f %{public}f %{public}f %{public}f]",
625 surface->GetName().c_str(), params.dstRect.GetLeft(), params.dstRect.GetTop(),
626 params.dstRect.GetWidth(), params.dstRect.GetHeight());
627 }
628
SrcRectScaleDown(BufferDrawParam & params,const sptr<SurfaceBuffer> & buffer,const sptr<IConsumerSurface> & surface,RectF & localBounds)629 void RSUniRenderUtil::SrcRectScaleDown(BufferDrawParam& params, const sptr<SurfaceBuffer>& buffer,
630 const sptr<IConsumerSurface>& surface, RectF& localBounds)
631 {
632 if (buffer == nullptr || surface == nullptr) {
633 return;
634 }
635 // Canvas is able to handle the situation when the window is out of screen, using bounds instead of dst.
636 uint32_t boundsWidth = static_cast<uint32_t>(localBounds.GetWidth());
637 uint32_t boundsHeight = static_cast<uint32_t>(localBounds.GetHeight());
638 if (boundsWidth == 0 || boundsHeight == 0) {
639 RS_LOGE("RSUniRenderUtil::SrcRectScaleDown: boundsWidth or boundsHeight is 0");
640 return;
641 }
642 uint32_t newWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
643 uint32_t newHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
644
645 uint32_t newWidthBoundsHeight = newWidth * boundsHeight;
646 uint32_t newHeightBoundsWidth = newHeight * boundsWidth;
647
648 if (newWidthBoundsHeight > newHeightBoundsWidth) {
649 newWidth = boundsWidth * newHeight / boundsHeight;
650 } else if (newWidthBoundsHeight < newHeightBoundsWidth) {
651 newHeight = boundsHeight * newWidth / boundsWidth;
652 } else {
653 return;
654 }
655
656 uint32_t currentWidth = static_cast<uint32_t>(params.srcRect.GetWidth());
657 uint32_t currentHeight = static_cast<uint32_t>(params.srcRect.GetHeight());
658 if (newWidth < currentWidth) {
659 // the crop is too wide
660 uint32_t dw = currentWidth - newWidth;
661 auto halfdw = dw / 2;
662 params.srcRect =
663 Drawing::Rect(params.srcRect.GetLeft() + static_cast<int32_t>(halfdw), params.srcRect.GetTop(),
664 params.srcRect.GetLeft() + static_cast<int32_t>(halfdw) + static_cast<int32_t>(newWidth),
665 params.srcRect.GetTop() + params.srcRect.GetHeight());
666 } else {
667 // thr crop is too tall
668 uint32_t dh = currentHeight - newHeight;
669 auto halfdh = dh / 2;
670 params.srcRect =
671 Drawing::Rect(params.srcRect.GetLeft(), params.srcRect.GetTop() + static_cast<int32_t>(halfdh),
672 params.srcRect.GetLeft() + params.srcRect.GetWidth(),
673 params.srcRect.GetTop() + static_cast<int32_t>(halfdh) + static_cast<int32_t>(newHeight));
674 }
675 RS_LOGD("RsDebug RSUniRenderUtil::SrcRectScaleDown name:%{public}s,"
676 " srcRect [%{public}f %{public}f %{public}f %{public}f]",
677 surface->GetName().c_str(), params.srcRect.GetLeft(), params.srcRect.GetTop(),
678 params.srcRect.GetWidth(), params.srcRect.GetHeight());
679 }
680
SetSrcRect(BufferDrawParam & params,const sptr<SurfaceBuffer> & buffer)681 void RSUniRenderUtil::SetSrcRect(BufferDrawParam& params, const sptr<SurfaceBuffer>& buffer)
682 {
683 Rect crop = {0, 0, 0, 0};
684 params.hasCropMetadata = buffer->GetCropMetadata(crop);
685
686 if (UNLIKELY(params.hasCropMetadata)) {
687 RS_LOGD("buffer has crop metadata, "
688 "left = %{public}u, right = %{public}u, width = %{public}u, height = %{public}u",
689 crop.x, crop.y, crop.w, crop.h);
690 params.srcRect = Drawing::Rect(crop.x, crop.y, crop.x + crop.w, crop.y + crop.h);
691 } else {
692 params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
693 }
694 }
695
GetMatrixOfBufferToRelRect(const RSSurfaceRenderNode & node)696 Drawing::Matrix RSUniRenderUtil::GetMatrixOfBufferToRelRect(const RSSurfaceRenderNode& node)
697 {
698 const sptr<SurfaceBuffer> buffer = node.GetRSSurfaceHandler()->GetBuffer();
699 if (buffer == nullptr) {
700 return Drawing::Matrix();
701 }
702
703 auto consumer = node.GetRSSurfaceHandler()->GetConsumer();
704 if (consumer == nullptr) {
705 return Drawing::Matrix();
706 }
707
708 BufferDrawParam params;
709 params.buffer = buffer;
710 params.srcRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
711 const RSProperties& property = node.GetRenderProperties();
712 params.dstRect = Drawing::Rect(0, 0, property.GetBoundsWidth(), property.GetBoundsHeight());
713 auto transform = RSBaseRenderUtil::GetSurfaceBufferTransformType(consumer, buffer);
714 RectF localBounds = { 0.0f, 0.0f, property.GetBoundsWidth(), property.GetBoundsHeight() };
715 auto& renderParams = const_cast<RSSurfaceRenderNode&>(node).GetStagingRenderParams();
716 auto surfaceRenderParams = renderParams == nullptr
717 ? nullptr
718 : static_cast<RSSurfaceRenderParams*>(renderParams.get());
719 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, property.GetFrameGravity(), localBounds, params,
720 surfaceRenderParams);
721 RSBaseRenderUtil::FlipMatrix(transform, params);
722 return params.matrix;
723 }
724
CreateBufferDrawParam(const RSSurfaceRenderNode & node,bool forceCPU,uint32_t threadIndex,bool useRenderParams)725 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(
726 const RSSurfaceRenderNode& node, bool forceCPU, uint32_t threadIndex, bool useRenderParams)
727 {
728 BufferDrawParam params;
729
730 auto drawable = node.GetRenderDrawable();
731 if (useRenderParams && !drawable) {
732 return params;
733 }
734 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
735 auto& nodeParams = surfaceDrawable->GetRenderParams();
736 if (useRenderParams && !nodeParams) {
737 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam RenderThread nodeParams is nullptr");
738 return params;
739 }
740 auto surfaceHandler = node.GetRSSurfaceHandler();
741 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(nodeParams.get());
742 const RSProperties& property = node.GetRenderProperties();
743
744 params.threadIndex = threadIndex;
745 params.useBilinearInterpolation = useRenderParams ?
746 surfaceParams->NeedBilinearInterpolation() : node.NeedBilinearInterpolation();
747 params.useCPU = forceCPU;
748 Drawing::Filter filter;
749 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
750 params.paint.SetFilter(filter);
751
752 auto boundWidth = useRenderParams ? nodeParams->GetBounds().GetWidth() : property.GetBoundsWidth();
753 auto boundHeight = useRenderParams ? nodeParams->GetBounds().GetHeight() : property.GetBoundsHeight();
754 params.dstRect = Drawing::Rect(0, 0, boundWidth, boundHeight);
755
756 const sptr<SurfaceBuffer> buffer = useRenderParams ? surfaceParams->GetBuffer() : surfaceHandler->GetBuffer();
757 if (buffer == nullptr) {
758 return params;
759 }
760 params.buffer = buffer;
761 params.acquireFence = useRenderParams ? nodeParams->GetAcquireFence() : surfaceHandler->GetAcquireFence();
762 SetSrcRect(params, buffer);
763 auto consumer = useRenderParams ? surfaceDrawable->GetConsumerOnDraw() : surfaceHandler->GetConsumer();
764 if (consumer == nullptr) {
765 return params;
766 }
767 auto transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
768 if (consumer->GetSurfaceBufferTransformType(buffer, &transform) != GSERROR_OK) {
769 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam GetSurfaceBufferTransformType failed");
770 }
771 RectF localBounds = { 0.0f, 0.0f, boundWidth, boundHeight };
772 auto gravity = useRenderParams ? nodeParams->GetFrameGravity() : property.GetFrameGravity();
773 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, gravity, localBounds, params, surfaceParams);
774 RSBaseRenderUtil::FlipMatrix(transform, params);
775 ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
776 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
777 SrcRectScaleDown(params, buffer, consumer, localBounds);
778 } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
779 SrcRectScaleFit(params, buffer, consumer, localBounds);
780 }
781 return params;
782 }
783
CreateBufferDrawParam(const DrawableV2::RSSurfaceRenderNodeDrawable & surfaceDrawable,bool forceCPU,uint32_t threadIndex)784 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(
785 const DrawableV2::RSSurfaceRenderNodeDrawable& surfaceDrawable, bool forceCPU, uint32_t threadIndex)
786 {
787 BufferDrawParam params;
788 auto& nodeParams = surfaceDrawable.GetRenderParams();
789 if (!nodeParams) {
790 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam RenderThread nodeParams is nullptr");
791 return params;
792 }
793 auto surfaceNodeParams = static_cast<RSSurfaceRenderParams*>(nodeParams.get());
794 params.threadIndex = threadIndex;
795 params.useBilinearInterpolation = surfaceNodeParams->NeedBilinearInterpolation();
796 params.useCPU = forceCPU;
797 Drawing::Filter filter;
798 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
799 params.paint.SetFilter(filter);
800
801 auto boundWidth = nodeParams->GetBounds().GetWidth();
802 auto boundHeight = nodeParams->GetBounds().GetHeight();
803 params.dstRect = Drawing::Rect(0, 0, boundWidth, boundHeight);
804
805 const sptr<SurfaceBuffer> buffer = nodeParams->GetBuffer();
806 if (buffer == nullptr) {
807 return params;
808 }
809 params.buffer = buffer;
810 params.acquireFence = nodeParams->GetAcquireFence();
811 SetSrcRect(params, buffer);
812 auto consumer = surfaceDrawable.GetConsumerOnDraw();
813 if (consumer == nullptr) {
814 return params;
815 }
816 auto transform = GraphicTransformType::GRAPHIC_ROTATE_NONE;
817 if (consumer->GetSurfaceBufferTransformType(buffer, &transform) != GSERROR_OK) {
818 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam GetSurfaceBufferTransformType failed");
819 }
820 params.preRotation = consumer->GetSurfaceAppFrameworkType() == "fixed-rotation" ? true : false;
821
822 RectF localBounds = { 0.0f, 0.0f, boundWidth, boundHeight };
823 auto gravity = nodeParams->GetFrameGravity();
824 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, gravity, localBounds, params, surfaceNodeParams);
825 RSBaseRenderUtil::FlipMatrix(transform, params);
826 ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
827 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
828 SrcRectScaleDown(params, buffer, consumer, localBounds);
829 } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
830 SrcRectScaleFit(params, buffer, consumer, localBounds);
831 }
832 return params;
833 }
834
CreateBufferDrawParamForRotationFixed(const DrawableV2::RSSurfaceRenderNodeDrawable & surfaceDrawable,RSSurfaceRenderParams & renderParams)835 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParamForRotationFixed(
836 const DrawableV2::RSSurfaceRenderNodeDrawable& surfaceDrawable, RSSurfaceRenderParams& renderParams)
837 {
838 BufferDrawParam params;
839 params.threadIndex = static_cast<uint32_t>(gettid());
840 params.useBilinearInterpolation = renderParams.NeedBilinearInterpolation();
841 params.useCPU = false;
842 params.targetColorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
843 #ifdef USE_VIDEO_PROCESSING_ENGINE
844 params.sdrNits = renderParams.GetSdrNit();
845 params.tmoNits = renderParams.GetDisplayNit();
846 params.displayNits = params.tmoNits / std::pow(renderParams.GetBrightnessRatio(), GAMMA2_2); // gamma 2.2
847 params.layerLinearMatrix = renderParams.GetLayerLinearMatrix();
848 #endif
849
850 Drawing::Filter filter;
851 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
852 params.paint.SetFilter(filter);
853
854 auto buffer = renderParams.GetBuffer();
855 if (buffer == nullptr) {
856 return params;
857 }
858 params.buffer = buffer;
859 params.acquireFence = renderParams.GetAcquireFence();
860 auto srcRect = renderParams.GetLayerInfo().srcRect;
861 params.srcRect = Drawing::Rect(srcRect.x, srcRect.y, srcRect.x + srcRect.w, srcRect.y + srcRect.h);
862
863 auto dstRect = renderParams.GetLayerInfo().dstRect;
864 params.matrix = Drawing::Matrix();
865 params.matrix.PreTranslate(static_cast<float>(dstRect.x), static_cast<float>(dstRect.y));
866
867 auto layerTransform = renderParams.GetLayerInfo().transformType;
868 int realRotation = RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(layerTransform));
869 auto flip = RSBaseRenderUtil::GetFlipTransform(layerTransform);
870 // calculate transform in anti-clockwise
871 auto transform = RSBaseRenderUtil::RotateEnumToInt(realRotation, flip);
872
873 RectF localBounds = { 0.0f, 0.0f,
874 static_cast<float>(dstRect.w), static_cast<float>(dstRect.h) };
875 DealWithRotationAndGravityForRotationFixed(transform, renderParams.GetFrameGravity(), localBounds, params);
876 RSBaseRenderUtil::FlipMatrix(transform, params);
877 return params;
878 }
879
DealWithRotationAndGravityForRotationFixed(GraphicTransformType transform,Gravity gravity,RectF & localBounds,BufferDrawParam & params)880 void RSUniRenderUtil::DealWithRotationAndGravityForRotationFixed(GraphicTransformType transform, Gravity gravity,
881 RectF& localBounds, BufferDrawParam& params)
882 {
883 auto rotationTransform = RSBaseRenderUtil::GetRotateTransform(transform);
884 params.matrix.PreConcat(RSBaseRenderUtil::GetSurfaceTransformMatrixForRotationFixed(
885 rotationTransform, localBounds));
886 if (rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_90 ||
887 rotationTransform == GraphicTransformType::GRAPHIC_ROTATE_270) {
888 // after rotate, we should swap dstRect and bound's width and height.
889 std::swap(localBounds.width_, localBounds.height_);
890 }
891 params.dstRect = Drawing::Rect(0, 0, params.srcRect.GetWidth(), params.srcRect.GetHeight());
892
893 Drawing::Matrix gravityMatrix;
894 if (!RSPropertiesPainter::GetGravityMatrix(gravity, localBounds,
895 params.srcRect.GetWidth(), params.srcRect.GetHeight(), gravityMatrix)) {
896 RS_LOGD("RSUniRenderUtil::DealWithRotationAndGravityForRotationFixed did not obtain gravity matrix.");
897 }
898 params.matrix.PreConcat(gravityMatrix);
899 }
900
CreateBufferDrawParam(const RSDisplayRenderNode & node,bool forceCPU)901 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(const RSDisplayRenderNode& node, bool forceCPU)
902 {
903 BufferDrawParam params;
904 params.useCPU = forceCPU;
905 Drawing::Filter filter;
906 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
907 params.paint.SetFilter(filter);
908
909 auto drawable = node.GetRenderDrawable();
910 if (!drawable) {
911 return params;
912 }
913 auto displayDrawable = std::static_pointer_cast<DrawableV2::RSDisplayRenderNodeDrawable>(drawable);
914 auto surfaceHandler = displayDrawable->GetRSSurfaceHandlerOnDraw();
915 const sptr<SurfaceBuffer> buffer = surfaceHandler->GetBuffer();
916 if (!buffer) {
917 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam buffer is null.");
918 return params;
919 }
920 params.buffer = buffer;
921 params.acquireFence = surfaceHandler->GetAcquireFence();
922 SetSrcRect(params, buffer);
923 params.dstRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
924 return params;
925 }
926
CreateBufferDrawParam(const RSSurfaceHandler & surfaceHandler,bool forceCPU)927 BufferDrawParam RSUniRenderUtil::CreateBufferDrawParam(const RSSurfaceHandler& surfaceHandler, bool forceCPU)
928 {
929 BufferDrawParam bufferDrawParam;
930 bufferDrawParam.useCPU = forceCPU;
931 Drawing::Filter filter;
932 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
933 bufferDrawParam.paint.SetFilter(filter);
934
935 const sptr<SurfaceBuffer> buffer = surfaceHandler.GetBuffer();
936 if (!buffer) {
937 RS_LOGE("RSUniRenderUtil::CreateBufferDrawParam buffer is null.");
938 return bufferDrawParam;
939 }
940 bufferDrawParam.buffer = buffer;
941 bufferDrawParam.acquireFence = surfaceHandler.GetAcquireFence();
942 SetSrcRect(bufferDrawParam, buffer);
943 bufferDrawParam.dstRect = Drawing::Rect(0, 0, buffer->GetSurfaceBufferWidth(), buffer->GetSurfaceBufferHeight());
944 return bufferDrawParam;
945 }
946
CreateLayerBufferDrawParam(const LayerInfoPtr & layer,bool forceCPU)947 BufferDrawParam RSUniRenderUtil::CreateLayerBufferDrawParam(const LayerInfoPtr& layer, bool forceCPU)
948 {
949 BufferDrawParam params;
950 if (layer == nullptr) {
951 return params;
952 }
953 params.useCPU = forceCPU;
954 params.useBilinearInterpolation = layer->GetNeedBilinearInterpolation();
955 Drawing::Filter filter;
956 filter.SetFilterQuality(Drawing::Filter::FilterQuality::LOW);
957 params.paint.SetFilter(filter);
958 params.paint.SetAlpha(layer->GetAlpha().gAlpha);
959 sptr<SurfaceBuffer> buffer = layer->GetBuffer();
960 if (buffer == nullptr) {
961 return params;
962 }
963 params.acquireFence = layer->GetAcquireFence();
964 params.buffer = buffer;
965 SetSrcRect(params, buffer);
966 auto boundRect = layer->GetBoundSize();
967 params.dstRect = Drawing::Rect(0, 0, boundRect.w, boundRect.h);
968
969 auto layerMatrix = layer->GetMatrix();
970 params.matrix = Drawing::Matrix();
971 bool rotationFixed = layer->GetRotationFixed();
972 auto dstRect = layer->GetLayerSize();
973 if (rotationFixed) {
974 // if rotation fixed, not use [total matrix + bounds] to draw buffer, use [src + dst + transform]
975 params.matrix.PreTranslate(static_cast<float>(dstRect.x), static_cast<float>(dstRect.y));
976 auto srcRect = layer->GetCropRect();
977 params.srcRect = Drawing::Rect(srcRect.x, srcRect.y, srcRect.x + srcRect.w, srcRect.y + srcRect.h);
978 } else {
979 params.matrix.SetMatrix(layerMatrix.scaleX, layerMatrix.skewX, layerMatrix.transX, layerMatrix.skewY,
980 layerMatrix.scaleY, layerMatrix.transY, layerMatrix.pers0, layerMatrix.pers1, layerMatrix.pers2);
981 }
982 // rotation degree anti-clockwise
983 int nodeRotation = rotationFixed ? 0 : RSUniRenderUtil::GetRotationFromMatrix(params.matrix);
984 auto layerTransform = layer->GetTransformType();
985 // calculate clockwise rotation degree excluded rotation in total matrix
986 int realRotation = (nodeRotation +
987 RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(layerTransform))) % 360;
988 auto flip = RSBaseRenderUtil::GetFlipTransform(layerTransform);
989 // calculate transform in anti-clockwise
990 auto transform = RSBaseRenderUtil::RotateEnumToInt(realRotation, flip);
991
992 RectF localBounds = { 0.0f, 0.0f,
993 rotationFixed ? static_cast<float>(dstRect.w) : static_cast<float>(boundRect.w),
994 rotationFixed ? static_cast<float>(dstRect.h) : static_cast<float>(boundRect.h) };
995 if (rotationFixed) {
996 DealWithRotationAndGravityForRotationFixed(transform, static_cast<Gravity>(layer->GetGravity()), localBounds,
997 params);
998 } else {
999 RSBaseRenderUtil::DealWithSurfaceRotationAndGravity(transform, static_cast<Gravity>(layer->GetGravity()),
1000 localBounds, params);
1001 }
1002 RSBaseRenderUtil::FlipMatrix(transform, params);
1003 if (rotationFixed) {
1004 // if rotation fixed, no need to calculate scaling mode, it is contained in dstRect
1005 return params;
1006 }
1007 const auto& surface = layer->GetSurface();
1008 if (surface == nullptr) {
1009 RS_LOGE("buffer or surface is nullptr");
1010 return params;
1011 }
1012
1013 ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
1014 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_CROP) {
1015 SrcRectScaleDown(params, buffer, surface, localBounds);
1016 } else if (scalingMode == ScalingMode::SCALING_MODE_SCALE_FIT) {
1017 SrcRectScaleFit(params, buffer, surface, localBounds);
1018 }
1019 return params;
1020 }
1021
IsNeedClient(RSSurfaceRenderNode & node,const ComposeInfo & info)1022 bool RSUniRenderUtil::IsNeedClient(RSSurfaceRenderNode& node, const ComposeInfo& info)
1023 {
1024 if (RSSystemProperties::IsForceClient()) {
1025 RS_LOGD("RSUniRenderUtil::IsNeedClient: force client.");
1026 return true;
1027 }
1028 const auto& property = node.GetRenderProperties();
1029 if (!ROSEN_EQ(property.GetRotation(), 0.f) || !ROSEN_EQ(property.GetRotationX(), 0.f) ||
1030 !ROSEN_EQ(property.GetRotationY(), 0.f) || property.GetQuaternion() != Quaternion()) {
1031 RS_LOGD("RSUniRenderUtil::IsNeedClient need client with RSSurfaceRenderNode rotation");
1032 return true;
1033 }
1034 return false;
1035 }
1036
AlignedDirtyRegion(const Occlusion::Region & dirtyRegion,int32_t alignedBits)1037 Occlusion::Region RSUniRenderUtil::AlignedDirtyRegion(const Occlusion::Region& dirtyRegion, int32_t alignedBits)
1038 {
1039 Occlusion::Region alignedRegion;
1040 if (alignedBits <= 1) {
1041 return dirtyRegion;
1042 }
1043 for (const auto& dirtyRect : dirtyRegion.GetRegionRects()) {
1044 int32_t left = (dirtyRect.left_ / alignedBits) * alignedBits;
1045 int32_t top = (dirtyRect.top_ / alignedBits) * alignedBits;
1046 int32_t width = ((dirtyRect.right_ + alignedBits - 1) / alignedBits) * alignedBits - left;
1047 int32_t height = ((dirtyRect.bottom_ + alignedBits - 1) / alignedBits) * alignedBits - top;
1048 Occlusion::Rect rect = { left, top, left + width, top + height };
1049 Occlusion::Region singleAlignedRegion(rect);
1050 alignedRegion.OrSelf(singleAlignedRegion);
1051 }
1052 return alignedRegion;
1053 }
1054
TransferToAntiClockwiseDegrees(int angle)1055 int RSUniRenderUtil::TransferToAntiClockwiseDegrees(int angle)
1056 {
1057 static const std::map<int, int> supportedDegrees = { { 90, 270 }, { 180, 180 }, { -90, 90 }, { -180, 180 },
1058 { 270, 90 }, { -270, 270 } };
1059 auto iter = supportedDegrees.find(angle);
1060 return iter != supportedDegrees.end() ? iter->second : 0;
1061 }
1062
GetRotationFromMatrix(Drawing::Matrix matrix)1063 int RSUniRenderUtil::GetRotationFromMatrix(Drawing::Matrix matrix)
1064 {
1065 Drawing::Matrix::Buffer value;
1066 matrix.GetAll(value);
1067
1068 int rAngle = static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::SKEW_X],
1069 value[Drawing::Matrix::Index::SCALE_X]) * (180 / PI)));
1070 // transfer the result to anti-clockwise degrees
1071 // only rotation with 90°, 180°, 270° are composed through hardware,
1072 // in which situation the transformation of the layer needs to be set.
1073 return TransferToAntiClockwiseDegrees(rAngle);
1074 }
1075
GetRotationDegreeFromMatrix(Drawing::Matrix matrix)1076 int RSUniRenderUtil::GetRotationDegreeFromMatrix(Drawing::Matrix matrix)
1077 {
1078 Drawing::Matrix::Buffer value;
1079 matrix.GetAll(value);
1080 return static_cast<int>(-round(atan2(value[Drawing::Matrix::Index::SKEW_X],
1081 value[Drawing::Matrix::Index::SCALE_X]) * (RS_ROTATION_180 / PI)));
1082 }
1083
GetFloatRotationDegreeFromMatrix(Drawing::Matrix matrix)1084 float RSUniRenderUtil::GetFloatRotationDegreeFromMatrix(Drawing::Matrix matrix)
1085 {
1086 Drawing::Matrix::Buffer value;
1087 matrix.GetAll(value);
1088 return atan2(value[Drawing::Matrix::Index::SKEW_X], value[Drawing::Matrix::Index::SCALE_X]) *
1089 (RS_ROTATION_180 / PI);
1090 }
1091
HasNonZRotationTransform(Drawing::Matrix matrix)1092 bool RSUniRenderUtil::HasNonZRotationTransform(Drawing::Matrix matrix)
1093 {
1094 Drawing::Matrix::Buffer value;
1095 matrix.GetAll(value);
1096 if (!ROSEN_EQ(value[Drawing::Matrix::Index::PERSP_0], 0.f) ||
1097 !ROSEN_EQ(value[Drawing::Matrix::Index::PERSP_1], 0.f)) {
1098 return true;
1099 }
1100 int rotation = static_cast<int>(round(value[Drawing::Matrix::Index::SCALE_X] *
1101 value[Drawing::Matrix::Index::SKEW_Y] +
1102 value[Drawing::Matrix::Index::SCALE_Y] *
1103 value[Drawing::Matrix::Index::SKEW_X]));
1104 if (rotation != 0) {
1105 return true;
1106 }
1107 int vectorZ = value[Drawing::Matrix::Index::SCALE_X] * value[Drawing::Matrix::Index::SCALE_Y] -
1108 value[Drawing::Matrix::Index::SKEW_Y] * value[Drawing::Matrix::Index::SKEW_X];
1109 return vectorZ < 0;
1110 }
1111
SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)1112 void RSUniRenderUtil::SortSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
1113 {
1114 // sort subThreadNodes by priority and z-order
1115 subThreadNodes.sort([](const auto& first, const auto& second) -> bool {
1116 auto node1 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(first);
1117 auto node2 = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(second);
1118 if (node1 == nullptr || node2 == nullptr) {
1119 ROSEN_LOGE(
1120 "RSUniRenderUtil::SortSubThreadNodes sort nullptr found in subThreadNodes, this should not happen");
1121 return false;
1122 }
1123 if (node1->GetPriority() == node2->GetPriority()) {
1124 return node2->GetRenderProperties().GetPositionZ() < node1->GetRenderProperties().GetPositionZ();
1125 } else {
1126 return node1->GetPriority() < node2->GetPriority();
1127 }
1128 });
1129 }
1130
CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>> & oldSubThreadNodes,std::list<std::shared_ptr<RSSurfaceRenderNode>> & subThreadNodes)1131 void RSUniRenderUtil::CacheSubThreadNodes(std::list<std::shared_ptr<RSSurfaceRenderNode>>& oldSubThreadNodes,
1132 std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes)
1133 {
1134 std::unordered_set<std::shared_ptr<RSSurfaceRenderNode>> nodes(subThreadNodes.begin(), subThreadNodes.end());
1135 for (auto node : oldSubThreadNodes) {
1136 if (nodes.count(node) > 0) {
1137 continue;
1138 }
1139 // The node being processed by sub thread may have been removed.
1140 if (node->GetCacheSurfaceProcessedStatus() == CacheProcessStatus::DOING) {
1141 subThreadNodes.emplace_back(node);
1142 }
1143 }
1144 oldSubThreadNodes.clear();
1145 oldSubThreadNodes = subThreadNodes;
1146 }
1147
HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode> & node)1148 void RSUniRenderUtil::HandleHardwareNode(const std::shared_ptr<RSSurfaceRenderNode>& node)
1149 {
1150 if (node == nullptr || !node->HasHardwareNode()) {
1151 return;
1152 }
1153 auto appWindow = node;
1154 if (node->IsLeashWindow()) {
1155 for (auto& child : *node->GetSortedChildren()) {
1156 auto surfaceNodePtr = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1157 if (surfaceNodePtr && surfaceNodePtr->IsAppWindow()) {
1158 appWindow = surfaceNodePtr;
1159 break;
1160 }
1161 }
1162 }
1163 auto hardwareEnabledNodes = appWindow->GetChildHardwareEnabledNodes();
1164 for (auto& hardwareEnabledNode : hardwareEnabledNodes) {
1165 auto hardwareEnabledNodePtr = hardwareEnabledNode.lock();
1166 if (hardwareEnabledNodePtr) {
1167 hardwareEnabledNodePtr->SetHardwareDisabledByCache(false);
1168 }
1169 }
1170 }
1171
ClearCacheSurface(RSRenderNode & node,uint32_t threadIndex,bool isClearCompletedCacheSurface)1172 void RSUniRenderUtil::ClearCacheSurface(RSRenderNode& node, uint32_t threadIndex, bool isClearCompletedCacheSurface)
1173 {
1174 RS_LOGD("ClearCacheSurface node: [%{public}" PRIu64 "]", node.GetId());
1175 uint32_t cacheSurfaceThreadIndex = node.GetCacheSurfaceThreadIndex();
1176 uint32_t completedSurfaceThreadIndex = node.GetCompletedSurfaceThreadIndex();
1177 if (cacheSurfaceThreadIndex == threadIndex && completedSurfaceThreadIndex == threadIndex) {
1178 node.ClearCacheSurface(isClearCompletedCacheSurface);
1179 return;
1180 }
1181 std::shared_ptr<Drawing::Surface> completedCacheSurface = isClearCompletedCacheSurface ?
1182 node.GetCompletedCacheSurface(threadIndex, false, true) : nullptr;
1183 ClearNodeCacheSurface(node.GetCacheSurface(threadIndex, false, true),
1184 std::move(completedCacheSurface), cacheSurfaceThreadIndex, completedSurfaceThreadIndex);
1185 node.ClearCacheSurface(isClearCompletedCacheSurface);
1186 }
1187
ClearNodeCacheSurface(std::shared_ptr<Drawing::Surface> && cacheSurface,std::shared_ptr<Drawing::Surface> && cacheCompletedSurface,uint32_t cacheSurfaceThreadIndex,uint32_t completedSurfaceThreadIndex)1188 void RSUniRenderUtil::ClearNodeCacheSurface(std::shared_ptr<Drawing::Surface>&& cacheSurface,
1189 std::shared_ptr<Drawing::Surface>&& cacheCompletedSurface,
1190 uint32_t cacheSurfaceThreadIndex, uint32_t completedSurfaceThreadIndex)
1191 {
1192 PostReleaseSurfaceTask(std::move(cacheSurface), cacheSurfaceThreadIndex);
1193 PostReleaseSurfaceTask(std::move(cacheCompletedSurface), completedSurfaceThreadIndex);
1194 }
1195
PostReleaseSurfaceTask(std::shared_ptr<Drawing::Surface> && surface,uint32_t threadIndex)1196 void RSUniRenderUtil::PostReleaseSurfaceTask(std::shared_ptr<Drawing::Surface>&& surface, uint32_t threadIndex)
1197 {
1198 if (surface == nullptr) {
1199 return;
1200 }
1201
1202 if (threadIndex == UNI_MAIN_THREAD_INDEX || threadIndex == UNI_RENDER_THREAD_INDEX) {
1203 if (RSUniRenderJudgement::IsUniRender()) {
1204 auto instance = &(RSUniRenderThread::Instance());
1205 instance->AddToReleaseQueue(std::move(surface));
1206 instance->PostTask(([instance] () { instance->ReleaseSurface(); }),
1207 RELEASE_SURFACE_TASK, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1208 } else {
1209 auto instance = RSMainThread::Instance();
1210 instance->AddToReleaseQueue(std::move(surface));
1211 instance->PostTask(([instance] () { instance->ReleaseSurface(); }),
1212 RELEASE_SURFACE_TASK, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
1213 }
1214 } else {
1215 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1216 auto instance = RSSubThreadManager::Instance();
1217 instance->AddToReleaseQueue(std::move(surface), threadIndex);
1218 instance->ReleaseSurface(threadIndex);
1219 #endif
1220 }
1221 }
1222
DrawRectForDfx(RSPaintFilterCanvas & canvas,const RectI & rect,Drawing::Color color,float alpha,const std::string & extraInfo)1223 void RSUniRenderUtil::DrawRectForDfx(RSPaintFilterCanvas& canvas, const RectI& rect, Drawing::Color color,
1224 float alpha, const std::string& extraInfo)
1225 {
1226 if (rect.width_ <= 0 || rect.height_ <= 0) {
1227 RS_LOGD("DrawRectForDfx rect is invalid.");
1228 return;
1229 }
1230 RS_LOGD("DrawRectForDfx current rect = %{public}s", rect.ToString().c_str());
1231 auto dstRect = Drawing::Rect(rect.left_, rect.top_,
1232 rect.left_ + rect.width_, rect.top_ + rect.height_);
1233
1234 std::string position = rect.ToString() + extraInfo;
1235
1236 const int defaultTextOffsetX = 6; // text position is 6 pixelSize right side of the Rect
1237 const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the Rect
1238 Drawing::Brush rectBrush;
1239 std::shared_ptr<Drawing::Typeface> typeFace = nullptr;
1240
1241 // font size: 24
1242 std::shared_ptr<Drawing::TextBlob> textBlob =
1243 Drawing::TextBlob::MakeFromString(position.c_str(), Drawing::Font(typeFace, 24.0f, 1.0f, 0.0f));
1244
1245 rectBrush.SetColor(color);
1246 rectBrush.SetAntiAlias(true);
1247 rectBrush.SetAlphaF(alpha);
1248 canvas.AttachBrush(rectBrush);
1249 canvas.DrawRect(dstRect);
1250 canvas.DetachBrush();
1251 canvas.AttachBrush(Drawing::Brush());
1252 canvas.DrawTextBlob(textBlob.get(), rect.left_ + defaultTextOffsetX, rect.top_ + defaultTextOffsetY);
1253 canvas.DetachBrush();
1254 }
1255
1256 #ifdef RS_ENABLE_VK
FindMemoryType(uint32_t typeFilter,VkMemoryPropertyFlags properties)1257 uint32_t RSUniRenderUtil::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
1258 {
1259 if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
1260 OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
1261 return UINT32_MAX;
1262 }
1263 auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton().GetRsVulkanInterface();
1264 VkPhysicalDevice physicalDevice = vkContext.GetPhysicalDevice();
1265
1266 VkPhysicalDeviceMemoryProperties memProperties;
1267 vkContext.vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
1268
1269 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
1270 if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
1271 return i;
1272 }
1273 }
1274
1275 return UINT32_MAX;
1276 }
1277
SetVkImageInfo(std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo,const VkImageCreateInfo & imageInfo)1278 void RSUniRenderUtil::SetVkImageInfo(std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo,
1279 const VkImageCreateInfo& imageInfo)
1280 {
1281 if (vkImageInfo == nullptr) {
1282 return;
1283 }
1284 vkImageInfo->imageTiling = imageInfo.tiling;
1285 vkImageInfo->imageLayout = imageInfo.initialLayout;
1286 vkImageInfo->format = imageInfo.format;
1287 vkImageInfo->imageUsageFlags = imageInfo.usage;
1288 vkImageInfo->levelCount = imageInfo.mipLevels;
1289 vkImageInfo->currentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
1290 vkImageInfo->ycbcrConversionInfo = {};
1291 vkImageInfo->sharingMode = imageInfo.sharingMode;
1292 }
1293
MakeBackendTexture(uint32_t width,uint32_t height,VkFormat format)1294 Drawing::BackendTexture RSUniRenderUtil::MakeBackendTexture(uint32_t width, uint32_t height, VkFormat format)
1295 {
1296 VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
1297 VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
1298 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1299 VkImageCreateInfo imageInfo {
1300 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
1301 .pNext = nullptr,
1302 .flags = 0,
1303 .imageType = VK_IMAGE_TYPE_2D,
1304 .format = format,
1305 .extent = {width, height, 1},
1306 .mipLevels = 1,
1307 .arrayLayers = 1,
1308 .samples = VK_SAMPLE_COUNT_1_BIT,
1309 .tiling = tiling,
1310 .usage = usage,
1311 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1312 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
1313 };
1314
1315 auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton().GetRsVulkanInterface();
1316 VkDevice device = vkContext.GetDevice();
1317 VkImage image = VK_NULL_HANDLE;
1318 VkDeviceMemory memory = VK_NULL_HANDLE;
1319
1320 if (width * height > OHOS::Rosen::NativeBufferUtils::VKIMAGE_LIMIT_SIZE) {
1321 ROSEN_LOGE(
1322 "RSUniRenderUtil::MakeBackendTexture failed, image is too large, width:%{public}u, height::%{public}u",
1323 width, height);
1324 return {};
1325 }
1326
1327 if (vkContext.vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
1328 return {};
1329 }
1330
1331 VkMemoryRequirements memRequirements;
1332 vkContext.vkGetImageMemoryRequirements(device, image, &memRequirements);
1333
1334 VkMemoryAllocateInfo allocInfo{};
1335 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
1336 allocInfo.allocationSize = memRequirements.size;
1337 allocInfo.memoryTypeIndex = FindMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
1338 if (allocInfo.memoryTypeIndex == UINT32_MAX) {
1339 return {};
1340 }
1341
1342 if (vkContext.vkAllocateMemory(device, &allocInfo, nullptr, &memory) != VK_SUCCESS) {
1343 return {};
1344 }
1345
1346 vkContext.vkBindImageMemory(device, image, memory, 0);
1347
1348 OHOS::Rosen::Drawing::BackendTexture backendTexture(true);
1349 OHOS::Rosen::Drawing::TextureInfo textureInfo;
1350 textureInfo.SetWidth(width);
1351 textureInfo.SetHeight(height);
1352
1353 std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo =
1354 std::make_shared<OHOS::Rosen::Drawing::VKTextureInfo>();
1355 vkImageInfo->vkImage = image;
1356 vkImageInfo->vkAlloc.memory = memory;
1357 vkImageInfo->vkAlloc.size = memRequirements.size;
1358
1359 SetVkImageInfo(vkImageInfo, imageInfo);
1360 textureInfo.SetVKTextureInfo(vkImageInfo);
1361 backendTexture.SetTextureInfo(textureInfo);
1362 return backendTexture;
1363 }
1364 #endif
1365
GetRotateTransformForRotationFixed(RSSurfaceRenderNode & node,sptr<IConsumerSurface> consumer)1366 GraphicTransformType RSUniRenderUtil::GetRotateTransformForRotationFixed(RSSurfaceRenderNode& node,
1367 sptr<IConsumerSurface> consumer)
1368 {
1369 auto transformType = RSBaseRenderUtil::GetRotateTransform(RSBaseRenderUtil::GetSurfaceBufferTransformType(
1370 node.GetRSSurfaceHandler()->GetConsumer(), node.GetRSSurfaceHandler()->GetBuffer()));
1371 int extraRotation = 0;
1372 int degree = static_cast<int>(round(node.GetAbsRotation()));
1373 auto surfaceParams = node.GetStagingRenderParams() == nullptr
1374 ? nullptr
1375 : static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
1376 int32_t rotationDegree = RSBaseRenderUtil::GetScreenRotationOffset(surfaceParams);
1377 extraRotation = (degree - rotationDegree) % ROUND_ANGLE;
1378 transformType = static_cast<GraphicTransformType>(
1379 (transformType + extraRotation / RS_ROTATION_90 + SCREEN_ROTATION_NUM) % SCREEN_ROTATION_NUM);
1380 return transformType;
1381 }
1382
UpdateRealSrcRect(RSSurfaceRenderNode & node,const RectI & absRect)1383 void RSUniRenderUtil::UpdateRealSrcRect(RSSurfaceRenderNode& node, const RectI& absRect)
1384 {
1385 auto surfaceHandler = node.GetRSSurfaceHandler();
1386 auto consumer = surfaceHandler->GetConsumer();
1387 auto buffer = surfaceHandler->GetBuffer();
1388 if (!consumer || !buffer) {
1389 return;
1390 }
1391 auto bufferRotateTransformType = node.GetFixRotationByUser() ?
1392 RSUniRenderUtil::GetRotateTransformForRotationFixed(node, consumer) :
1393 RSBaseRenderUtil::GetRotateTransform(RSBaseRenderUtil::GetSurfaceBufferTransformType(consumer, buffer));
1394 const auto& property = node.GetRenderProperties();
1395 auto bufferWidth = buffer->GetSurfaceBufferWidth();
1396 auto bufferHeight = buffer->GetSurfaceBufferHeight();
1397 const auto boundsWidth = property.GetBoundsWidth();
1398 const auto boundsHeight = property.GetBoundsHeight();
1399 auto srcRect = node.GetSrcRect();
1400 if (bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1401 bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
1402 std::swap(bufferWidth, bufferHeight);
1403 }
1404 if ((bufferWidth != boundsWidth || bufferHeight != boundsHeight) &&
1405 node.GetRenderProperties().GetFrameGravity() != Gravity::TOP_LEFT) {
1406 float xScale = (ROSEN_EQ(boundsWidth, 0.0f) ? 1.0f : bufferWidth / boundsWidth);
1407 float yScale = (ROSEN_EQ(boundsHeight, 0.0f) ? 1.0f : bufferHeight / boundsHeight);
1408 if (absRect == node.GetDstRect()) {
1409 // If the SurfaceRenderNode is completely in the DisplayRenderNode,
1410 // we do not need to crop the buffer.
1411 srcRect.width_ = bufferWidth;
1412 srcRect.height_ = bufferHeight;
1413 } else {
1414 srcRect.left_ = srcRect.left_ * xScale;
1415 srcRect.top_ = srcRect.top_ * yScale;
1416 srcRect.width_ = std::min(static_cast<int32_t>(std::ceil(srcRect.width_ * xScale)), bufferWidth);
1417 srcRect.height_ = std::min(static_cast<int32_t>(std::ceil(srcRect.height_ * yScale)), bufferHeight);
1418 }
1419 }
1420 RectI bufferRect(0, 0, bufferWidth, bufferHeight);
1421 RectI calibratedSrcRect = srcRect.IntersectRect(bufferRect);
1422 if (bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1423 bufferRotateTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
1424 std::swap(calibratedSrcRect.left_, calibratedSrcRect.top_);
1425 std::swap(calibratedSrcRect.width_, calibratedSrcRect.height_);
1426 }
1427 auto newSrcRect = SrcRectRotateTransform(*buffer, bufferRotateTransformType, calibratedSrcRect);
1428 node.SetSrcRect(newSrcRect);
1429 }
1430
GetConsumerTransform(const RSSurfaceRenderNode & node,const sptr<SurfaceBuffer> buffer,const sptr<IConsumerSurface> consumer)1431 GraphicTransformType RSUniRenderUtil::GetConsumerTransform(const RSSurfaceRenderNode& node,
1432 const sptr<SurfaceBuffer> buffer, const sptr<IConsumerSurface> consumer)
1433 {
1434 auto transformType = GraphicTransformType::GRAPHIC_ROTATE_NONE;
1435 if (consumer != nullptr && buffer != nullptr) {
1436 if (consumer->GetSurfaceBufferTransformType(buffer, &transformType) != GSERROR_OK) {
1437 RS_LOGE("RSUniRenderUtil::GetConsumerTransform GetSurfaceBufferTransformType failed");
1438 }
1439 }
1440 GraphicTransformType consumerTransform = RSBaseRenderUtil::GetRotateTransform(transformType);
1441 return consumerTransform;
1442 }
1443
CalcSrcRectByBufferFlip(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1444 void RSUniRenderUtil::CalcSrcRectByBufferFlip(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1445 {
1446 auto surfaceHandler = node.GetRSSurfaceHandler();
1447 auto consumer = surfaceHandler->GetConsumer();
1448 auto buffer = surfaceHandler->GetBuffer();
1449 if (!consumer || !buffer) {
1450 return;
1451 }
1452 const auto bufferWidth = buffer->GetSurfaceBufferWidth();
1453 const auto bufferHeight = buffer->GetSurfaceBufferHeight();
1454 const auto dstRect = node.GetDstRect();
1455 RectI srcRect = node.GetSrcRect();
1456 auto bufferFlipTransformType =
1457 RSBaseRenderUtil::GetFlipTransform(RSBaseRenderUtil::GetSurfaceBufferTransformType(consumer, buffer));
1458 switch (bufferFlipTransformType) {
1459 case GraphicTransformType::GRAPHIC_FLIP_H: {
1460 if (srcRect.left_ >= 0) {
1461 srcRect.left_ = bufferWidth - srcRect.left_ - srcRect.width_;
1462 } else if (dstRect.left_ + dstRect.width_ >= static_cast<int32_t>(screenInfo.width)) {
1463 srcRect.left_ = bufferWidth - srcRect.width_;
1464 }
1465 break;
1466 }
1467 case GraphicTransformType::GRAPHIC_FLIP_V: {
1468 if (srcRect.top_ >= 0) {
1469 srcRect.top_ = bufferHeight - srcRect.top_ - srcRect.height_;
1470 } else if (dstRect.top_ + dstRect.height_ >= static_cast<int32_t>(screenInfo.height)) {
1471 srcRect.top_ = bufferHeight - srcRect.height_;
1472 }
1473 break;
1474 }
1475 default:
1476 break;
1477 }
1478 node.SetSrcRect(srcRect);
1479 }
1480
SrcRectRotateTransform(const SurfaceBuffer & buffer,const GraphicTransformType bufferRotateTransformType,const RectI & newSrcRect)1481 RectI RSUniRenderUtil::SrcRectRotateTransform(const SurfaceBuffer& buffer,
1482 const GraphicTransformType bufferRotateTransformType, const RectI& newSrcRect)
1483 {
1484 const auto bufferWidth = buffer.GetSurfaceBufferWidth();
1485 const auto bufferHeight = buffer.GetSurfaceBufferHeight();
1486 int left = newSrcRect.GetLeft();
1487 int top = newSrcRect.GetTop();
1488 int width = newSrcRect.GetWidth();
1489 int height = newSrcRect.GetHeight();
1490 RectI srcRect(newSrcRect);
1491 switch (bufferRotateTransformType) {
1492 case GraphicTransformType::GRAPHIC_ROTATE_90: {
1493 srcRect = RectI {bufferWidth - width - left, top, width, height};
1494 break;
1495 }
1496 case GraphicTransformType::GRAPHIC_ROTATE_180: {
1497 srcRect = RectI {bufferWidth - width - left, bufferHeight - height - top, width, height};
1498 break;
1499 }
1500 case GraphicTransformType::GRAPHIC_ROTATE_270: {
1501 srcRect = RectI {left, bufferHeight - height - top, width, height};
1502 break;
1503 }
1504 default:
1505 break;
1506 }
1507 return srcRect;
1508 }
1509
CalcSrcRectByBufferRotation(const SurfaceBuffer & buffer,const GraphicTransformType consumerTransformType,Drawing::Rect newSrcRect)1510 Drawing::Rect RSUniRenderUtil::CalcSrcRectByBufferRotation(const SurfaceBuffer& buffer,
1511 const GraphicTransformType consumerTransformType, Drawing::Rect newSrcRect)
1512 {
1513 const float frameWidth = buffer.GetSurfaceBufferWidth();
1514 const float frameHeight = buffer.GetSurfaceBufferHeight();
1515 int left = std::clamp<int>(newSrcRect.GetLeft(), 0, frameWidth);
1516 int top = std::clamp<int>(newSrcRect.GetTop(), 0, frameHeight);
1517 int width = std::clamp<int>(newSrcRect.GetWidth(), 0, frameWidth - left);
1518 int height = std::clamp<int>(newSrcRect.GetHeight(), 0, frameHeight - top);
1519 switch (consumerTransformType) {
1520 case GraphicTransformType::GRAPHIC_ROTATE_NONE: {
1521 newSrcRect = Drawing::Rect(left, top, left + width, top + height);
1522 break;
1523 }
1524 case GraphicTransformType::GRAPHIC_ROTATE_90: {
1525 newSrcRect = Drawing::Rect(frameWidth - width - left, top, frameWidth - left, top + height);
1526 break;
1527 }
1528 case GraphicTransformType::GRAPHIC_ROTATE_180: {
1529 newSrcRect = Drawing::Rect(frameWidth - width - left, frameHeight - height - top,
1530 frameWidth - left, frameHeight - top);
1531 break;
1532 }
1533 case GraphicTransformType::GRAPHIC_ROTATE_270: {
1534 newSrcRect = Drawing::Rect(left, frameHeight - height - top, left + width, frameHeight - top);
1535 break;
1536 }
1537 default:
1538 break;
1539 }
1540 return newSrcRect;
1541 }
1542
IsHwcEnabledByGravity(RSSurfaceRenderNode & node,const Gravity frameGravity)1543 bool RSUniRenderUtil::IsHwcEnabledByGravity(RSSurfaceRenderNode& node, const Gravity frameGravity)
1544 {
1545 // When renderfit mode is not Gravity::RESIZE or Gravity::TOP_LEFT,
1546 // we currently disable hardware composer.
1547 if (frameGravity != Gravity::RESIZE && frameGravity != Gravity::TOP_LEFT) {
1548 RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: name:%s id:%" PRIu64 "disabled by frameGravity[%d]",
1549 node.GetName().c_str(), node.GetId(), static_cast<int>(frameGravity));
1550 node.SetHardwareForcedDisabledState(true);
1551 return false;
1552 }
1553 return true;
1554 }
1555
DealWithNodeGravity(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix)1556 void RSUniRenderUtil::DealWithNodeGravity(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix)
1557 {
1558 auto surfaceHandler = node.GetRSSurfaceHandler();
1559 if (!surfaceHandler) {
1560 return;
1561 }
1562 const auto buffer = surfaceHandler->GetBuffer();
1563 const auto consumer = surfaceHandler->GetConsumer();
1564 if (!consumer || !buffer) {
1565 return;
1566 }
1567 float bufferWidth = buffer->GetSurfaceBufferWidth();
1568 float bufferHeight = buffer->GetSurfaceBufferHeight();
1569 const float boundsWidth = node.GetRenderProperties().GetBoundsWidth();
1570 const float boundsHeight = node.GetRenderProperties().GetBoundsHeight();
1571 const Gravity frameGravity = node.GetRenderProperties().GetFrameGravity();
1572 const GraphicTransformType consumerTransformType = node.GetFixRotationByUser() ?
1573 GetRotateTransformForRotationFixed(node, consumer) : GetConsumerTransform(node, buffer, consumer);
1574 CheckForceHardwareAndUpdateDstRect(node);
1575 if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1576 consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
1577 std::swap(bufferWidth, bufferHeight);
1578 }
1579 Drawing::Matrix gravityMatrix;
1580 RSPropertiesPainter::GetGravityMatrix(frameGravity,
1581 {0.f, 0.f, boundsWidth, boundsHeight}, bufferWidth, bufferHeight, gravityMatrix);
1582 Drawing::Matrix inverseTotalMatrix;
1583 Drawing::Matrix inverseGravityMatrix;
1584 // We don't have to do additional works when renderfit mode is Gravity::RESIZE or frameSize == boundsSize.
1585 if (frameGravity == Gravity::RESIZE ||
1586 (ROSEN_EQ(bufferWidth, boundsWidth) && ROSEN_EQ(bufferHeight, boundsHeight)) ||
1587 !totalMatrix.Invert(inverseTotalMatrix) || !gravityMatrix.Invert(inverseGravityMatrix) ||
1588 !IsHwcEnabledByGravity(node, frameGravity)) {
1589 return;
1590 }
1591 Drawing::Rect bound = Drawing::Rect(0.f, 0.f, boundsWidth, boundsHeight);
1592 Drawing::Rect frame = Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight);
1593 Drawing::Rect localIntersectRect;
1594 gravityMatrix.MapRect(localIntersectRect, frame);
1595 localIntersectRect.Intersect(bound);
1596 Drawing::Rect absIntersectRect;
1597 totalMatrix.MapRect(absIntersectRect, localIntersectRect);
1598 const RectI dstRect = node.GetDstRect();
1599 Drawing::Rect newDstRect(dstRect.left_, dstRect.top_, dstRect.GetRight(), dstRect.GetBottom());
1600 newDstRect.Intersect(absIntersectRect);
1601 node.SetDstRect({std::floor(newDstRect.GetLeft()), std::floor(newDstRect.GetTop()),
1602 std::ceil(newDstRect.GetWidth()), std::ceil(newDstRect.GetHeight())});
1603 Drawing::Rect newSrcRect;
1604 inverseTotalMatrix.MapRect(newSrcRect, newDstRect);
1605 inverseGravityMatrix.MapRect(newSrcRect, newSrcRect);
1606 if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1607 consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
1608 std::swap(newSrcRect.left_, newSrcRect.top_);
1609 std::swap(newSrcRect.right_, newSrcRect.bottom_);
1610 }
1611 newSrcRect = CalcSrcRectByBufferRotation(*buffer, consumerTransformType, newSrcRect);
1612 node.SetSrcRect({newSrcRect.GetLeft(), newSrcRect.GetTop(), newSrcRect.GetWidth(), newSrcRect.GetHeight()});
1613 }
1614
DealWithNodeGravityOldVersion(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1615 void RSUniRenderUtil::DealWithNodeGravityOldVersion(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1616 {
1617 auto buffer = node.GetRSSurfaceHandler()->GetBuffer();
1618 if (!buffer) {
1619 return;
1620 }
1621 const auto& property = node.GetRenderProperties();
1622 const float frameWidth = buffer->GetSurfaceBufferWidth();
1623 const float frameHeight = buffer->GetSurfaceBufferHeight();
1624 const float boundsWidth = property.GetBoundsWidth();
1625 const float boundsHeight = property.GetBoundsHeight();
1626 const Gravity frameGravity = property.GetFrameGravity();
1627
1628 CheckForceHardwareAndUpdateDstRect(node);
1629 // we do not need to do additional works for Gravity::RESIZE and if frameSize == boundsSize.
1630 if (frameGravity == Gravity::RESIZE || (ROSEN_EQ(frameWidth, boundsWidth) && ROSEN_EQ(frameHeight, boundsHeight)) ||
1631 frameGravity == Gravity::TOP_LEFT) {
1632 return;
1633 }
1634
1635 // get current node's translate matrix and calculate gravity matrix.
1636 auto translateMatrix = Drawing::Matrix();
1637 translateMatrix.Translate(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_X),
1638 std::ceil(node.GetTotalMatrix().Get(Drawing::Matrix::Index::TRANS_Y)));
1639 Drawing::Matrix gravityMatrix;
1640 (void)RSPropertiesPainter::GetGravityMatrix(frameGravity,
1641 RectF {0.0f, 0.0f, boundsWidth, boundsHeight}, frameWidth, frameHeight, gravityMatrix);
1642 // create a canvas to calculate new dstRect and new srcRect
1643 int32_t screenWidth = screenInfo.phyWidth;
1644 int32_t screenHeight = screenInfo.phyHeight;
1645 const auto screenRotation = screenInfo.rotation;
1646 if (screenRotation == ScreenRotation::ROTATION_90 || screenRotation == ScreenRotation::ROTATION_270) {
1647 std::swap(screenWidth, screenHeight);
1648 }
1649
1650 auto canvas = std::make_unique<Drawing::Canvas>(screenWidth, screenHeight);
1651 canvas->ConcatMatrix(translateMatrix);
1652 canvas->ConcatMatrix(gravityMatrix);
1653 Drawing::Rect clipRect;
1654 gravityMatrix.MapRect(clipRect, Drawing::Rect(0, 0, frameWidth, frameHeight));
1655 canvas->ClipRect(Drawing::Rect(0, 0, clipRect.GetWidth(), clipRect.GetHeight()), Drawing::ClipOp::INTERSECT);
1656 Drawing::RectI newDstRect = canvas->GetDeviceClipBounds();
1657 auto dstRect = node.GetDstRect();
1658 // we make the newDstRect as the intersection of new and old dstRect,
1659 // to deal with the situation that frameSize > boundsSize.
1660 newDstRect.Intersect(Drawing::RectI(
1661 dstRect.left_, dstRect.top_, dstRect.width_ + dstRect.left_, dstRect.height_ + dstRect.top_));
1662 auto localRect = canvas->GetLocalClipBounds();
1663 int left = std::clamp<int>(localRect.GetLeft(), 0, frameWidth);
1664 int top = std::clamp<int>(localRect.GetTop(), 0, frameHeight);
1665 int width = std::clamp<int>(localRect.GetWidth(), 0, frameWidth - left);
1666 int height = std::clamp<int>(localRect.GetHeight(), 0, frameHeight - top);
1667
1668 node.SetDstRect({newDstRect.GetLeft(), newDstRect.GetTop(), newDstRect.GetWidth(), newDstRect.GetHeight()});
1669 node.SetSrcRect({left, top, width, height});
1670 }
1671
CheckForceHardwareAndUpdateDstRect(RSSurfaceRenderNode & node)1672 void RSUniRenderUtil::CheckForceHardwareAndUpdateDstRect(RSSurfaceRenderNode& node)
1673 {
1674 auto surfaceHandler = node.GetRSSurfaceHandler();
1675 if (!surfaceHandler->GetConsumer() || !node.IsInFixedRotation() || !surfaceHandler->GetBuffer()) {
1676 return;
1677 }
1678 node.SetSrcRect(node.GetOriginalSrcRect());
1679 auto dstRect = node.GetDstRect();
1680 auto originalDstRect = node.GetOriginalDstRect();
1681 dstRect.left_ += (dstRect.width_ - originalDstRect.width_) / 2;
1682 dstRect.top_ += (dstRect.height_ - originalDstRect.height_) / 2;
1683 dstRect.width_ = originalDstRect.width_;
1684 dstRect.height_ = originalDstRect.height_;
1685 node.SetDstRect(dstRect);
1686 }
1687
LayerRotate(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1688 void RSUniRenderUtil::LayerRotate(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1689 {
1690 const auto screenWidth = static_cast<int32_t>(screenInfo.width);
1691 const auto screenHeight = static_cast<int32_t>(screenInfo.height);
1692 const auto screenRotation = screenInfo.rotation;
1693 const auto rect = node.GetDstRect();
1694 switch (screenRotation) {
1695 case ScreenRotation::ROTATION_90: {
1696 node.SetDstRect({rect.top_, screenHeight - rect.left_ - rect.width_, rect.height_, rect.width_});
1697 break;
1698 }
1699 case ScreenRotation::ROTATION_180: {
1700 node.SetDstRect({screenWidth - rect.left_ - rect.width_, screenHeight - rect.top_ - rect.height_,
1701 rect.width_, rect.height_});
1702 break;
1703 }
1704 case ScreenRotation::ROTATION_270: {
1705 node.SetDstRect({screenWidth - rect.top_ - rect.height_, rect.left_, rect.height_, rect.width_});
1706 break;
1707 }
1708 default: {
1709 break;
1710 }
1711 }
1712 }
1713
GetLayerTransform(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1714 GraphicTransformType RSUniRenderUtil::GetLayerTransform(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1715 {
1716 auto surfaceHandler = node.GetRSSurfaceHandler();
1717 if (!surfaceHandler) {
1718 return GraphicTransformType::GRAPHIC_ROTATE_NONE;
1719 }
1720 auto consumer = surfaceHandler->GetConsumer();
1721 auto surfaceParams = node.GetStagingRenderParams() == nullptr
1722 ? nullptr
1723 : static_cast<RSSurfaceRenderParams*>(node.GetStagingRenderParams().get());
1724 int32_t rotationDegree = RSBaseRenderUtil::GetScreenRotationOffset(surfaceParams);
1725 int surfaceNodeRotation = 0;
1726 if (node.GetFixRotationByUser()) {
1727 surfaceNodeRotation = -1 * rotationDegree;
1728 } else {
1729 surfaceNodeRotation =
1730 TransferToAntiClockwiseDegrees(static_cast<int>(round(node.GetAbsRotation())) % ROUND_ANGLE);
1731 }
1732 auto transformType = GraphicTransformType::GRAPHIC_ROTATE_NONE;
1733 auto buffer = node.GetRSSurfaceHandler()->GetBuffer();
1734 if (consumer != nullptr && buffer != nullptr) {
1735 if (consumer->GetSurfaceBufferTransformType(buffer, &transformType) != GSERROR_OK) {
1736 RS_LOGE("RSUniRenderUtil::GetLayerTransform GetSurfaceBufferTransformType failed");
1737 }
1738 }
1739 int consumerTransform = RSBaseRenderUtil::RotateEnumToInt(RSBaseRenderUtil::GetRotateTransform(transformType));
1740 GraphicTransformType consumerFlip = RSBaseRenderUtil::GetFlipTransform(transformType);
1741 int totalRotation =
1742 (RSBaseRenderUtil::RotateEnumToInt(screenInfo.rotation) + surfaceNodeRotation + consumerTransform + 360) % 360;
1743 GraphicTransformType rotateEnum = RSBaseRenderUtil::RotateEnumToInt(totalRotation, consumerFlip);
1744
1745 RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderUtil::GetLayerTransform nodeId:[%llu] fixRotationByUser:[%s] "
1746 "surfaceNodeRotation:[%d] consumerTransform:[%d] rotateEnum:[%d]",
1747 node.GetId(), std::to_string(node.GetFixRotationByUser()).c_str(),
1748 surfaceNodeRotation, consumerTransform, rotateEnum);
1749
1750 return rotateEnum;
1751 }
1752
LayerCrop(RSSurfaceRenderNode & node,const ScreenInfo & screenInfo)1753 void RSUniRenderUtil::LayerCrop(RSSurfaceRenderNode& node, const ScreenInfo& screenInfo)
1754 {
1755 auto dstRect = node.GetDstRect();
1756 auto srcRect = node.GetSrcRect();
1757 auto originSrcRect = srcRect;
1758
1759 RectI dstRectI(dstRect.left_, dstRect.top_, dstRect.width_, dstRect.height_);
1760 int32_t screenWidth = static_cast<int32_t>(screenInfo.phyWidth);
1761 int32_t screenHeight = static_cast<int32_t>(screenInfo.phyHeight);
1762 RectI screenRectI(0, 0, screenWidth, screenHeight);
1763 RectI resDstRect = dstRectI.IntersectRect(screenRectI);
1764 if (resDstRect == dstRectI) {
1765 return;
1766 }
1767 if (node.IsInFixedRotation()) {
1768 node.SetDstRect(resDstRect);
1769 return;
1770 }
1771 dstRect = {resDstRect.left_, resDstRect.top_, resDstRect.width_, resDstRect.height_};
1772 srcRect.left_ = (resDstRect.IsEmpty() || dstRectI.IsEmpty()) ? 0 : std::ceil((resDstRect.left_ - dstRectI.left_) *
1773 originSrcRect.width_ / dstRectI.width_);
1774 srcRect.top_ = (resDstRect.IsEmpty() || dstRectI.IsEmpty()) ? 0 : std::ceil((resDstRect.top_ - dstRectI.top_) *
1775 originSrcRect.height_ / dstRectI.height_);
1776 srcRect.width_ = dstRectI.IsEmpty() ? 0 : originSrcRect.width_ * resDstRect.width_ / dstRectI.width_;
1777 srcRect.height_ = dstRectI.IsEmpty() ? 0 : originSrcRect.height_ * resDstRect.height_ / dstRectI.height_;
1778 node.SetDstRect(dstRect);
1779 node.SetSrcRect(srcRect);
1780 }
1781
IsHwcEnabledByScalingMode(RSSurfaceRenderNode & node,const ScalingMode scalingMode)1782 bool RSUniRenderUtil::IsHwcEnabledByScalingMode(RSSurfaceRenderNode& node, const ScalingMode scalingMode)
1783 {
1784 // We temporarily disabled HWC when scalingMode is freeze or no_scale_crop
1785 if (scalingMode == ScalingMode::SCALING_MODE_FREEZE || scalingMode == ScalingMode::SCALING_MODE_NO_SCALE_CROP) {
1786 RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: name:%s id:%" PRIu64 "disabled by scalingMode[%d]",
1787 node.GetName().c_str(), node.GetId(), static_cast<int>(scalingMode));
1788 node.SetHardwareForcedDisabledState(true);
1789 return false;
1790 }
1791 return true;
1792 }
1793
DealWithScalingMode(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix)1794 void RSUniRenderUtil::DealWithScalingMode(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix)
1795 {
1796 auto surfaceHandler = node.GetRSSurfaceHandler();
1797 if (!surfaceHandler) {
1798 return;
1799 }
1800 const auto buffer = surfaceHandler->GetBuffer();
1801 const auto consumer = surfaceHandler->GetConsumer();
1802 if (!consumer || !buffer) {
1803 return;
1804 }
1805 float bufferWidth = buffer->GetSurfaceBufferWidth();
1806 float bufferHeight = buffer->GetSurfaceBufferHeight();
1807 const float boundsWidth = node.GetRenderProperties().GetBoundsWidth();
1808 const float boundsHeight = node.GetRenderProperties().GetBoundsHeight();
1809 const GraphicTransformType consumerTransformType = node.GetFixRotationByUser() ?
1810 GetRotateTransformForRotationFixed(node, consumer) : GetConsumerTransform(node, buffer, consumer);
1811 const Gravity frameGravity = node.GetRenderProperties().GetFrameGravity();
1812 const ScalingMode scalingMode = buffer->GetSurfaceBufferScalingMode();
1813 if (scalingMode == ScalingMode::SCALING_MODE_SCALE_TO_WINDOW || !IsHwcEnabledByScalingMode(node, scalingMode) ||
1814 !IsHwcEnabledByGravity(node, frameGravity)) {
1815 return;
1816 }
1817 if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1818 consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
1819 std::swap(bufferWidth, bufferHeight);
1820 }
1821 Drawing::Matrix gravityMatrix;
1822 RSPropertiesPainter::GetGravityMatrix(frameGravity,
1823 {0.f, 0.f, boundsWidth, boundsHeight}, bufferWidth, bufferHeight, gravityMatrix);
1824 Drawing::Matrix rawScalingModeMatrix;
1825 RSPropertiesPainter::GetScalingModeMatrix(scalingMode,
1826 {0.f, 0.f, boundsWidth, boundsHeight}, bufferWidth, bufferHeight, rawScalingModeMatrix);
1827 Drawing::Rect rawSrcRect;
1828 rawScalingModeMatrix.MapRect(rawSrcRect, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
1829 float xScale = ROSEN_EQ(boundsWidth, 0.f) ? 1.0f : rawSrcRect.GetWidth() / boundsWidth;
1830 float yScale = ROSEN_EQ(boundsHeight, 0.f) ? 1.0f : rawSrcRect.GetHeight() / boundsHeight;
1831 Drawing::Matrix scalingModeMatrix;
1832 scalingModeMatrix.PostScale(xScale, yScale);
1833 Drawing::Rect adjustedSrcRect;
1834 scalingModeMatrix.MapRect(adjustedSrcRect, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
1835 float xTranslate = (bufferWidth - adjustedSrcRect.GetWidth()) / 2.0f;
1836 float yTranslate = (bufferHeight - adjustedSrcRect.GetHeight()) / 2.0f;
1837 scalingModeMatrix.PostTranslate(xTranslate, yTranslate);
1838 UpdateHwcNodeByScalingMode(node, totalMatrix, gravityMatrix, scalingModeMatrix);
1839 }
1840
UpdateHwcNodeByScalingMode(RSSurfaceRenderNode & node,const Drawing::Matrix & totalMatrix,const Drawing::Matrix & gravityMatrix,const Drawing::Matrix & scalingModeMatrix)1841 void RSUniRenderUtil::UpdateHwcNodeByScalingMode(RSSurfaceRenderNode& node, const Drawing::Matrix& totalMatrix,
1842 const Drawing::Matrix& gravityMatrix, const Drawing::Matrix& scalingModeMatrix)
1843 {
1844 auto surfaceHandler = node.GetRSSurfaceHandler();
1845 const auto& property = node.GetRenderProperties();
1846 const auto buffer = surfaceHandler->GetBuffer();
1847 const auto consumer = surfaceHandler->GetConsumer();
1848 float bufferWidth = buffer->GetSurfaceBufferWidth();
1849 float bufferHeight = buffer->GetSurfaceBufferHeight();
1850 const GraphicTransformType consumerTransformType = node.GetFixRotationByUser() ?
1851 GetRotateTransformForRotationFixed(node, consumer) : GetConsumerTransform(node, buffer, consumer);
1852 Drawing::Matrix inverseScalingModeMatrix;
1853 Drawing::Matrix inverseGravityMatrix;
1854 Drawing::Matrix inverseTotalMatrix;
1855 if (!totalMatrix.Invert(inverseTotalMatrix) || !scalingModeMatrix.Invert(inverseScalingModeMatrix) ||
1856 !gravityMatrix.Invert(inverseGravityMatrix)) {
1857 return;
1858 }
1859 if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1860 consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
1861 std::swap(bufferWidth, bufferHeight);
1862 }
1863 Drawing::Rect newDstRect;
1864 scalingModeMatrix.MapRect(newDstRect, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
1865 gravityMatrix.MapRect(newDstRect, newDstRect);
1866 totalMatrix.MapRect(newDstRect, newDstRect);
1867 Drawing::Rect dstRectWithoutScaling;
1868 gravityMatrix.MapRect(dstRectWithoutScaling, Drawing::Rect(0.f, 0.f, bufferWidth, bufferHeight));
1869 totalMatrix.MapRect(dstRectWithoutScaling, dstRectWithoutScaling);
1870 newDstRect.Intersect(dstRectWithoutScaling);
1871 Drawing::Rect bounds = node.GetDstRectWithoutRenderFit();
1872 newDstRect.Intersect(bounds);
1873 node.SetDstRect({std::floor(newDstRect.GetLeft()), std::floor(newDstRect.GetTop()),
1874 std::ceil(newDstRect.GetWidth()), std::ceil(newDstRect.GetHeight())});
1875 Drawing::Rect newSrcRect;
1876 inverseTotalMatrix.MapRect(newSrcRect, newDstRect);
1877 inverseGravityMatrix.MapRect(newSrcRect, newSrcRect);
1878 inverseScalingModeMatrix.MapRect(newSrcRect, newSrcRect);
1879 if (consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_90 ||
1880 consumerTransformType == GraphicTransformType::GRAPHIC_ROTATE_270) {
1881 std::swap(newSrcRect.left_, newSrcRect.top_);
1882 std::swap(newSrcRect.right_, newSrcRect.bottom_);
1883 }
1884 newSrcRect = CalcSrcRectByBufferRotation(*buffer, consumerTransformType, newSrcRect);
1885 node.SetSrcRect({newSrcRect.GetLeft(), newSrcRect.GetTop(), newSrcRect.GetWidth(), newSrcRect.GetHeight()});
1886 }
1887
OptimizedFlushAndSubmit(std::shared_ptr<Drawing::Surface> & surface,Drawing::GPUContext * const grContext,bool optFenceWait)1888 void RSUniRenderUtil::OptimizedFlushAndSubmit(std::shared_ptr<Drawing::Surface>& surface,
1889 Drawing::GPUContext* const grContext, bool optFenceWait)
1890 {
1891 if (!surface || !grContext) {
1892 RS_LOGE("RSUniRenderUtil::OptimizedFlushAndSubmit cacheSurface or grContext are nullptr");
1893 return;
1894 }
1895 RS_TRACE_NAME_FMT("Render surface flush and submit");
1896 RS_LOGD("RSUniRenderUtil::optimized flush and submit GpuApiType:%{public}d",
1897 RSSystemProperties::GetGpuApiType());
1898 #ifdef RS_ENABLE_VK
1899 if ((RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
1900 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) && optFenceWait) {
1901 auto& vkContext = RsVulkanContext::GetSingleton().GetRsVulkanInterface();
1902
1903 VkExportSemaphoreCreateInfo exportSemaphoreCreateInfo;
1904 exportSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
1905 exportSemaphoreCreateInfo.pNext = nullptr;
1906 exportSemaphoreCreateInfo.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
1907
1908 VkSemaphoreCreateInfo semaphoreInfo;
1909 semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
1910 semaphoreInfo.pNext = &exportSemaphoreCreateInfo;
1911 semaphoreInfo.flags = 0;
1912 VkSemaphore semaphore;
1913 vkContext.vkCreateSemaphore(vkContext.GetDevice(), &semaphoreInfo, nullptr, &semaphore);
1914 GrBackendSemaphore backendSemaphore;
1915 backendSemaphore.initVulkan(semaphore);
1916
1917 DestroySemaphoreInfo* destroyInfo =
1918 new DestroySemaphoreInfo(vkContext.vkDestroySemaphore, vkContext.GetDevice(), semaphore);
1919
1920 Drawing::FlushInfo drawingFlushInfo;
1921 drawingFlushInfo.backendSurfaceAccess = true;
1922 drawingFlushInfo.numSemaphores = 1;
1923 drawingFlushInfo.backendSemaphore = static_cast<void*>(&backendSemaphore);
1924 drawingFlushInfo.finishedProc = [](void *context) {
1925 DestroySemaphoreInfo::DestroySemaphore(context);
1926 };
1927 drawingFlushInfo.finishedContext = destroyInfo;
1928 surface->Flush(&drawingFlushInfo);
1929 grContext->Submit();
1930 DestroySemaphoreInfo::DestroySemaphore(destroyInfo);
1931 } else {
1932 surface->FlushAndSubmit(true);
1933 }
1934 #else
1935 surface->FlushAndSubmit(true);
1936 #endif
1937 }
1938
AccumulateMatrixAndAlpha(std::shared_ptr<RSSurfaceRenderNode> & hwcNode,Drawing::Matrix & matrix,float & alpha)1939 void RSUniRenderUtil::AccumulateMatrixAndAlpha(std::shared_ptr<RSSurfaceRenderNode>& hwcNode,
1940 Drawing::Matrix& matrix, float& alpha)
1941 {
1942 if (hwcNode == nullptr) {
1943 return;
1944 }
1945 const auto& property = hwcNode->GetRenderProperties();
1946 alpha = property.GetAlpha();
1947 matrix = property.GetBoundsGeometry()->GetMatrix();
1948 auto parent = hwcNode->GetParent().lock();
1949 while (parent && parent->GetType() != RSRenderNodeType::DISPLAY_NODE) {
1950 const auto& curProperty = parent->GetRenderProperties();
1951 alpha *= curProperty.GetAlpha();
1952 matrix.PostConcat(curProperty.GetBoundsGeometry()->GetMatrix());
1953 parent = parent->GetParent().lock();
1954 }
1955 if (!parent) {
1956 return;
1957 }
1958 const auto& parentProperty = parent->GetRenderProperties();
1959 alpha *= parentProperty.GetAlpha();
1960 matrix.PostConcat(parentProperty.GetBoundsGeometry()->GetMatrix());
1961 }
1962
GenerateSecRectInfoFromNode(RSRenderNode & node,RectI rect)1963 SecRectInfo RSUniRenderUtil::GenerateSecRectInfoFromNode(RSRenderNode& node, RectI rect)
1964 {
1965 SecRectInfo uiExtensionRectInfo;
1966 uiExtensionRectInfo.relativeCoords = rect;
1967 uiExtensionRectInfo.scale = node.GetRenderProperties().GetScale();
1968 return uiExtensionRectInfo;
1969 }
1970
GenerateSecSurfaceInfoFromNode(NodeId uiExtensionId,NodeId hostId,SecRectInfo uiExtensionRectInfo)1971 SecSurfaceInfo RSUniRenderUtil::GenerateSecSurfaceInfoFromNode(
1972 NodeId uiExtensionId, NodeId hostId, SecRectInfo uiExtensionRectInfo)
1973 {
1974 SecSurfaceInfo secSurfaceInfo;
1975 secSurfaceInfo.uiExtensionRectInfo = uiExtensionRectInfo;
1976 secSurfaceInfo.uiExtensionPid = ExtractPid(uiExtensionId);
1977 secSurfaceInfo.hostPid = ExtractPid(hostId);
1978 secSurfaceInfo.uiExtensionNodeId = uiExtensionId;
1979 secSurfaceInfo.hostNodeId = hostId;
1980 return secSurfaceInfo;
1981 }
1982
UIExtensionFindAndTraverseAncestor(const RSRenderNodeMap & nodeMap,UIExtensionCallbackData & callbackData,bool isUnobscured)1983 void RSUniRenderUtil::UIExtensionFindAndTraverseAncestor(
1984 const RSRenderNodeMap& nodeMap, UIExtensionCallbackData& callbackData, bool isUnobscured)
1985 {
1986 const auto& secUIExtensionNodes = RSSurfaceRenderNode::GetSecUIExtensionNodes();
1987 for (auto it = secUIExtensionNodes.begin(); it != secUIExtensionNodes.end(); ++it) {
1988 currentUIExtensionIndex_ = -1;
1989 // only traverse host node one time, even if it has multiple uiextension children.
1990 if (callbackData.find(it->second) != callbackData.end()) {
1991 continue;
1992 }
1993 auto hostNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(nodeMap.GetRenderNode(it->second));
1994 if (!hostNode || !hostNode->GetSortedChildren()) {
1995 RS_LOGE("RSUniRenderUtil::UIExtensionFindAndTraverseAncestor failed to get host node or its children.");
1996 return;
1997 }
1998 for (const auto& child : *hostNode->GetSortedChildren()) {
1999 TraverseAndCollectUIExtensionInfo(child, Drawing::Matrix(), hostNode->GetId(), callbackData, isUnobscured);
2000 }
2001 }
2002 }
2003
TraverseAndCollectUIExtensionInfo(std::shared_ptr<RSRenderNode> node,Drawing::Matrix parentMatrix,NodeId hostId,UIExtensionCallbackData & callbackData,bool isUnobscured)2004 void RSUniRenderUtil::TraverseAndCollectUIExtensionInfo(std::shared_ptr<RSRenderNode> node,
2005 Drawing::Matrix parentMatrix, NodeId hostId, UIExtensionCallbackData& callbackData, bool isUnobscured)
2006 {
2007 if (!node) {
2008 return;
2009 }
2010 // update position relative to host app window node.
2011 std::optional<Drawing::Point> offset;
2012 auto parent = node->GetParent().lock();
2013 if (parent && !(node->IsInstanceOf<RSSurfaceRenderNode>())) {
2014 const auto& parentRenderProperties = parent->GetRenderProperties();
2015 offset = Drawing::Point { parentRenderProperties.GetFrameOffsetX(), parentRenderProperties.GetFrameOffsetY() };
2016 }
2017 const auto& nodeRenderProperties = node->GetRenderProperties();
2018 RSObjAbsGeometry boundsGeo = nodeRenderProperties.GetBoundsGeometry() == nullptr ?
2019 RSObjAbsGeometry() : *(nodeRenderProperties.GetBoundsGeometry());
2020 boundsGeo.UpdateMatrix(&parentMatrix, offset);
2021 auto rect = boundsGeo.MapAbsRect(node->GetSelfDrawRect().JoinRect(node->GetChildrenRect().ConvertTo<float>()));
2022 // if node is UIExtension type, update its own info, and skip its children.
2023 if (auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node)) {
2024 if ((surfaceNode->IsSecureUIExtension() && !isUnobscured) ||
2025 (surfaceNode->IsUnobscuredUIExtensionNode() && isUnobscured)) {
2026 currentUIExtensionIndex_++;
2027 // if host node is not recorded in callbackData, insert it.
2028 auto [iter, inserted] = callbackData.insert(std::pair(hostId, std::vector<SecSurfaceInfo>{}));
2029 if (iter != callbackData.end()) {
2030 iter->second.push_back(GenerateSecSurfaceInfoFromNode(
2031 surfaceNode->GetId(), hostId, GenerateSecRectInfoFromNode(*surfaceNode, rect)));
2032 }
2033 if (surfaceNode->ChildrenHasUIExtension()) {
2034 RS_LOGW("RSUniRenderUtil::TraverseAndCollectUIExtensionInfo UIExtension node [%{public}" PRIu64 "]"
2035 " has children UIExtension, not surpported!", surfaceNode->GetId());
2036 }
2037 return;
2038 }
2039 }
2040 // if the node is traversed after a UIExtension, collect it and skip its children (except it has UIExtension child.)
2041 auto iter = callbackData.find(hostId);
2042 if (iter != callbackData.end() && currentUIExtensionIndex_ != -1 &&
2043 currentUIExtensionIndex_ < static_cast<int>((iter->second).size())) {
2044 (iter->second)[currentUIExtensionIndex_].upperNodes.push_back(GenerateSecRectInfoFromNode(*node, rect));
2045 if (!node->ChildrenHasUIExtension()) {
2046 return;
2047 }
2048 }
2049 // continue to traverse.
2050 for (const auto& child : *node->GetSortedChildren()) {
2051 TraverseAndCollectUIExtensionInfo(child, boundsGeo.GetAbsMatrix(), hostId, callbackData, isUnobscured);
2052 }
2053 }
2054
ProcessCacheImage(RSPaintFilterCanvas & canvas,Drawing::Image & cacheImageProcessed)2055 void RSUniRenderUtil::ProcessCacheImage(RSPaintFilterCanvas& canvas, Drawing::Image& cacheImageProcessed)
2056 {
2057 Drawing::Brush brush;
2058 brush.SetAntiAlias(true);
2059 canvas.AttachBrush(brush);
2060 // Be cautious when changing FilterMode and MipmapMode that may affect clarity
2061 auto sampling = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NEAREST);
2062 canvas.DrawImage(cacheImageProcessed, 0, 0, sampling);
2063 canvas.DetachBrush();
2064 }
2065
ProcessCacheImageRect(RSPaintFilterCanvas & canvas,Drawing::Image & cacheImageProcessed,const Drawing::Rect & src,const Drawing::Rect & dst)2066 void RSUniRenderUtil::ProcessCacheImageRect(RSPaintFilterCanvas& canvas, Drawing::Image& cacheImageProcessed,
2067 const Drawing::Rect& src, const Drawing::Rect& dst)
2068 {
2069 Drawing::Brush brush;
2070 brush.SetAntiAlias(true);
2071 canvas.AttachBrush(brush);
2072 // Be cautious when changing FilterMode and MipmapMode that may affect clarity
2073 auto sampling = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NEAREST);
2074 canvas.DrawImageRect(cacheImageProcessed, src, dst, sampling, Drawing::SrcRectConstraint::FAST_SRC_RECT_CONSTRAINT);
2075 canvas.DetachBrush();
2076 }
2077
ProcessCacheImageForMultiScreenView(RSPaintFilterCanvas & canvas,Drawing::Image & cacheImageProcessed,const RectF & rect)2078 void RSUniRenderUtil::ProcessCacheImageForMultiScreenView(RSPaintFilterCanvas& canvas,
2079 Drawing::Image& cacheImageProcessed, const RectF& rect)
2080 {
2081 if (cacheImageProcessed.GetWidth() == 0 || cacheImageProcessed.GetHeight() == 0) {
2082 RS_TRACE_NAME("ProcessCacheImageForMultiScreenView cacheImageProcessed is invalid");
2083 return;
2084 }
2085 Drawing::Brush brush;
2086 brush.SetAntiAlias(true);
2087 canvas.AttachBrush(brush);
2088 // Be cautious when changing FilterMode and MipmapMode that may affect clarity
2089 auto sampling = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NEAREST);
2090 canvas.Save();
2091 // Use Fill Mode
2092 const float scaleX = rect.GetWidth() / cacheImageProcessed.GetWidth();
2093 const float scaleY = rect.GetHeight() / cacheImageProcessed.GetHeight();
2094 canvas.Scale(scaleX, scaleY);
2095 canvas.DrawImage(cacheImageProcessed, 0, 0, sampling);
2096 canvas.Restore();
2097 canvas.DetachBrush();
2098 }
2099
FlushDmaSurfaceBuffer(Media::PixelMap * pixelMap)2100 void RSUniRenderUtil::FlushDmaSurfaceBuffer(Media::PixelMap* pixelMap)
2101 {
2102 if (!pixelMap || pixelMap->GetAllocatorType() != Media::AllocatorType::DMA_ALLOC) {
2103 return;
2104 }
2105 SurfaceBuffer* surfaceBuffer = reinterpret_cast<SurfaceBuffer*>(pixelMap->GetFd());
2106 if (surfaceBuffer && (surfaceBuffer->GetUsage() & BUFFER_USAGE_MEM_MMZ_CACHE)) {
2107 GSError err = surfaceBuffer->Map();
2108 if (err != GSERROR_OK) {
2109 RS_LOGE("RSUniRenderUtil::FlushDmaSurfaceBuffer Map failed, GSError=%{public}d", err);
2110 return;
2111 }
2112 err = surfaceBuffer->InvalidateCache();
2113 if (err != GSERROR_OK) {
2114 RS_LOGE("RSUniRenderUtil::FlushDmaSurfaceBuffer InvalidateCache failed, GSError=%{public}d", err);
2115 }
2116 }
2117 }
2118
GetMatrix(std::shared_ptr<RSRenderNode> hwcNode)2119 std::optional<Drawing::Matrix> RSUniRenderUtil::GetMatrix(
2120 std::shared_ptr<RSRenderNode> hwcNode)
2121 {
2122 if (!hwcNode) {
2123 return std::nullopt;
2124 }
2125 auto relativeMat = Drawing::Matrix();
2126 auto& property = hwcNode->GetRenderProperties();
2127 if (auto geo = property.GetBoundsGeometry()) {
2128 if (LIKELY(!property.GetSandBox().has_value())) {
2129 relativeMat = geo->GetMatrix();
2130 } else {
2131 auto parent = hwcNode->GetParent().lock();
2132 if (!parent) {
2133 return std::nullopt;
2134 }
2135 if (auto parentGeo = parent->GetRenderProperties().GetBoundsGeometry()) {
2136 auto invertAbsParentMatrix = Drawing::Matrix();
2137 parentGeo->GetAbsMatrix().Invert(invertAbsParentMatrix);
2138 relativeMat = geo->GetAbsMatrix();
2139 relativeMat.PostConcat(invertAbsParentMatrix);
2140 }
2141 }
2142 } else {
2143 return std::nullopt;
2144 }
2145 return relativeMat;
2146 }
2147
CheckRenderSkipIfScreenOff(bool extraFrame,std::optional<ScreenId> screenId)2148 bool RSUniRenderUtil::CheckRenderSkipIfScreenOff(bool extraFrame, std::optional<ScreenId> screenId)
2149 {
2150 if (!RSSystemProperties::GetSkipDisplayIfScreenOffEnabled()) {
2151 return false;
2152 }
2153 auto screenManager = CreateOrGetScreenManager();
2154 if (!screenManager) {
2155 RS_LOGE("RSUniRenderUtil::CheckRenderSkipIfScreenOff, failed to get screen manager!");
2156 return false;
2157 }
2158 // in certain cases such as wireless display, render skipping may be disabled.
2159 auto disableRenderControlScreensCount = screenManager->GetDisableRenderControlScreensCount();
2160 auto isScreenOff = screenId.has_value() ?
2161 screenManager->IsScreenPowerOff(screenId.value()) : screenManager->IsAllScreensPowerOff();
2162 RS_TRACE_NAME_FMT("CheckRenderSkipIfScreenOff disableRenderControl:[%d], PowerOff:[%d]",
2163 disableRenderControlScreensCount, isScreenOff);
2164 if (disableRenderControlScreensCount != 0 || !isScreenOff) {
2165 return false;
2166 }
2167 if (extraFrame && screenManager->GetPowerOffNeedProcessOneFrame()) {
2168 RS_LOGI("RSUniRenderUtil::CheckRenderSkipIfScreenOff screen power off, one more frame.");
2169 screenManager->ResetPowerOffNeedProcessOneFrame();
2170 return false;
2171 } else {
2172 return !screenManager->GetPowerOffNeedProcessOneFrame();
2173 }
2174 }
2175
UpdateHwcNodeProperty(std::shared_ptr<RSSurfaceRenderNode> hwcNode)2176 void RSUniRenderUtil::UpdateHwcNodeProperty(std::shared_ptr<RSSurfaceRenderNode> hwcNode)
2177 {
2178 if (hwcNode == nullptr) {
2179 RS_LOGE("hwcNode is null.");
2180 return;
2181 }
2182 auto hwcNodeGeo = hwcNode->GetRenderProperties().GetBoundsGeometry();
2183 if (!hwcNodeGeo) {
2184 RS_LOGE("hwcNode Geometry is not prepared.");
2185 return;
2186 }
2187 bool hasCornerRadius = !hwcNode->GetRenderProperties().GetCornerRadius().IsZero();
2188 std::vector<RectI> currIntersectedRoundCornerAABBs = {};
2189 float alpha = hwcNode->GetRenderProperties().GetAlpha();
2190 Drawing::Matrix totalMatrix = hwcNodeGeo->GetMatrix();
2191 auto hwcNodeRect = hwcNodeGeo->GetAbsRect();
2192 bool isNodeRenderByDrawingCache = false;
2193 bool isNodeRenderBySaveLayer = false;
2194 hwcNode->SetAbsRotation(hwcNode->GetRenderProperties().GetRotation());
2195 RSUniRenderUtil::TraverseParentNodeAndReduce(
2196 hwcNode,
2197 [&isNodeRenderByDrawingCache](std::shared_ptr<RSRenderNode> parent) {
2198 if (isNodeRenderByDrawingCache) {
2199 return;
2200 }
2201 // if the parent node of hwcNode is marked freeze or nodegroup, RS closes hardware composer of hwcNode.
2202 isNodeRenderByDrawingCache = isNodeRenderByDrawingCache || parent->IsStaticCached() ||
2203 (parent->GetNodeGroupType() != RSRenderNode::NodeGroupType::NONE);
2204 },
2205 [&alpha](std::shared_ptr<RSRenderNode> parent) {
2206 auto& parentProperty = parent->GetRenderProperties();
2207 alpha *= parentProperty.GetAlpha();
2208 },
2209 [&totalMatrix](std::shared_ptr<RSRenderNode> parent) {
2210 if (auto opt = RSUniRenderUtil::GetMatrix(parent)) {
2211 totalMatrix.PostConcat(opt.value());
2212 } else {
2213 return;
2214 }
2215 },
2216 [&currIntersectedRoundCornerAABBs, hwcNodeRect](std::shared_ptr<RSRenderNode> parent) {
2217 auto& parentProperty = parent->GetRenderProperties();
2218 auto cornerRadius = parentProperty.GetCornerRadius();
2219 auto maxCornerRadius = *std::max_element(std::begin(cornerRadius.data_), std::end(cornerRadius.data_));
2220 auto parentGeo = parentProperty.GetBoundsGeometry();
2221 static const std::array offsetVecs {
2222 UIPoint { 0, 0 },
2223 UIPoint { 1, 0 },
2224 UIPoint { 0, 1 },
2225 UIPoint { 1, 1 }
2226 };
2227
2228 // The logic here is to calculate whether the HWC Node affects
2229 // the round corner property of the parent node.
2230 // The method is calculating the rounded AABB of each HWC node
2231 // with respect to all parent nodes above it and storing the results.
2232 // When a HWC node is found below, the AABBs and the HWC node
2233 // are checked for intersection. If there is an intersection,
2234 // the node above it is disabled from taking the HWC pipeline.
2235 auto checkIntersectWithRoundCorner = [&currIntersectedRoundCornerAABBs, hwcNodeRect](
2236 const RectI& rect, float radiusX, float radiusY) {
2237 if (radiusX <= 0 || radiusY <= 0) {
2238 return;
2239 }
2240 UIPoint offset { rect.GetWidth() - radiusX, rect.GetHeight() - radiusY };
2241 UIPoint anchorPoint { rect.GetLeft(), rect.GetTop() };
2242 std::for_each(std::begin(offsetVecs), std::end(offsetVecs),
2243 [&currIntersectedRoundCornerAABBs, hwcNodeRect, offset,
2244 radiusX, radiusY, anchorPoint](auto offsetVec) {
2245 auto res = anchorPoint + offset * offsetVec;
2246 auto roundCornerAABB = RectI(res.x_, res.y_, radiusX, radiusY);
2247 if (!roundCornerAABB.IntersectRect(hwcNodeRect).IsEmpty()) {
2248 currIntersectedRoundCornerAABBs.push_back(roundCornerAABB);
2249 }
2250 }
2251 );
2252 };
2253 if (parentGeo) {
2254 auto parentRect = parentGeo->GetAbsRect();
2255 checkIntersectWithRoundCorner(parentRect, maxCornerRadius, maxCornerRadius);
2256
2257 if (parentProperty.GetClipToRRect()) {
2258 RRect parentClipRRect = parentProperty.GetClipRRect();
2259 RectI parentClipRect = parentGeo->MapAbsRect(parentClipRRect.rect_);
2260 float maxClipRRectCornerRadiusX = 0;
2261 float maxClipRRectCornerRadiusY = 0;
2262 constexpr size_t radiusVecSize = 4;
2263 for (size_t i = 0; i < radiusVecSize; ++i) {
2264 maxClipRRectCornerRadiusX = std::max(maxClipRRectCornerRadiusX, parentClipRRect.radius_[i].x_);
2265 maxClipRRectCornerRadiusY = std::max(maxClipRRectCornerRadiusY, parentClipRRect.radius_[i].y_);
2266 }
2267 checkIntersectWithRoundCorner(parentClipRect, maxClipRRectCornerRadiusX, maxClipRRectCornerRadiusY);
2268 }
2269 }
2270 },
2271 [hwcNode](std::shared_ptr<RSRenderNode> parent) {
2272 hwcNode->SetAbsRotation(hwcNode->GetAbsRotation() + parent->GetRenderProperties().GetRotation());
2273 },
2274 [&isNodeRenderBySaveLayer](std::shared_ptr<RSRenderNode> parent) {
2275 if (isNodeRenderBySaveLayer) {
2276 return;
2277 }
2278 const auto& parentProperty = parent->GetRenderProperties();
2279 isNodeRenderBySaveLayer = isNodeRenderBySaveLayer ||
2280 (parentProperty.IsColorBlendApplyTypeOffscreen() && !parentProperty.IsColorBlendModeNone());
2281 });
2282 if (isNodeRenderByDrawingCache || isNodeRenderBySaveLayer) {
2283 RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: name:%s id:%" PRIu64 " disabled by drawing cache or save layer, ",
2284 "isNodeRenderByDrawingCache[%d] isNodeRenderBySaveLayer[%d]",
2285 hwcNode->GetName().c_str(), hwcNode->GetId(), isNodeRenderByDrawingCache, isNodeRenderBySaveLayer);
2286 hwcNode->SetHardwareForcedDisabledState(true);
2287 }
2288 hwcNode->SetTotalMatrix(totalMatrix);
2289 hwcNode->SetGlobalAlpha(alpha);
2290 hwcNode->SetIntersectedRoundCornerAABBs(std::move(currIntersectedRoundCornerAABBs));
2291 }
2292
2293 #ifdef FRAME_AWARE_TRACE
FrameAwareTraceBoost(size_t layerNum)2294 bool RSUniRenderUtil::FrameAwareTraceBoost(size_t layerNum)
2295 {
2296 using namespace FRAME_TRACE;
2297 constexpr uint32_t FRAME_TRACE_LAYER_NUM_1 = 11;
2298 constexpr uint32_t FRAME_TRACE_LAYER_NUM_2 = 13;
2299 constexpr int32_t FRAME_TRACE_PERF_REQUESTED_CODE = 10024;
2300 RenderFrameTrace& ft = RenderFrameTrace::GetInstance();
2301 if (layerNum != FRAME_TRACE_LAYER_NUM_1 && layerNum != FRAME_TRACE_LAYER_NUM_2) {
2302 if (ft.RenderFrameTraceIsOpen()) {
2303 ft.RenderFrameTraceClose();
2304 PerfRequest(FRAME_TRACE_PERF_REQUESTED_CODE, false);
2305 RS_LOGD("RsDebug RSUniRenderUtil::Perf: FrameTrace 0");
2306 }
2307 return false;
2308 }
2309
2310 static std::chrono::steady_clock::time_point lastRequestPerfTime = std::chrono::steady_clock::now();
2311 auto currentTime = std::chrono::steady_clock::now();
2312 bool isTimeOut = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastRequestPerfTime).
2313 count() > PERF_TIME_OUT;
2314 if (isTimeOut || !ft.RenderFrameTraceIsOpen()) {
2315 if (!ft.RenderFrameTraceOpen()) {
2316 return false;
2317 }
2318 PerfRequest(FRAME_TRACE_PERF_REQUESTED_CODE, true);
2319 RS_LOGD("RsDebug RSProcessor::Perf: FrameTrace 1");
2320 lastRequestPerfTime = currentTime;
2321 }
2322 return true;
2323 }
2324 #endif
2325
RequestPerf(uint32_t layerLevel,bool onOffTag)2326 void RSUniRenderUtil::RequestPerf(uint32_t layerLevel, bool onOffTag)
2327 {
2328 switch (layerLevel) {
2329 case PERF_LEVEL_0: {
2330 // do nothing
2331 RS_LOGD("RsDebug RSProcessor::perf do nothing");
2332 break;
2333 }
2334 case PERF_LEVEL_1: {
2335 PerfRequest(PERF_LEVEL_1_REQUESTED_CODE, onOffTag);
2336 RS_LOGD("RsDebug RSProcessor::Perf: level1 %{public}d", onOffTag);
2337 break;
2338 }
2339 case PERF_LEVEL_2: {
2340 PerfRequest(PERF_LEVEL_2_REQUESTED_CODE, onOffTag);
2341 RS_LOGD("RsDebug RSProcessor::Perf: level2 %{public}d", onOffTag);
2342 break;
2343 }
2344 default: {
2345 PerfRequest(PERF_LEVEL_3_REQUESTED_CODE, onOffTag);
2346 RS_LOGD("RsDebug RSProcessor::Perf: level3 %{public}d", onOffTag);
2347 break;
2348 }
2349 }
2350 }
2351
MultiLayersPerf(size_t layerNum)2352 void RSUniRenderUtil::MultiLayersPerf(size_t layerNum)
2353 {
2354 RS_LOGD("FrameAwareTraceBoost return false");
2355 static uint32_t lastLayerLevel = 0;
2356 constexpr uint32_t PERF_LEVEL_INTERVAL = 10;
2357 static std::chrono::steady_clock::time_point lastRequestPerfTime = std::chrono::steady_clock::now();
2358 auto curLayerLevel = layerNum / PERF_LEVEL_INTERVAL;
2359 if (curLayerLevel == 0 && layerNum >= PERF_LAYER_START_NUM) {
2360 curLayerLevel = 1;
2361 }
2362 auto currentTime = std::chrono::steady_clock::now();
2363 bool isTimeOut = std::chrono::duration_cast<std::chrono::milliseconds>(currentTime - lastRequestPerfTime).
2364 count() > PERF_TIME_OUT;
2365 if (curLayerLevel != lastLayerLevel || isTimeOut) {
2366 if (!isTimeOut) {
2367 RequestPerf(lastLayerLevel, false);
2368 }
2369 RequestPerf(curLayerLevel, true);
2370 lastLayerLevel = curLayerLevel;
2371 lastRequestPerfTime = currentTime;
2372 }
2373 }
2374
GetImageRegions(float screenWidth,float screenHeight,float realImageWidth,float realImageHeight)2375 Drawing::Rect RSUniRenderUtil::GetImageRegions(float screenWidth, float screenHeight,
2376 float realImageWidth, float realImageHeight)
2377 {
2378 auto dstRect = Drawing::Rect(0, 0, screenWidth, screenHeight);
2379 if (ROSEN_EQ(realImageWidth, 0.0f) || ROSEN_EQ(realImageHeight, 0.0f)) {
2380 return dstRect;
2381 }
2382 float imageScaleWidth = screenWidth / static_cast<float>(realImageWidth);
2383 float imageScaleHeight = screenHeight / static_cast<float>(realImageHeight);
2384 auto imageWidth = realImageWidth * imageScaleHeight;
2385 auto imageHeight = realImageHeight * imageScaleWidth;
2386 // Ensure that the security mask is located in the middle of the virtual screen.
2387 if (imageScaleWidth > imageScaleHeight) {
2388 // Left and right set black
2389 float halfBoundWidthLeft = (screenWidth - imageWidth) / 2;
2390 float halfBoundWidthRight = halfBoundWidthLeft + imageWidth;
2391 dstRect = Drawing::Rect(halfBoundWidthLeft, 0, halfBoundWidthRight, screenHeight);
2392 return dstRect;
2393 }
2394
2395 if (imageScaleWidth < imageScaleHeight) {
2396 // Up and down set black
2397 float halfBoundHeightTop = (screenHeight - imageHeight) / 2;
2398 float halfBoundHeightBottom = halfBoundHeightTop + imageHeight;
2399 dstRect = Drawing::Rect(0, halfBoundHeightTop, screenWidth, halfBoundHeightBottom);
2400 return dstRect;
2401 }
2402 return dstRect;
2403 }
2404
GetSampledDamageAndDrawnRegion(const ScreenInfo & screenInfo,const Occlusion::Region & srcDamageRegion,bool isDirtyAlignEnabled,Occlusion::Region & sampledDamageRegion,Occlusion::Region & sampledDrawnRegion)2405 void RSUniRenderUtil::GetSampledDamageAndDrawnRegion(const ScreenInfo& screenInfo,
2406 const Occlusion::Region& srcDamageRegion, bool isDirtyAlignEnabled, Occlusion::Region& sampledDamageRegion,
2407 Occlusion::Region& sampledDrawnRegion)
2408 {
2409 Drawing::Matrix scaleMatrix;
2410 scaleMatrix.SetScaleTranslate(screenInfo.samplingScale, screenInfo.samplingScale,
2411 screenInfo.samplingTranslateX, screenInfo.samplingTranslateY);
2412 const Vector4<int> expandSize{screenInfo.samplingDistance, screenInfo.samplingDistance,
2413 screenInfo.samplingDistance, screenInfo.samplingDistance};
2414 auto rects = srcDamageRegion.GetRegionRectIs();
2415 sampledDamageRegion.Reset();
2416 for (const auto& rect : rects) {
2417 RectI mappedRect = RSObjAbsGeometry::MapRect(rect.ConvertTo<float>(), scaleMatrix);
2418 Occlusion::Region mappedAndExpandedRegion{mappedRect.MakeOutset(expandSize)};
2419 sampledDamageRegion.OrSelf(mappedAndExpandedRegion);
2420 }
2421
2422 Occlusion::Region drawnRegion = isDirtyAlignEnabled ?
2423 sampledDamageRegion.GetAlignedRegion(MAX_DIRTY_ALIGNMENT_SIZE) : sampledDamageRegion;
2424
2425 Drawing::Matrix invertedScaleMatrix;
2426 if (!scaleMatrix.Invert(invertedScaleMatrix)) {
2427 RS_LOGW("%{public}s, invert scaleMatrix failed", __func__);
2428 sampledDrawnRegion = drawnRegion;
2429 return;
2430 }
2431 sampledDrawnRegion.Reset();
2432 for (const auto& rect : drawnRegion.GetRegionRectIs()) {
2433 RectI mappedRect = RSObjAbsGeometry::MapRect(rect.ConvertTo<float>(), invertedScaleMatrix);
2434 Occlusion::Region mappedRegion{mappedRect};
2435 sampledDrawnRegion.OrSelf(mappedRegion);
2436 }
2437 }
2438 } // namespace Rosen
2439 } // namespace OHOS
2440