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