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