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