1 /*
2 * Copyright (c) 2025 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 "drawable/rs_screen_render_node_drawable.h"
17
18 #include <memory>
19 #include <parameters.h>
20 #include <string>
21
22 #include "graphic_feature_param_manager.h"
23 #include "rs_trace.h"
24 #include "system/rs_system_parameters.h"
25
26 #include "common/rs_common_def.h"
27 #include "common/rs_optional_trace.h"
28 #include "common/rs_singleton.h"
29 #include "common/rs_special_layer_manager.h"
30 #include "display_engine/rs_luminance_control.h"
31 #include "drawable/rs_surface_render_node_drawable.h"
32 #include "feature/anco_manager/rs_anco_manager.h"
33 #include "feature/uifirst/rs_uifirst_manager.h"
34 #ifdef RS_ENABLE_OVERLAY_DISPLAY
35 #include "feature/overlay_display/rs_overlay_display_manager.h"
36 #endif
37 #include "hgm_core.h"
38 #include "memory/rs_tag_tracker.h"
39 #include "params/rs_screen_render_params.h"
40 #include "params/rs_surface_render_params.h"
41 #include "feature/dirty/rs_uni_dirty_compute_util.h"
42 #include "feature/drm/rs_drm_util.h"
43 #include "feature/round_corner_display/rs_round_corner_display_manager.h"
44 #include "feature/round_corner_display/rs_rcd_surface_render_node_drawable.h"
45 #include "feature/round_corner_display/rs_message_bus.h"
46 #include "pipeline/render_thread/rs_base_render_engine.h"
47 #include "pipeline/rs_screen_render_node.h"
48 #include "pipeline/main_thread/rs_main_thread.h"
49 #include "pipeline/rs_paint_filter_canvas.h"
50 #include "pipeline/rs_processor_factory.h"
51 #include "pipeline/rs_pointer_window_manager.h"
52 #include "pipeline/rs_surface_handler.h"
53 #include "pipeline/main_thread/rs_uni_render_listener.h"
54 #include "pipeline/render_thread/rs_uni_render_thread.h"
55 #include "pipeline/render_thread/rs_uni_render_util.h"
56 #include "pipeline/render_thread/rs_uni_render_virtual_processor.h"
57 #include "pipeline/sk_resource_manager.h"
58 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
59 #include "pipeline/magic_pointer_render/rs_magic_pointer_render_manager.h"
60 #endif
61 #include "platform/common/rs_log.h"
62 #include "platform/ohos/rs_jank_stats_helper.h"
63 #include "render/rs_pixel_map_util.h"
64 #include "screen_manager/rs_screen_manager.h"
65 #include "rs_frame_report.h"
66 // dfx
67 #include "drawable/dfx/rs_dirty_rects_dfx.h"
68 #include "drawable/dfx/rs_skp_capture_dfx.h"
69 #include "platform/ohos/overdraw/rs_overdraw_controller.h"
70 #include "utils/performanceCaculate.h"
71 // cpu boost
72 #include "c/ffrt_cpu_boost.h"
73 // xml parser
74 #include "graphic_feature_param_manager.h"
75 // hpae offline
76 #include "feature/hwc/hpae_offline/rs_hpae_offline_processor.h"
77
78 #ifdef SUBTREE_PARALLEL_ENABLE
79 #include "rs_parallel_manager.h"
80 #endif
81
82 namespace OHOS::Rosen::DrawableV2 {
83 namespace {
84 constexpr const char* CLEAR_GPU_CACHE = "ClearGpuCache";
85 constexpr const char* DEFAULT_CLEAR_GPU_CACHE = "DefaultClearGpuCache";
86 constexpr int32_t CAPTURE_WINDOW = 2; // To be deleted after captureWindow being deleted
87 constexpr int64_t MAX_JITTER_NS = 2000000; // 2ms
88
RectVectorToString(const std::vector<RectI> & regionRects)89 std::string RectVectorToString(const std::vector<RectI>& regionRects)
90 {
91 std::string results = "";
92 for (auto& rect : regionRects) {
93 results += rect.ToString();
94 }
95 return results;
96 }
97
GetFlippedRegion(const std::vector<RectI> & rects,ScreenInfo & screenInfo)98 Drawing::Region GetFlippedRegion(const std::vector<RectI>& rects, ScreenInfo& screenInfo)
99 {
100 Drawing::Region region;
101
102 for (const auto& r : rects) {
103 int32_t topAfterFilp = 0;
104 #ifdef RS_ENABLE_VK
105 topAfterFilp = (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
106 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)
107 ? r.top_
108 : static_cast<int32_t>(screenInfo.GetRotatedHeight()) - r.GetBottom();
109 #else
110 topAfterFilp = static_cast<int32_t>(screenInfo.GetRotatedHeight()) - r.GetBottom();
111 #endif
112 Drawing::Region tmpRegion;
113 tmpRegion.SetRect(Drawing::RectI(r.left_, topAfterFilp, r.left_ + r.width_, topAfterFilp + r.height_));
114 RS_OPTIONAL_TRACE_NAME_FMT("GetFlippedRegion orig ltrb[%d %d %d %d] to fliped rect ltrb[%d %d %d %d]",
115 r.left_, r.top_, r.left_ + r.width_, r.top_ + r.height_, r.left_, topAfterFilp, r.left_ + r.width_,
116 topAfterFilp + r.height_);
117 region.Op(tmpRegion, Drawing::RegionOp::UNION);
118 }
119 return region;
120 }
121 }
122
123 // Rcd node will be handled by RS tree in OH 6.0 rcd refactoring, should remove this later
DoScreenRcdTask(RSScreenRenderParams & params,std::shared_ptr<RSProcessor> & processor)124 void DoScreenRcdTask(RSScreenRenderParams& params, std::shared_ptr<RSProcessor> &processor)
125 {
126 if (processor == nullptr) {
127 RS_LOGD("DoScreenRcdTask has no processor");
128 return;
129 }
130 const auto &screenInfo = params.GetScreenInfo();
131 if (screenInfo.state != ScreenState::HDI_OUTPUT_ENABLE) {
132 RS_LOGD("DoScreenRcdTask is not at HDI_OUPUT mode");
133 return;
134 }
135
136 bool res = true;
137 bool resourceChanged = false;
138 auto drawables = params.GetRoundCornerDrawables();
139 for (auto drawable : drawables) {
140 auto rcdDrawable = std::static_pointer_cast<DrawableV2::RSRcdSurfaceRenderNodeDrawable>(drawable);
141 if (rcdDrawable) {
142 resourceChanged |= rcdDrawable->IsResourceChanged();
143 res &= rcdDrawable->DoProcessRenderTask(processor);
144 }
145 }
146 if (resourceChanged && res) {
147 RSSingleton<RsMessageBus>::GetInstance().SendMsg<NodeId, bool>(
148 TOPIC_RCD_DISPLAY_HWRESOURCE, params.GetId(), true);
149 }
150 }
151
152 RSScreenRenderNodeDrawable::Registrar RSScreenRenderNodeDrawable::instance_;
153
RSScreenRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)154 RSScreenRenderNodeDrawable::RSScreenRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
155 : RSRenderNodeDrawable(std::move(node)), surfaceHandler_(std::make_shared<RSSurfaceHandler>(nodeId_)),
156 syncDirtyManager_(std::make_shared<RSDirtyRegionManager>(true))
157 {}
158
OnGenerate(std::shared_ptr<const RSRenderNode> node)159 RSRenderNodeDrawable::Ptr RSScreenRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
160 {
161 return new RSScreenRenderNodeDrawable(std::move(node));
162 }
163
RequestFrame(RSScreenRenderParams & params,std::shared_ptr<RSProcessor> processor)164 std::unique_ptr<RSRenderFrame> RSScreenRenderNodeDrawable::RequestFrame(
165 RSScreenRenderParams& params, std::shared_ptr<RSProcessor> processor)
166 {
167 RS_TRACE_NAME_FMT("RSScreenRenderNodeDrawable:RequestFrame with colorSpace: %d, pixelformat: %d, ",
168 "lastPixelFormat: %d", params.GetNewColorSpace(), params.GetNewPixelFormat(), GetLastPixelFormat());
169 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
170 if (UNLIKELY(!renderEngine)) {
171 RS_LOGE("RSScreenRenderNodeDrawable::RequestFrame RenderEngine is null!");
172 return nullptr;
173 }
174
175 if (!processor->InitForRenderThread(*this, renderEngine)) {
176 RS_LOGE("RSScreenRenderNodeDrawable::RequestFrame processor init failed!");
177 return nullptr;
178 }
179
180 if (!IsSurfaceCreated()) {
181 sptr<IBufferConsumerListener> listener = new RSUniRenderListener(surfaceHandler_);
182 if (!CreateSurface(listener)) {
183 RS_LOGE("RSScreenRenderNodeDrawable::RequestFrame CreateSurface failed");
184 return nullptr;
185 }
186 }
187
188 auto rsSurface = GetRSSurface();
189 if (!rsSurface) {
190 RS_LOGE("RSScreenRenderNodeDrawable::RequestFrame No RSSurface found");
191 return nullptr;
192 }
193 auto bufferConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(params.GetScreenInfo(), false,
194 params.GetNewColorSpace(), params.GetNewPixelFormat());
195 RS_LOGD("RequestFrame colorspace is %{public}d, pixelformat is %{public}d, lastPixelFormat: %{public}d",
196 params.GetNewColorSpace(), params.GetNewPixelFormat(), GetLastPixelFormat());
197
198 bool isHebc = true;
199 if (RSAncoManager::Instance()->GetAncoHebcStatus() == AncoHebcStatus::NOT_USE_HEBC) {
200 isHebc = false;
201 RS_LOGI("anco request frame not use hebc");
202 }
203 RSAncoManager::Instance()->SetAncoHebcStatus(AncoHebcStatus::INITIAL);
204 if (IsPixelFormatChanged(params)) {
205 auto ohosSurface = std::static_pointer_cast<RSSurfaceOhos>(rsSurface);
206 auto surface = ohosSurface->GetSurface();
207 if (surface == nullptr) {
208 RS_LOGE("RSScreenRenderNodeDrawable::rsSurface->GetSurface is nullptr!!");
209 } else {
210 RS_TRACE_NAME("RSScreenRenderNodeDrawable::SetBufferReallocFlag succeed");
211 surface->SetBufferReallocFlag(true);
212 RS_LOGI("RSScreenRenderNodeDrawable::SetBufferReallocFlag succeed");
213 }
214 }
215 SetLastPixelFormat(params.GetNewPixelFormat());
216 auto renderFrame = renderEngine->RequestFrame(std::static_pointer_cast<RSSurfaceOhos>(rsSurface),
217 bufferConfig, false, isHebc);
218 if (!renderFrame) {
219 RS_LOGE("RSScreenRenderNodeDrawable::RequestFrame renderEngine requestFrame is null");
220 return nullptr;
221 }
222
223 return renderFrame;
224 }
225
ClipRegion(Drawing::Canvas & canvas,Drawing::Region & region,bool clear=true)226 static void ClipRegion(Drawing::Canvas& canvas, Drawing::Region& region, bool clear = true)
227 {
228 if (region.IsEmpty()) {
229 // [planning] Remove this after frame buffer can cancel
230 canvas.ClipRect(Drawing::Rect());
231 } else if (region.IsRect()) {
232 canvas.ClipRegion(region);
233 } else {
234 RS_TRACE_NAME("RSScreenRenderNodeDrawable: clipPath");
235 #ifdef RS_ENABLE_VK
236 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
237 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
238 canvas.ClipRegion(region);
239 } else {
240 Drawing::Path dirtyPath;
241 region.GetBoundaryPath(&dirtyPath);
242 canvas.ClipPath(dirtyPath, Drawing::ClipOp::INTERSECT, true);
243 }
244 #else
245 Drawing::Path dirtyPath;
246 region.GetBoundaryPath(&dirtyPath);
247 canvas.ClipPath(dirtyPath, Drawing::ClipOp::INTERSECT, true);
248 #endif
249 }
250
251 // clear canvas after clip region if need
252 if (clear && !region.IsEmpty()) {
253 canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
254 }
255 }
256
HardCursorCreateLayer(std::shared_ptr<RSProcessor> processor)257 bool RSScreenRenderNodeDrawable::HardCursorCreateLayer(std::shared_ptr<RSProcessor> processor)
258 {
259 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
260 if (!uniParam) {
261 RS_LOGE("RSScreenRenderNodeDrawable::HardCursorCreateLayer uniParam is null");
262 return false;
263 }
264 auto& hardCursorDrawables = uniParam->GetHardCursorDrawables();
265 if (hardCursorDrawables.empty()) {
266 return false;
267 }
268 auto iter = std::find_if(hardCursorDrawables.begin(), hardCursorDrawables.end(), [id = GetId()](const auto& node) {
269 return std::get<0>(node) == id;
270 });
271 if (iter == hardCursorDrawables.end()) {
272 return false;
273 }
274 auto& hardCursorDrawable = std::get<2>(*iter);
275 if (!hardCursorDrawable) {
276 return false;
277 }
278 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(hardCursorDrawable->GetRenderParams().get());
279 if (!surfaceParams) {
280 RS_LOGE("RSScreenRenderNodeDrawable::HardCursorCreateLayer surfaceParams is null");
281 return false;
282 }
283 auto surfaceDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(hardCursorDrawable);
284 if (surfaceDrawable && surfaceParams->GetHardCursorStatus()) {
285 processor->CreateLayerForRenderThread(*surfaceDrawable);
286 return true;
287 }
288 return false;
289 }
290
RenderOverDraw()291 void RSScreenRenderNodeDrawable::RenderOverDraw()
292 {
293 bool isEnabled = false;
294 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
295 if (LIKELY(uniParam)) {
296 isEnabled = uniParam->IsOverDrawEnabled();
297 }
298 bool enable = isEnabled && curCanvas_ != nullptr;
299 if (!enable) {
300 return;
301 }
302 auto gpuContext = curCanvas_->GetGPUContext();
303 if (gpuContext == nullptr) {
304 RS_LOGE("RSScreenRenderNodeDrawable::RenderOverDraw failed: need gpu canvas");
305 return;
306 }
307 Drawing::ImageInfo info = Drawing::ImageInfo { curCanvas_->GetWidth(), curCanvas_->GetHeight(),
308 Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
309 auto overdrawSurface = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, info);
310 if (!overdrawSurface) {
311 RS_LOGE("RSScreenRenderNodeDrawable::RenderOverDraw failed: surface is nullptr");
312 return;
313 }
314 auto overdrawCanvas = std::make_shared<Drawing::OverDrawCanvas>(overdrawSurface->GetCanvas());
315 overdrawCanvas->SetGrContext(gpuContext);
316 auto paintCanvas = std::make_shared<RSPaintFilterCanvas>(overdrawCanvas.get());
317 // traverse all drawable to detect overdraw
318 auto params = static_cast<RSScreenRenderParams*>(renderParams_.get());
319 paintCanvas->ConcatMatrix(params->GetMatrix());
320 RS_TRACE_NAME_FMT("RSScreenRenderNodeDrawable::RenderOverDraw");
321 RSRenderNodeDrawable::OnDraw(*paintCanvas);
322 // show overdraw result in main display
323 auto image = overdrawSurface->GetImageSnapshot();
324 if (image == nullptr) {
325 RS_LOGE("RSScreenRenderNodeDrawable::RenderOverDraw image is nullptr");
326 return;
327 }
328 Drawing::Brush brush;
329 auto overdrawColors = RSOverdrawController::GetInstance().GetColorArray();
330 auto colorFilter = Drawing::ColorFilter::CreateOverDrawColorFilter(overdrawColors.data());
331 Drawing::Filter filter;
332 filter.SetColorFilter(colorFilter);
333 brush.SetFilter(filter);
334 curCanvas_->AttachBrush(brush);
335 curCanvas_->DrawImage(*image, 0, 0, Drawing::SamplingOptions());
336 curCanvas_->DetachBrush();
337 }
338
IsForceCommit(uint32_t forceCommitReason,bool needForceUpdateHwcNode,bool hasHardCursor)339 static inline bool IsForceCommit(uint32_t forceCommitReason, bool needForceUpdateHwcNode,
340 bool hasHardCursor)
341 {
342 /* force commit in 3 situations:
343 1.force commit reasons is not hwc nodes updated or cursor moved
344 2.hwc nodes forced commit and hwc nodes is visible
345 3.soft cursor's position changed */
346 return (forceCommitReason & ~(ForceCommitReason::FORCED_BY_HWC_UPDATE |
347 ForceCommitReason::FORCED_BY_POINTER_WINDOW)) ||
348 ((forceCommitReason & ForceCommitReason::FORCED_BY_HWC_UPDATE) && needForceUpdateHwcNode) ||
349 ((forceCommitReason & ForceCommitReason::FORCED_BY_POINTER_WINDOW) && !hasHardCursor);
350 }
351
CheckScreenNodeSkip(RSScreenRenderParams & params,std::shared_ptr<RSProcessor> processor)352 bool RSScreenRenderNodeDrawable::CheckScreenNodeSkip(
353 RSScreenRenderParams& params, std::shared_ptr<RSProcessor> processor)
354 {
355 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
356 if (params.HasChildCrossNode() && !params.IsMirrorScreen() &&
357 uniParam->GetCrossNodeOffScreenStatus() != CrossNodeOffScreenRenderDebugType::DISABLED) {
358 return false;
359 }
360 if (GetSyncDirtyManager()->IsCurrentFrameDirty() ||
361 (params.GetMainAndLeashSurfaceDirty() || RSUifirstManager::Instance().HasForceUpdateNode()) ||
362 RSMainThread::Instance()->GetDirtyFlag()) {
363 return false;
364 }
365 if (params.IsHDRStatusChanged()) {
366 RS_LOGD("RSScreenRenderNodeDrawable::CheckScreenNodeSkip IsHDRStatusChanged");
367 return false;
368 }
369
370 RS_LOGD("ScreenNode skip");
371 RS_TRACE_NAME("DisplayNode skip");
372 GpuDirtyRegionCollection::GetInstance().AddSkipProcessFramesNumberForDFX(RSBaseRenderUtil::GetLastSendingPid());
373 #ifdef OHOS_PLATFORM
374 RSJankStatsRenderFrameHelper::GetInstance().SetSkipJankAnimatorFrame(true);
375 #endif
376 auto hardCursorDrawable = RSPointerWindowManager::Instance().GetHardCursorDrawable(GetId());
377 bool hasHardCursor = (hardCursorDrawable != nullptr);
378 bool hardCursorNeedCommit = (hasHardCursor != hardCursorLastCommitSuccess_);
379 auto forceCommitReason = uniParam->GetForceCommitReason();
380 bool layersNeedCommit = IsForceCommit(forceCommitReason, params.GetNeedForceUpdateHwcNodes(), hasHardCursor);
381 RS_TRACE_NAME_FMT("DisplayNode skip, forceCommitReason: %d, forceUpdateByHwcNodes %d, "
382 "byHardCursor: %d", forceCommitReason, params.GetNeedForceUpdateHwcNodes(), hardCursorNeedCommit);
383 if (!layersNeedCommit && !hardCursorNeedCommit) {
384 RS_TRACE_NAME("DisplayNodeSkip skip commit");
385 return true;
386 }
387
388 if (!processor->InitForRenderThread(*this, RSUniRenderThread::Instance().GetRenderEngine())) {
389 RS_LOGE("RSScreenRenderNodeDrawable::CheckScreenNodeSkip processor init failed");
390 return false;
391 }
392 hardCursorLastCommitSuccess_ = hasHardCursor;
393 if (hardCursorDrawable != nullptr) {
394 processor->CreateLayerForRenderThread(*hardCursorDrawable);
395 }
396 auto& hardwareDrawables =
397 RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
398 for (const auto& [screenNodeId, _, drawable] : hardwareDrawables) {
399 if (UNLIKELY(!drawable || !drawable->GetRenderParams()) || screenNodeId != params.GetId()) {
400 continue;
401 }
402
403 if (drawable->GetRenderParams()->GetHardwareEnabled()) {
404 auto surfaceDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(drawable);
405 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
406 // hpae offline
407 if (surfaceParams->GetLayerInfo().useDeviceOffline &&
408 ProcessOfflineSurfaceDrawable(processor, surfaceDrawable, false)) {
409 continue;
410 }
411 processor->CreateLayerForRenderThread(*surfaceDrawable);
412 }
413 }
414 if (!RSMainThread::Instance()->WaitHardwareThreadTaskExecute()) {
415 RS_LOGW("RSScreenRenderNodeDrawable::CheckScreenNodeSkip: hardwareThread task has too many to Execute"
416 " TaskNum:[%{public}d]", RSHardwareThread::Instance().GetunExecuteTaskNum());
417 RSHardwareThread::Instance().DumpEventQueue();
418 }
419 processor->ProcessScreenSurfaceForRenderThread(*this);
420
421 // commit RCD layers
422
423 DoScreenRcdTask(params, processor);
424 processor->PostProcess();
425 return true;
426 }
427
PostClearMemoryTask() const428 void RSScreenRenderNodeDrawable::PostClearMemoryTask() const
429 {
430 auto& unirenderThread = RSUniRenderThread::Instance();
431 if (unirenderThread.IsDefaultClearMemroyFinished()) {
432 unirenderThread.DefaultClearMemoryCache(); //default clean with no rendering in 5s
433 unirenderThread.SetDefaultClearMemoryFinished(false);
434 }
435 }
436
SetScreenNodeSkipFlag(RSRenderThreadParams & uniParam,bool flag)437 void RSScreenRenderNodeDrawable::SetScreenNodeSkipFlag(RSRenderThreadParams& uniParam, bool flag)
438 {
439 isScreenNodeSkipStatusChanged_ = (isScreenNodeSkip_ != flag);
440 isScreenNodeSkip_ = flag;
441 uniParam.SetForceMirrorScreenDirty(isScreenNodeSkipStatusChanged_ && isScreenNodeSkip_);
442 }
443
CheckFilterCacheFullyCovered(RSSurfaceRenderParams & surfaceParams,RectI screenRect)444 void RSScreenRenderNodeDrawable::CheckFilterCacheFullyCovered(RSSurfaceRenderParams& surfaceParams, RectI screenRect)
445 {
446 surfaceParams.SetFilterCacheFullyCovered(false);
447 if (!surfaceParams.IsTransparent() || surfaceParams.GetIsRotating() || surfaceParams.GetAttractionAnimation()) {
448 RS_OPTIONAL_TRACE_NAME_FMT("CheckFilterCacheFullyCovered NodeId[%" PRIu64 "], isOpaque: %d, "
449 "isRotating: %d, isAttractionAnimation: %d", surfaceParams.GetId(), !surfaceParams.IsTransparent(),
450 surfaceParams.GetIsRotating(), surfaceParams.GetAttractionAnimation());
451 return;
452 }
453 bool dirtyBelowContainsFilterNode = false;
454 for (auto& filterNodeId : surfaceParams.GetVisibleFilterChild()) {
455 auto drawableAdapter = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(filterNodeId);
456 if (drawableAdapter == nullptr) {
457 continue;
458 }
459 auto filterNodeDrawable = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(drawableAdapter);
460 if (filterNodeDrawable == nullptr) {
461 RS_LOGD("CheckFilterCacheFullyCovered filter node drawable is nullptr, Name[%{public}s],"
462 "NodeId[%" PRIu64 "]", surfaceParams.GetName().c_str(), filterNodeId);
463 continue;
464 }
465 const auto& filterParams = filterNodeDrawable->GetRenderParams();
466 if (filterParams == nullptr || !filterParams->HasBlurFilter()) {
467 RS_LOGD("CheckFilterCacheFullyCovered filter params is nullptr or has no blur, Name[%{public}s],"
468 "NodeId[%" PRIu64 "]", surfaceParams.GetName().c_str(), filterNodeId);
469 continue;
470 }
471 // Filter cache occlusion need satisfy:
472 // 1.The filter node global alpha equals 1;
473 // 2.There is no invalid filter cache node below, which should take snapshot;
474 // 3.The filter node has no global corner;
475 // 4.The node type is not EFFECT_NODE;
476 if (ROSEN_EQ(filterParams->GetGlobalAlpha(), 1.f) && !dirtyBelowContainsFilterNode &&
477 !filterParams->HasGlobalCorner() && filterParams->GetType() != RSRenderNodeType::EFFECT_NODE) {
478 bool cacheValid = filterNodeDrawable->IsFilterCacheValidForOcclusion();
479 RectI filterCachedRect = filterNodeDrawable->GetFilterCachedRegion();
480 surfaceParams.CheckValidFilterCacheFullyCoverTarget(cacheValid, filterCachedRect, screenRect);
481 RSFilterDirtyCollector::RecordFilterCacheValidForOcclusion(filterNodeId,
482 surfaceParams.IsMainWindowType() && cacheValid && screenRect.IsInsideOf(filterCachedRect));
483 }
484 RS_OPTIONAL_TRACE_NAME_FMT("CheckFilterCacheFullyCovered NodeId[%" PRIu64 "], globalAlpha: %f, "
485 "hasInvalidFilterCacheBefore: %d, hasNoCorner: %d, isNodeTypeCorrect: %d, isCacheValid: %d, "
486 "cacheRect: %s", filterNodeId, filterParams->GetGlobalAlpha(), !dirtyBelowContainsFilterNode,
487 !filterParams->HasGlobalCorner(), filterParams->GetType() != RSRenderNodeType::EFFECT_NODE,
488 filterNodeDrawable->IsFilterCacheValidForOcclusion(),
489 filterNodeDrawable->GetFilterCachedRegion().ToString().c_str());
490 if (filterParams->GetEffectNodeShouldPaint() && !filterNodeDrawable->IsFilterCacheValidForOcclusion()) {
491 dirtyBelowContainsFilterNode = true;
492 }
493 }
494 }
495
CheckAndUpdateFilterCacheOcclusionFast()496 void RSScreenRenderNodeDrawable::CheckAndUpdateFilterCacheOcclusionFast()
497 {
498 auto params = static_cast<RSScreenRenderParams*>(renderParams_.get());
499 ScreenId paramScreenId = params->GetScreenId();
500 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
501 if (!screenManager) {
502 SetDrawSkipType(DrawSkipType::SCREEN_MANAGER_NULL);
503 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw ScreenManager is nullptr");
504 return;
505 }
506 ScreenInfo curScreenInfo = screenManager->QueryScreenInfo(paramScreenId);
507 CheckAndUpdateFilterCacheOcclusion(*params, curScreenInfo);
508 filterCacheOcclusionUpdated_ = true;
509 }
510
CheckAndUpdateFilterCacheOcclusion(RSScreenRenderParams & params,const ScreenInfo & screenInfo)511 void RSScreenRenderNodeDrawable::CheckAndUpdateFilterCacheOcclusion(
512 RSScreenRenderParams& params, const ScreenInfo& screenInfo)
513 {
514 if (!RSSystemParameters::GetFilterCacheOcculusionEnabled()) {
515 return;
516 }
517 bool isScreenOccluded = false;
518 RectI screenRect = {0, 0, screenInfo.width, screenInfo.height};
519 // top-down traversal all mainsurface
520 // if upper surface reuse filter cache which fully cover whole screen
521 // mark lower layers for process skip
522 auto& curAllSurfaceDrawables = params.GetAllMainAndLeashSurfaceDrawables();
523 for (const auto& adapter : curAllSurfaceDrawables) {
524 if (adapter == nullptr || adapter->GetNodeType() != RSRenderNodeType::SURFACE_NODE) {
525 RS_LOGD("CheckAndUpdateFilterCacheOcclusion adapter is nullptr or error type");
526 continue;
527 }
528 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(adapter);
529 if (surfaceNodeDrawable == nullptr) {
530 RS_LOGD("CheckAndUpdateFilterCacheOcclusion surfaceNodeDrawable is nullptr");
531 continue;
532 }
533 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
534 if (surfaceParams == nullptr) {
535 RS_LOGD("CheckAndUpdateFilterCacheOcclusion surface params is nullptr");
536 continue;
537 }
538
539 CheckFilterCacheFullyCovered(*surfaceParams, screenRect);
540
541 if (surfaceParams->IsMainWindowType()) {
542 // reset occluded status for all mainwindow
543 surfaceParams->SetOccludedByFilterCache(isScreenOccluded);
544 }
545 isScreenOccluded = isScreenOccluded || surfaceParams->GetFilterCacheFullyCovered();
546 }
547 }
548
GetBufferAge()549 int32_t RSScreenRenderNodeDrawable::GetBufferAge()
550 {
551 return expandRenderFrame_ ? expandRenderFrame_->GetBufferAge() : 0;
552 }
553
SetDamageRegion(const std::vector<RectI> & rects)554 void RSScreenRenderNodeDrawable::SetDamageRegion(const std::vector<RectI>& rects)
555 {
556 if (expandRenderFrame_ == nullptr) {
557 return;
558 }
559 expandRenderFrame_->SetDamageRegion(rects);
560 }
561
OnDraw(Drawing::Canvas & canvas)562 void RSScreenRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
563 {
564 Drawing::GPUResourceTag::SetCurrentNodeId(GetId());
565 SetDrawSkipType(DrawSkipType::NONE);
566 // canvas will generate in every request frame
567 (void)canvas;
568
569 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
570 if (UNLIKELY(!renderParams_ || !uniParam)) {
571 SetDrawSkipType(DrawSkipType::RENDER_PARAMS_OR_UNI_PARAMS_NULL);
572 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw renderParams/uniParam is null!");
573 return;
574 }
575 auto params = static_cast<RSScreenRenderParams*>(renderParams_.get());
576 if (params->GetChildDisplayCount() == 0) {
577 SetDrawSkipType(DrawSkipType::NO_DISPLAY_NODE);
578 return;
579 }
580 auto screenInfo = params->GetScreenInfo();
581 if (screenInfo.state == ScreenState::DISABLED) {
582 SetDrawSkipType(DrawSkipType::SCREEN_STATE_INVALID);
583 return;
584 }
585 // [Attention] do not return before layer created set false, otherwise will result in buffer not released
586 auto& hardwareDrawables = uniParam->GetHardwareEnabledTypeDrawables();
587 for (const auto& [screenNodeId, _, drawable] : hardwareDrawables) {
588 if (UNLIKELY(!drawable || !drawable->GetRenderParams()) ||
589 screenNodeId != params->GetId()) {
590 continue;
591 }
592 drawable->GetRenderParams()->SetLayerCreated(false);
593 }
594 auto& hardCursorDrawables = uniParam->GetHardCursorDrawables();
595 auto iter = std::find_if(hardCursorDrawables.begin(), hardCursorDrawables.end(), [id = GetId()](const auto& node) {
596 return std::get<0>(node) == id;
597 });
598 if (iter != hardCursorDrawables.end()) {
599 auto drawable = std::get<2>(*iter);
600 if (drawable && drawable->GetRenderParams()) {
601 drawable->GetRenderParams()->SetLayerCreated(false);
602 }
603 }
604
605 // if screen power off, skip on draw, needs to draw one more frame.
606 isRenderSkipIfScreenOff_ = RSUniRenderUtil::CheckRenderSkipIfScreenOff(true, params->GetScreenId());
607 if (isRenderSkipIfScreenOff_) {
608 SetDrawSkipType(DrawSkipType::RENDER_SKIP_IF_SCREEN_OFF);
609 return;
610 }
611
612 if (CheckScreenFreezeSkip(*params)) {
613 return;
614 }
615
616 PostClearMemoryTask();
617
618 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
619 if (!screenManager) {
620 SetDrawSkipType(DrawSkipType::SCREEN_MANAGER_NULL);
621 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw ScreenManager is nullptr");
622 return;
623 }
624
625 if (RSSystemProperties::IsFoldScreenFlag() && screenManager->IsScreenSwitching()) {
626 SetDrawSkipType(DrawSkipType::RENDER_SKIP_IF_SCREEN_SWITCHING);
627 RS_LOGI("RSScreenRenderNodeDrawable::OnDraw FoldScreenNodeSwitching is true, do not drawframe");
628 RS_TRACE_NAME_FMT("RSScreenRenderNodeDrawable FoldScreenNodeSwitching is true");
629 return;
630 }
631
632 // dfx
633 RSRenderNodeDrawable::InitDfxForCacheInfo();
634 // set for cache and draw cross node in extended screen model
635 uniParam->SetIsMirrorScreen(params->IsMirrorScreen());
636 uniParam->SetCurrentVisitDisplayDrawableId(GetId());
637 uniParam->SetIsFirstVisitCrossNodeDisplay(params->IsFirstVisitCrossNodeDisplay());
638 uniParam->SetCompositeType(params->GetCompositeType());
639 params->SetDirtyAlignEnabled(uniParam->IsDirtyAlignEnabled());
640 ScreenId paramScreenId = params->GetScreenId();
641 offsetX_ = params->GetScreenOffsetX();
642 offsetY_ = params->GetScreenOffsetY();
643 curDisplayScreenId_ = paramScreenId;
644 RS_LOGD("RSScreenRenderNodeDrawable::OnDraw curScreenId=[%{public}" PRIu64 "], "
645 "offsetX=%{public}d, offsetY=%{public}d", paramScreenId, offsetX_, offsetY_);
646
647 auto syncDirtyManager = GetSyncDirtyManager();
648 const RectI& dirtyRegion = syncDirtyManager->GetCurrentFrameDirtyRegion();
649 const auto& activeSurfaceRect = syncDirtyManager->GetActiveSurfaceRect().IsEmpty() ?
650 syncDirtyManager->GetSurfaceRect() : syncDirtyManager->GetActiveSurfaceRect();
651 uint32_t vsyncRefreshRate = RSMainThread::Instance()->GetVsyncRefreshRate();
652 RS_TRACE_NAME_FMT("RSScreenRenderNodeDrawable::OnDraw[%" PRIu64 "][%" PRIu64"] zoomed(%d), "
653 "currentFrameDirty(%d, %d, %d, %d), screen(%d, %d), active(%d, %d, %d, %d), vsyncRefreshRate(%u)",
654 paramScreenId, GetId(), params->GetZoomed(),
655 dirtyRegion.left_, dirtyRegion.top_, dirtyRegion.width_, dirtyRegion.height_,
656 screenInfo.width, screenInfo.height,
657 activeSurfaceRect.left_, activeSurfaceRect.top_, activeSurfaceRect.width_, activeSurfaceRect.height_,
658 vsyncRefreshRate);
659 RS_LOGD("RSScreenRenderNodeDrawable::OnDraw node: %{public}" PRIu64 "", GetId());
660 ScreenId activeScreenId = HgmCore::Instance().GetActiveScreenId();
661
662 // when set expectedRefreshRate, the vsyncRefreshRate maybe change from 60 to 120
663 // so that need change whether equal vsync period and whether use virtual dirty
664 if (screenInfo.skipFrameStrategy == SKIP_FRAME_BY_REFRESH_RATE) {
665 bool isEqualVsyncPeriod = (vsyncRefreshRate == screenInfo.expectedRefreshRate);
666 if (screenInfo.isEqualVsyncPeriod != isEqualVsyncPeriod) {
667 screenInfo.isEqualVsyncPeriod = isEqualVsyncPeriod;
668 screenManager->SetEqualVsyncPeriod(paramScreenId, isEqualVsyncPeriod);
669 }
670 }
671 screenManager->RemoveForceRefreshTask();
672
673 bool isVirtualExpandComposite =
674 params->GetCompositeType() == CompositeType::UNI_RENDER_EXPAND_COMPOSITE;
675 if (isVirtualExpandComposite) {
676 RSUniDirtyComputeUtil::UpdateVirtualExpandScreenAccumulatedParams(*params, *this);
677 if (RSUniDirtyComputeUtil::CheckVirtualExpandScreenSkip(*params, *this)) {
678 RS_TRACE_NAME("VirtualExpandScreenNode skip");
679 return;
680 }
681 }
682
683 if (SkipFrame(vsyncRefreshRate, screenInfo)) {
684 SetDrawSkipType(DrawSkipType::SKIP_FRAME);
685 RS_TRACE_NAME_FMT("SkipFrame, screenId:%lu, strategy:%d, interval:%u, refreshrate:%u", paramScreenId,
686 screenInfo.skipFrameStrategy, screenInfo.skipFrameInterval, screenInfo.expectedRefreshRate);
687 screenManager->PostForceRefreshTask();
688 return;
689 }
690 if (!screenInfo.isEqualVsyncPeriod) {
691 uniParam->SetVirtualDirtyRefresh(true);
692 }
693
694 auto processor = RSProcessorFactory::CreateProcessor(params->GetCompositeType());
695 if (!processor) {
696 SetDrawSkipType(DrawSkipType::CREATE_PROCESSOR_FAIL);
697 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw RSProcessor is null!");
698 return;
699 }
700
701 uniParam->SetRSProcessor(processor);
702 auto mirroredDrawable = params->GetMirrorSourceDrawable().lock();
703 auto mirroredRenderParams = mirroredDrawable ?
704 static_cast<RSScreenRenderParams*>(mirroredDrawable->GetRenderParams().get()) : nullptr;
705 if (mirroredRenderParams ||
706 params->GetCompositeType() == CompositeType::UNI_RENDER_EXPAND_COMPOSITE) {
707 DirtyStatusAutoUpdate dirtyStatusAutoUpdate(*uniParam, params->GetChildDisplayCount() == 1);
708 if (!processor->InitForRenderThread(*this, RSUniRenderThread::Instance().GetRenderEngine())) {
709 SetDrawSkipType(DrawSkipType::RENDER_ENGINE_NULL);
710 syncDirtyManager_->ResetDirtyAsSurfaceSize();
711 syncDirtyManager_->UpdateDirty(false);
712 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw processor init failed!");
713 return;
714 }
715 if (mirroredRenderParams) {
716 offsetX_ = mirroredRenderParams->GetScreenOffsetX();
717 offsetY_ = mirroredRenderParams->GetScreenOffsetY();
718 RSUniRenderThread::Instance().SetEnableVisibleRect(screenInfo.enableVisibleRect);
719 if (screenInfo.enableVisibleRect) {
720 const auto& rect = screenManager->GetMirrorScreenVisibleRect(paramScreenId);
721 auto curVisibleRect = Drawing::RectI(rect.x, rect.y, rect.x + rect.w, rect.y + rect.h);
722 RSUniRenderThread::Instance().SetVisibleRect(curVisibleRect);
723 }
724 if (params->GetCompositeType() == CompositeType::UNI_RENDER_COMPOSITE) {
725 SetDrawSkipType(DrawSkipType::WIRED_SCREEN_PROJECTION);
726 RSUniRenderThread::Instance().WaitUntilScreenNodeBufferReleased(*this);
727 expandRenderFrame_ = RequestFrame(*params, processor);
728 if (!expandRenderFrame_) {
729 SetDrawSkipType(DrawSkipType::REQUEST_FRAME_FAIL);
730 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw failed to request frame");
731 return;
732 }
733 auto drSurface = expandRenderFrame_->GetFrame()->GetSurface();
734 if (!drSurface) {
735 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw DrawingSurface is null");
736 return;
737 }
738 curCanvas_ = std::make_shared<RSPaintFilterCanvas>(drSurface.get());
739 RSRenderNodeDrawable::OnDraw(*curCanvas_);
740 expandRenderFrame_->Flush();
741 processor->ProcessScreenSurfaceForRenderThread(*this);
742 HardCursorCreateLayer(processor);
743 processor->PostProcess();
744 expandRenderFrame_ = nullptr;
745 return;
746 }
747 auto virtualProcessor = RSProcessor::ReinterpretCast<RSUniRenderVirtualProcessor>(processor);
748 if (!virtualProcessor) {
749 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw virtualProcessor is null!");
750 return;
751 }
752 curCanvas_ = virtualProcessor->GetCanvas();
753 RSRenderNodeDrawable::OnDraw(*curCanvas_);
754 params->ResetVirtualExpandAccumulatedParams();
755 } else {
756 RS_LOGD("RSScreenRenderNodeDrawable::OnDraw Expand screen.");
757 bool isOpDropped = uniParam->IsOpDropped();
758 uniParam->SetOpDropped(false);
759 auto expandProcessor = RSProcessor::ReinterpretCast<RSUniRenderVirtualProcessor>(processor);
760 if (!expandProcessor) {
761 SetDrawSkipType(DrawSkipType::EXPAND_PROCESSOR_NULL);
762 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw expandProcessor is null!");
763 return;
764 }
765 RSDirtyRectsDfx rsDirtyRectsDfx(*this);
766 std::vector<RectI> damageRegionRects;
767 // disable expand screen dirty when isEqualVsyncPeriod is false, because the dirty history is incorrect
768 if (uniParam->IsExpandScreenDirtyEnabled() && uniParam->IsVirtualDirtyEnabled() &&
769 screenInfo.isEqualVsyncPeriod) {
770 int32_t bufferAge = expandProcessor->GetBufferAge();
771 damageRegionRects = RSUniRenderUtil::MergeDirtyHistory(
772 *this, bufferAge, screenInfo, rsDirtyRectsDfx, *params);
773 uniParam->Reset();
774 if (!uniParam->IsVirtualDirtyDfxEnabled()) {
775 expandProcessor->SetDirtyInfo(damageRegionRects);
776 }
777 } else {
778 std::vector<RectI> emptyRects = {};
779 expandProcessor->SetRoiRegionToCodec(emptyRects);
780 }
781 rsDirtyRectsDfx.SetVirtualDirtyRects(damageRegionRects, screenInfo);
782 curCanvas_ = expandProcessor->GetCanvas();
783 curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
784 RSRenderNodeDrawable::OnDraw(*curCanvas_);
785 params->ResetVirtualExpandAccumulatedParams();
786 auto targetSurfaceRenderNodeDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(
787 params->GetTargetSurfaceRenderNodeDrawable().lock());
788 if ((targetSurfaceRenderNodeDrawable || params->HasMirrorScreen()) && curCanvas_->GetSurface()) {
789 RS_TRACE_NAME("DrawExpandScreen cacheImgForMultiScreenView");
790 cacheImgForMultiScreenView_ = curCanvas_->GetSurface()->GetImageSnapshot();
791 } else {
792 cacheImgForMultiScreenView_ = nullptr;
793 }
794 // Restore the initial state of the canvas to avoid state accumulation
795 curCanvas_->RestoreToCount(0);
796 if (curCanvas_) {
797 rsDirtyRectsDfx.OnDrawVirtual(*curCanvas_);
798 }
799 uniParam->SetOpDropped(isOpDropped);
800 }
801 DrawCurtainScreen();
802 processor->PostProcess();
803 SetDrawSkipType(DrawSkipType::MIRROR_DRAWABLE_SKIP);
804 return;
805 }
806
807 bool isHdrOn = params->GetHDRPresent();
808 // 0 means defalut hdrBrightnessRatio
809 float hdrBrightnessRatio = RSLuminanceControl::Get().GetHdrBrightnessRatio(paramScreenId, 0);
810 #ifdef RS_ENABLE_OVERLAY_DISPLAY // only for TV
811 /*
812 * Force hdrBrightnessRatio to be set to 1.0 when overlay_display display enabled.
813 * Do not change pixel value; the pixel value is encoded when overlay display enabled.
814 * If hdrBrightnessRatio is not equal 1.0, DSS will change the pixel value, so the
815 * decoded pixels is wrong and display is abnormal.
816 */
817 if (RSOverlayDisplayManager::Instance().IsOverlayDisplayEnableForCurrentVsync()) {
818 hdrBrightnessRatio = 1.0f;
819 }
820 #endif
821 if (!isHdrOn) {
822 params->SetBrightnessRatio(hdrBrightnessRatio);
823 hdrBrightnessRatio = 1.0f;
824 }
825 params->SetHdrBrightnessRatio(hdrBrightnessRatio);
826 RS_LOGD("RSScreenRenderNodeDrawable::OnDraw HDRDraw isHdrOn: %{public}d, BrightnessRatio: %{public}f",
827 isHdrOn, hdrBrightnessRatio);
828
829 // checkScreenNodeSkip need to be judged at the end
830 if (RSAncoManager::Instance()->GetAncoHebcStatus() == AncoHebcStatus::INITIAL &&
831 uniParam->IsOpDropped() && CheckScreenNodeSkip(*params, processor)) {
832 SetDrawSkipType(DrawSkipType::SCREEN_NODE_SKIP);
833 RSMainThread::Instance()->SetFrameIsRender(false);
834 SetScreenNodeSkipFlag(*uniParam, true);
835 return;
836 }
837 SetScreenNodeSkipFlag(*uniParam, false);
838 RSMainThread::Instance()->SetFrameIsRender(true);
839
840 if (filterCacheOcclusionUpdated_) {
841 filterCacheOcclusionUpdated_ = false;
842 } else {
843 CheckAndUpdateFilterCacheOcclusion(*params, screenInfo);
844 }
845 if (isHdrOn) {
846 params->SetNewPixelFormat(RSHdrUtil::GetRGBA1010108Enabled() && params->GetExistHWCNode() ?
847 GRAPHIC_PIXEL_FMT_RGBA_1010108 : GRAPHIC_PIXEL_FMT_RGBA_1010102);
848 }
849 // hpae offline: post offline task
850 CheckAndPostAsyncProcessOfflineTask();
851 RSUniRenderThread::Instance().WaitUntilScreenNodeBufferReleased(*this);
852 // displayNodeSp to get rsSurface witch only used in renderThread
853 auto renderFrame = RequestFrame(*params, processor);
854 if (!renderFrame) {
855 SetDrawSkipType(DrawSkipType::REQUEST_FRAME_FAIL);
856 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw failed to request frame");
857 return;
858 }
859
860 UpdateSlrScale(screenInfo);
861 RSDirtyRectsDfx rsDirtyRectsDfx(*this);
862 std::vector<RectI> damageRegionrects;
863 std::vector<RectI> curFrameVisibleRegionRects;
864 Drawing::Region clipRegion;
865 if (uniParam->IsPartialRenderEnabled()) {
866 damageRegionrects = RSUniRenderUtil::MergeDirtyHistory(
867 *this, renderFrame->GetBufferAge(), screenInfo, rsDirtyRectsDfx, *params);
868 curFrameVisibleRegionRects = RSUniDirtyComputeUtil::GetCurrentFrameVisibleDirty(*this, screenInfo, *params);
869 uniParam->Reset();
870 clipRegion = GetFlippedRegion(damageRegionrects, screenInfo);
871 RS_TRACE_NAME_FMT("SetDamageRegion damageRegionrects num: %zu, info: %s",
872 damageRegionrects.size(), RectVectorToString(damageRegionrects).c_str());
873 if (!uniParam->IsRegionDebugEnabled()) {
874 renderFrame->SetDamageRegion(damageRegionrects);
875 }
876 }
877
878 auto drSurface = renderFrame->GetFrame()->GetSurface();
879 if (!drSurface) {
880 SetDrawSkipType(DrawSkipType::SURFACE_NULL);
881 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw DrawingSurface is null");
882 return;
883 }
884
885 curCanvas_ = std::make_shared<RSPaintFilterCanvas>(drSurface.get());
886 if (!curCanvas_) {
887 SetDrawSkipType(DrawSkipType::CANVAS_NULL);
888 RS_LOGE("RSScreenRenderNodeDrawable::OnDraw failed to create canvas");
889 return;
890 }
891 curCanvas_->SetDrawnRegion(params->GetDrawnRegion());
892 curCanvas_->SetTargetColorGamut(params->GetNewColorSpace());
893 curCanvas_->SetScreenId(paramScreenId);
894 curCanvas_->SetHdrOn(isHdrOn);
895 curCanvas_->SetDisableFilterCache(params->GetZoomed());
896
897 #ifdef DDGR_ENABLE_FEATURE_OPINC
898 if (RSOpincDrawCache::IsAutoCacheEnable()) {
899 RSOpincDrawCache::SetScreenRectInfo({0, 0, screenInfo.width, screenInfo.height});
900 }
901 #endif
902 UpdateSurfaceDrawRegion(curCanvas_, params);
903
904 // canvas draw
905 {
906 {
907 RSSkpCaptureDfx capture(curCanvas_);
908 Drawing::AutoCanvasRestore acr(*curCanvas_, true);
909
910 #ifdef SUBTREE_PARALLEL_ENABLE
911 RSParallelManager::Singleton().Reset(curCanvas_, uniParam, params, vsyncRefreshRate);
912 #endif
913 if (uniParam->IsOpDropped()) {
914 if (uniParam->IsDirtyAlignEnabled()) {
915 RS_TRACE_NAME_FMT("dirty align enabled and no clip operation");
916 curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
917 } else {
918 uniParam->SetClipRegion(clipRegion);
919 ClipRegion(*curCanvas_, clipRegion);
920 }
921 } else {
922 curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
923 }
924 // just used in SubTree, used for check whether a new Surface needs to be created in the SubTree thread.
925 curCanvas_->SetWeakSurface(drSurface);
926
927 curCanvas_->SetHighContrast(RSUniRenderThread::Instance().IsHighContrastTextModeOn());
928 // cpu boost feature start
929 ffrt_cpu_boost_start(CPUBOOST_START_POINT + 1);
930 RSRenderNodeDrawable::OnDraw(*curCanvas_);
931 // cpu boost feature end
932 ffrt_cpu_boost_end(CPUBOOST_START_POINT + 1);
933 curCanvas_->Save();
934 curCanvas_->ResetMatrix();
935 if (screenInfo.isSamplingOn) {
936 curCanvas_->ConcatMatrix(params->GetSlrMatrix());
937 }
938 rsDirtyRectsDfx.OnDraw(*curCanvas_);
939 curCanvas_->Restore();
940 DrawCurtainScreen();
941 bool displayP3Enable = (params->GetNewColorSpace() == GRAPHIC_COLOR_GAMUT_DISPLAY_P3);
942 RSUniRenderUtil::SwitchColorFilter(*curCanvas_, hdrBrightnessRatio, displayP3Enable);
943
944 #ifdef RS_ENABLE_OVERLAY_DISPLAY
945 // add post filter for TV overlay display conversion
946 RSOverlayDisplayManager::Instance().PostProcFilter(*curCanvas_);
947 #endif
948 auto dirtyManager = GetSyncDirtyManager();
949 const auto& activeRect = dirtyManager->GetActiveSurfaceRect();
950 if (!activeRect.IsEmpty() && (!dirtyManager->GetDirtyRegion().IsInsideOf(activeRect) ||
951 !uniParam->IsPartialRenderEnabled() || uniParam->IsRegionDebugEnabled())) {
952 RS_TRACE_NAME_FMT("global dirty region:[%s] is not inside of active surface rect:[%s], "
953 "clear extra area to black", dirtyManager->GetDirtyRegion().ToString().c_str(),
954 activeRect.ToString().c_str());
955 curCanvas_->Save();
956 auto activeRegion = RSUniDirtyComputeUtil::ScreenIntersectDirtyRects(
957 Occlusion::Region(activeRect), screenInfo);
958 curCanvas_->ClipRegion(GetFlippedRegion(activeRegion, screenInfo), Drawing::ClipOp::DIFFERENCE);
959 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
960 curCanvas_->Restore();
961 }
962 }
963
964 if (RSSystemProperties::GetDrawMirrorCacheImageEnabled() && params->HasMirrorScreen() &&
965 curCanvas_->GetSurface() != nullptr) {
966 cacheImgForMultiScreenView_ = curCanvas_->GetSurface()->GetImageSnapshot();
967 } else {
968 cacheImgForMultiScreenView_ = nullptr;
969 }
970 }
971 RenderOverDraw();
972 RSMainThread::Instance()->SetDirtyFlag(false);
973
974 if (Drawing::PerformanceCaculate::GetDrawingFlushPrint()) {
975 RS_LOGI("Drawing Performance Flush start %{public}lld", Drawing::PerformanceCaculate::GetUpTime(false));
976 }
977 #ifdef SUBTREE_PARALLEL_ENABLE
978 // Wait for all sub threads process completely.
979 RSParallelManager::Singleton().WaitUntilSubTreeFinish(curCanvas_);
980 #endif
981 RS_TRACE_BEGIN("RSScreenRenderNodeDrawable Flush");
982 RsFrameReport::GetInstance().CheckBeginFlushPoint();
983 Drawing::GPUResourceTag::SetCurrentNodeId(GetId());
984
985 renderFrame->Flush();
986 RS_TRACE_END();
987 if (Drawing::PerformanceCaculate::GetDrawingFlushPrint()) {
988 RS_LOGI("Drawing Performance Flush end %{public}lld", Drawing::PerformanceCaculate::GetUpTime(false));
989 Drawing::PerformanceCaculate::ResetCaculateTimeCount();
990 }
991
992 // process round corner display
993 DoScreenRcdTask(*params, processor);
994
995 if (!RSMainThread::Instance()->WaitHardwareThreadTaskExecute()) {
996 RS_LOGW("RSScreenRenderNodeDrawable::ondraw: hardwareThread task has too many to Execute"
997 " TaskNum:[%{public}d]", RSHardwareThread::Instance().GetunExecuteTaskNum());
998 RSHardwareThread::Instance().DumpEventQueue();
999 }
1000
1001 RS_TRACE_BEGIN("RSScreenRenderNodeDrawable CommitLayer");
1002 for (const auto& [screenNodeId, _, drawable] : hardwareDrawables) {
1003 if (UNLIKELY(!drawable || !drawable->GetRenderParams())) {
1004 continue;
1005 }
1006 auto surfaceDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(drawable);
1007 if (!surfaceDrawable || screenNodeId != params->GetId()) {
1008 continue;
1009 }
1010 if (drawable->GetRenderParams()->GetHardwareEnabled()) {
1011 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
1012 // hpae offline: wait task and create layer
1013 if (surfaceParams->GetLayerInfo().useDeviceOffline &&
1014 ProcessOfflineSurfaceDrawable(processor, surfaceDrawable, true)) {
1015 continue;
1016 }
1017 processor->CreateLayerForRenderThread(*surfaceDrawable);
1018 }
1019 }
1020 HardCursorCreateLayer(processor);
1021 if (screenInfo.activeRect.IsEmpty() ||
1022 screenInfo.activeRect == RectI(0, 0, screenInfo.width, screenInfo.height) ||
1023 DirtyRegionParam::IsComposeDirtyRegionEnableInPartialDisplay()) {
1024 if (uniParam->IsRegionDebugEnabled()) {
1025 std::vector<RectI> emptyRegionRects = {};
1026 SetDirtyRects(emptyRegionRects);
1027 } else {
1028 SetDirtyRects(RSSystemProperties::GetOptimizeHwcComposeAreaEnabled() ?
1029 curFrameVisibleRegionRects : damageRegionrects);
1030 }
1031 } else {
1032 SetDirtyRects({GetSyncDirtyManager()->GetRectFlipWithinSurface(screenInfo.activeRect)});
1033 }
1034 processor->ProcessScreenSurfaceForRenderThread(*this);
1035 processor->PostProcess();
1036 RS_TRACE_END();
1037
1038 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
1039 if (RSMagicPointerRenderManager::GetInstance().GetPointerColorInversionEnabled() && !mirroredDrawable) {
1040 RSMagicPointerRenderManager::GetInstance().ProcessColorPicker(processor, curCanvas_->GetGPUContext());
1041 RSMagicPointerRenderManager::GetInstance().SetCacheImgForPointer(nullptr);
1042 }
1043 #endif
1044 }
1045
UpdateSlrScale(ScreenInfo & screenInfo)1046 void RSScreenRenderNodeDrawable::UpdateSlrScale(ScreenInfo& screenInfo)
1047 {
1048 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
1049 uniParam->SetSLRScaleManager(nullptr);
1050 if (screenInfo.isSamplingOn && RSSystemProperties::GetSLRScaleEnabled()) {
1051 auto scaleManager = std::make_shared<RSSLRScaleFunction>(
1052 screenInfo.phyWidth, screenInfo.phyHeight, screenInfo.width, screenInfo.height);
1053 screenInfo.samplingDistance = scaleManager->GetKernelSize();
1054 uniParam->SetSLRScaleManager(scaleManager);
1055 }
1056 }
1057
DrawCurtainScreen() const1058 void RSScreenRenderNodeDrawable::DrawCurtainScreen() const
1059 {
1060 if (!RSUniRenderThread::Instance().IsCurtainScreenOn() || !curCanvas_) {
1061 return;
1062 }
1063 RS_TRACE_FUNC();
1064 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
1065 }
1066
UpdateSurfaceDrawRegion(std::shared_ptr<RSPaintFilterCanvas> & mainCanvas,RSScreenRenderParams * params)1067 void RSScreenRenderNodeDrawable::UpdateSurfaceDrawRegion(std::shared_ptr<RSPaintFilterCanvas>& mainCanvas,
1068 RSScreenRenderParams* params)
1069 {
1070 auto& curAllSurfaces = params->GetAllMainAndLeashSurfaceDrawables();
1071
1072 for (auto& renderNodeDrawable : curAllSurfaces) {
1073 if (renderNodeDrawable != nullptr &&
1074 renderNodeDrawable->GetNodeType() == RSRenderNodeType::SURFACE_NODE) {
1075 auto surfaceNodeDrawable =
1076 std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(renderNodeDrawable);
1077 surfaceNodeDrawable->UpdateSurfaceDirtyRegion(mainCanvas);
1078 }
1079 }
1080 }
1081
1082 #ifndef ROSEN_CROSS_PLATFORM
CreateSurface(sptr<IBufferConsumerListener> listener)1083 bool RSScreenRenderNodeDrawable::CreateSurface(sptr<IBufferConsumerListener> listener)
1084 {
1085 auto consumer = surfaceHandler_->GetConsumer();
1086 if (consumer != nullptr && surface_ != nullptr) {
1087 RS_LOGI("RSScreenRenderNodeDrawable::CreateSurface already created, return");
1088 return true;
1089 }
1090 consumer = IConsumerSurface::Create("ScreenNode");
1091 if (consumer == nullptr) {
1092 RS_LOGE("RSScreenRenderNodeDrawable::CreateSurface get consumer surface fail");
1093 return false;
1094 }
1095 SurfaceError ret = consumer->RegisterConsumerListener(listener);
1096 if (ret != SURFACE_ERROR_OK) {
1097 RS_LOGE("RSScreenRenderNodeDrawable::CreateSurface RegisterConsumerListener fail");
1098 return false;
1099 }
1100 consumerListener_ = listener;
1101 auto producer = consumer->GetProducer();
1102 sptr<Surface> surface = Surface::CreateSurfaceAsProducer(producer);
1103 if (!surface) {
1104 RS_LOGE("RSScreenRenderNodeDrawable::CreateSurface CreateSurfaceAsProducer fail");
1105 return false;
1106 }
1107 surface->SetQueueSize(BUFFER_SIZE);
1108 auto client = std::static_pointer_cast<RSRenderServiceClient>(RSIRenderClient::CreateRenderServiceClient());
1109 surface_ = client->CreateRSSurface(surface);
1110 RS_LOGI("RSScreenRenderNodeDrawable::CreateSurface end");
1111 surfaceCreated_ = true;
1112 surfaceHandler_->SetConsumer(consumer);
1113 return true;
1114 }
1115 #endif
1116
SkipFrameByInterval(uint32_t refreshRate,uint32_t skipFrameInterval)1117 bool RSScreenRenderNodeDrawable::SkipFrameByInterval(uint32_t refreshRate, uint32_t skipFrameInterval)
1118 {
1119 if (refreshRate == 0 || skipFrameInterval <= 1) {
1120 return false;
1121 }
1122 int64_t currentTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
1123 std::chrono::steady_clock::now().time_since_epoch()).count();
1124 // the skipFrameInterval is equal to 60 divide the virtual screen refresh rate
1125 int64_t refreshInterval = currentTime - lastRefreshTime_;
1126 // 1000000000ns == 1s, 110/100 allows 10% over.
1127 bool needSkip = refreshInterval < (1000000000LL / refreshRate) * (skipFrameInterval - 1) * 110 / 100;
1128 if (!needSkip) {
1129 lastRefreshTime_ = currentTime;
1130 }
1131 return needSkip;
1132 }
1133
SkipFrameByRefreshRate(uint32_t refreshRate,uint32_t expectedRefreshRate)1134 bool RSScreenRenderNodeDrawable::SkipFrameByRefreshRate(uint32_t refreshRate, uint32_t expectedRefreshRate)
1135 {
1136 if (refreshRate == 0 || expectedRefreshRate == 0 || refreshRate == expectedRefreshRate) {
1137 return false;
1138 }
1139 int64_t currentTime = RSMainThread::Instance()->GetCurrentVsyncTime();
1140 int64_t minFrameInterval = 1000000000LL / expectedRefreshRate;
1141 if (minFrameInterval == 0) {
1142 return false;
1143 }
1144 // lastRefreshTime_ is next frame expected refresh time for virtual display
1145 if (lastRefreshTime_ <= 0) {
1146 lastRefreshTime_ = currentTime + minFrameInterval;
1147 return false;
1148 }
1149 if (currentTime < (lastRefreshTime_ - MAX_JITTER_NS)) {
1150 return true;
1151 }
1152 int64_t intervalNums = (currentTime - lastRefreshTime_ + MAX_JITTER_NS) / minFrameInterval;
1153 lastRefreshTime_ += (intervalNums + 1) * minFrameInterval;
1154 return false;
1155 }
1156
SkipFrame(uint32_t refreshRate,ScreenInfo screenInfo)1157 bool RSScreenRenderNodeDrawable::SkipFrame(uint32_t refreshRate, ScreenInfo screenInfo)
1158 {
1159 bool needSkip = false;
1160 switch (screenInfo.skipFrameStrategy) {
1161 case SKIP_FRAME_BY_INTERVAL:
1162 needSkip = SkipFrameByInterval(refreshRate, screenInfo.skipFrameInterval);
1163 break;
1164 case SKIP_FRAME_BY_REFRESH_RATE:
1165 needSkip = SkipFrameByRefreshRate(refreshRate, screenInfo.expectedRefreshRate);
1166 break;
1167 default:
1168 break;
1169 }
1170 return needSkip;
1171 }
1172
ProcessOfflineSurfaceDrawable(const std::shared_ptr<RSProcessor> & processor,std::shared_ptr<RSSurfaceRenderNodeDrawable> & surfaceDrawable,bool async)1173 bool RSScreenRenderNodeDrawable::ProcessOfflineSurfaceDrawable(
1174 const std::shared_ptr<RSProcessor>& processor,
1175 std::shared_ptr<RSSurfaceRenderNodeDrawable>& surfaceDrawable, bool async)
1176 {
1177 if (processor->ProcessOfflineLayer(surfaceDrawable, async)) {
1178 // use offline layer to display
1179 return true;
1180 }
1181 // reset offline tag, use original layer to display
1182 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceDrawable->GetRenderParams().get());
1183 surfaceParams->SetUseDeviceOffline(false);
1184 return false;
1185 }
1186
CheckAndPostAsyncProcessOfflineTask()1187 void RSScreenRenderNodeDrawable::CheckAndPostAsyncProcessOfflineTask()
1188 {
1189 auto& hardwareDrawables =
1190 RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
1191 for (const auto& [screenNodeId, _, drawable] : hardwareDrawables) {
1192 if (UNLIKELY(!drawable || !drawable->GetRenderParams())) {
1193 continue;
1194 }
1195 auto params = static_cast<RSScreenRenderParams*>(renderParams_.get());
1196 if (screenNodeId != params->GetId()) {
1197 continue;
1198 }
1199 auto surfaceDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(drawable);
1200 if (surfaceDrawable->GetRenderParams()->GetHardwareEnabled() &&
1201 surfaceDrawable->GetRenderParams()->GetLayerInfo().useDeviceOffline) {
1202 if (!RSHpaeOfflineProcessor::GetOfflineProcessor().PostProcessOfflineTask(
1203 surfaceDrawable, RSUniRenderThread::Instance().GetVsyncId())) {
1204 RS_LOGW("RSUniRenderProcessor::ProcessSurface: post offline task failed, go redraw");
1205 }
1206 }
1207 }
1208 }
1209
CheckScreenFreezeSkip(RSScreenRenderParams & params)1210 bool RSScreenRenderNodeDrawable::CheckScreenFreezeSkip(RSScreenRenderParams& params)
1211 {
1212 if (UNLIKELY(params.GetForceFreeze())) {
1213 SetDrawSkipType(DrawSkipType::SCREEN_FREEZE);
1214 RS_TRACE_NAME("Screen frozen, skip");
1215 return true;
1216 }
1217
1218 auto mirrorDrawable = params.GetMirrorSourceDrawable().lock();
1219 if (!mirrorDrawable) {
1220 return false;
1221 }
1222 auto mirrorParams = static_cast<RSScreenRenderParams*>(mirrorDrawable->GetRenderParams().get());
1223 if (mirrorParams && UNLIKELY(mirrorParams->GetForceFreeze())) {
1224 RS_TRACE_NAME("MirrorScreen frozen, skip");
1225 SetDrawSkipType(DrawSkipType::SCREEN_FREEZE);
1226 return true;
1227 }
1228 return false;
1229 }
1230
1231 } // namespace OHOS::Rosen::DrawableV2
1232