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