1 /*
2 * Copyright (c) 2024 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_display_render_node_drawable.h"
17
18 #include <memory>
19 #include <parameters.h>
20 #include <string>
21
22 #include "luminance/rs_luminance_control.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 "drawable/rs_surface_render_node_drawable.h"
30 #include "hgm_core.h"
31 #include "memory/rs_tag_tracker.h"
32 #include "params/rs_display_render_params.h"
33 #include "params/rs_surface_render_params.h"
34 #include "pipeline/round_corner_display/rs_rcd_render_manager.h"
35 #include "pipeline/round_corner_display/rs_round_corner_display.h"
36 #include "pipeline/round_corner_display/rs_round_corner_display_manager.h"
37 #include "pipeline/rs_base_render_engine.h"
38 #include "pipeline/rs_display_render_node.h"
39 #include "pipeline/rs_main_thread.h"
40 #include "pipeline/rs_paint_filter_canvas.h"
41 #include "pipeline/rs_processor_factory.h"
42 #include "pipeline/rs_surface_handler.h"
43 #include "pipeline/rs_uifirst_manager.h"
44 #include "pipeline/rs_uni_render_listener.h"
45 #include "pipeline/rs_uni_render_thread.h"
46 #include "pipeline/rs_uni_render_util.h"
47 #include "pipeline/rs_uni_render_virtual_processor.h"
48 #include "pipeline/sk_resource_manager.h"
49 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
50 #include "pipeline/pointer_render/rs_pointer_render_manager.h"
51 #endif
52 #include "platform/common/rs_log.h"
53 #include "platform/ohos/rs_jank_stats.h"
54 #include "property/rs_point_light_manager.h"
55 #include "screen_manager/rs_screen_manager.h"
56 #include "static_factory.h"
57 // dfx
58 #include "drawable/dfx/rs_dirty_rects_dfx.h"
59 #include "drawable/dfx/rs_skp_capture_dfx.h"
60 #include "platform/ohos/overdraw/rs_overdraw_controller.h"
61 #include "utils/performanceCaculate.h"
62 namespace OHOS::Rosen::DrawableV2 {
63 namespace {
64 constexpr const char* CLEAR_GPU_CACHE = "ClearGpuCache";
65 constexpr const char* DEFAULT_CLEAR_GPU_CACHE = "DefaultClearGpuCache";
66 constexpr int32_t NO_SPECIAL_LAYER = 0;
67 constexpr int32_t HAS_SPECIAL_LAYER = 1;
68 constexpr int32_t CAPTURE_WINDOW = 2; // To be deleted after captureWindow being deleted
69 constexpr int64_t MAX_JITTER_NS = 2000000; // 2ms
70
RectVectorToString(std::vector<RectI> & regionRects)71 std::string RectVectorToString(std::vector<RectI>& regionRects)
72 {
73 std::string results = "";
74 for (auto& rect : regionRects) {
75 results += rect.ToString();
76 }
77 return results;
78 }
79
GetFlippedRegion(const std::vector<RectI> & rects,ScreenInfo & screenInfo)80 Drawing::Region GetFlippedRegion(const std::vector<RectI>& rects, ScreenInfo& screenInfo)
81 {
82 Drawing::Region region;
83
84 for (const auto& r : rects) {
85 int32_t topAfterFilp = 0;
86 #ifdef RS_ENABLE_VK
87 topAfterFilp = (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
88 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR)
89 ? r.top_
90 : static_cast<int32_t>(screenInfo.GetRotatedHeight()) - r.GetBottom();
91 #else
92 topAfterFilp = static_cast<int32_t>(screenInfo.GetRotatedHeight()) - r.GetBottom();
93 #endif
94 Drawing::Region tmpRegion;
95 tmpRegion.SetRect(Drawing::RectI(r.left_, topAfterFilp, r.left_ + r.width_, topAfterFilp + r.height_));
96 RS_OPTIONAL_TRACE_NAME_FMT("GetFlippedRegion orig ltrb[%d %d %d %d] to fliped rect ltrb[%d %d %d %d]",
97 r.left_, r.top_, r.left_ + r.width_, r.top_ + r.height_, r.left_, topAfterFilp, r.left_ + r.width_,
98 topAfterFilp + r.height_);
99 region.Op(tmpRegion, Drawing::RegionOp::UNION);
100 }
101 return region;
102 }
103 }
104 class RSOverDrawDfx {
105 public:
RSOverDrawDfx(std::shared_ptr<RSPaintFilterCanvas> curCanvas)106 explicit RSOverDrawDfx(std::shared_ptr<RSPaintFilterCanvas> curCanvas)
107 {
108 bool isEnabled = false;
109 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
110 if (LIKELY(uniParam)) {
111 isEnabled = uniParam->IsOverDrawEnabled();
112 isAceDebugBoundaryEnabled_ = uniParam->IsAceDebugBoundaryEnabled();
113 }
114 enable_ = isEnabled && curCanvas != nullptr;
115 curCanvas_ = curCanvas;
116 StartOverDraw();
117 }
~RSOverDrawDfx()118 ~RSOverDrawDfx()
119 {
120 FinishOverDraw();
121 }
122 private:
StartOverDraw()123 void StartOverDraw()
124 {
125 if (!enable_) {
126 return;
127 }
128
129 auto width = curCanvas_->GetWidth();
130 auto height = curCanvas_->GetHeight();
131 Drawing::ImageInfo info =
132 Drawing::ImageInfo { width, height, Drawing::COLORTYPE_RGBA_8888, Drawing::ALPHATYPE_PREMUL };
133 if (!isAceDebugBoundaryEnabled_) {
134 auto gpuContext = curCanvas_->GetGPUContext();
135 if (gpuContext == nullptr) {
136 RS_LOGE("RSOverDrawDfx::StartOverDraw failed: need gpu canvas");
137 return;
138 }
139 overdrawSurface_ = Drawing::Surface::MakeRenderTarget(gpuContext.get(), false, info);
140 } else {
141 overdrawSurface_ = Drawing::Surface::MakeRaster(info);
142 }
143 if (!overdrawSurface_) {
144 RS_LOGE("RSOverDrawDfx::StartOverDraw failed: surface is nullptr");
145 return;
146 }
147 overdrawCanvas_ = std::make_shared<Drawing::OverDrawCanvas>(overdrawSurface_->GetCanvas());
148 curCanvas_->AddCanvas(overdrawCanvas_.get());
149 }
FinishOverDraw()150 void FinishOverDraw()
151 {
152 if (!enable_) {
153 return;
154 }
155 if (!overdrawSurface_) {
156 RS_LOGE("RSOverDrawDfx::FinishOverDraw overdrawSurface is nullptr");
157 return;
158 }
159 auto image = overdrawSurface_->GetImageSnapshot();
160 if (image == nullptr) {
161 RS_LOGE("RSOverDrawDfx::FinishOverDraw image is nullptr");
162 return;
163 }
164 Drawing::Brush brush;
165 auto overdrawColors = RSOverdrawController::GetInstance().GetColorArray();
166 auto colorFilter = Drawing::ColorFilter::CreateOverDrawColorFilter(overdrawColors.data());
167 Drawing::Filter filter;
168 filter.SetColorFilter(colorFilter);
169 brush.SetFilter(filter);
170 curCanvas_->AttachBrush(brush);
171 curCanvas_->DrawImage(*image, 0, 0, Drawing::SamplingOptions());
172 curCanvas_->DetachBrush();
173 }
174
175 bool enable_;
176 bool isAceDebugBoundaryEnabled_ = false;
177 mutable std::shared_ptr<RSPaintFilterCanvas> curCanvas_;
178 std::shared_ptr<Drawing::Surface> overdrawSurface_ = nullptr;
179 std::shared_ptr<Drawing::OverDrawCanvas> overdrawCanvas_ = nullptr;
180 };
181
DoScreenRcdTask(NodeId id,std::shared_ptr<RSProcessor> & processor,std::unique_ptr<RcdInfo> & rcdInfo,const ScreenInfo & screenInfo)182 void DoScreenRcdTask(NodeId id, std::shared_ptr<RSProcessor>& processor, std::unique_ptr<RcdInfo>& rcdInfo,
183 const ScreenInfo& screenInfo)
184 {
185 if (screenInfo.state != ScreenState::HDI_OUTPUT_ENABLE) {
186 RS_LOGD("DoScreenRcdTask is not at HDI_OUPUT mode");
187 return;
188 }
189 if (RSSingleton<RoundCornerDisplayManager>::GetInstance().GetRcdEnable()) {
190 RSSingleton<RoundCornerDisplayManager>::GetInstance().RunHardwareTask(id,
191 [id, &processor, &rcdInfo](void) {
192 auto hardInfo = RSSingleton<RoundCornerDisplayManager>::GetInstance().GetHardwareInfo(id, true);
193 rcdInfo->processInfo = {processor, hardInfo.topLayer, hardInfo.bottomLayer,
194 hardInfo.resourceChanged};
195 RSRcdRenderManager::GetInstance().DoProcessRenderTask(id, rcdInfo->processInfo);
196 });
197 }
198 }
199
200 RSDisplayRenderNodeDrawable::Registrar RSDisplayRenderNodeDrawable::instance_;
201
RSDisplayRenderNodeDrawable(std::shared_ptr<const RSRenderNode> && node)202 RSDisplayRenderNodeDrawable::RSDisplayRenderNodeDrawable(std::shared_ptr<const RSRenderNode>&& node)
203 : RSRenderNodeDrawable(std::move(node)), surfaceHandler_(std::make_shared<RSSurfaceHandler>(nodeId_)),
204 syncDirtyManager_(std::make_shared<RSDirtyRegionManager>(true))
205 {}
206
OnGenerate(std::shared_ptr<const RSRenderNode> node)207 RSRenderNodeDrawable::Ptr RSDisplayRenderNodeDrawable::OnGenerate(std::shared_ptr<const RSRenderNode> node)
208 {
209 return new RSDisplayRenderNodeDrawable(std::move(node));
210 }
211
RequestFrame(RSDisplayRenderParams & params,std::shared_ptr<RSProcessor> processor)212 std::unique_ptr<RSRenderFrame> RSDisplayRenderNodeDrawable::RequestFrame(
213 RSDisplayRenderParams& params, std::shared_ptr<RSProcessor> processor)
214 {
215 RS_TRACE_NAME("RSDisplayRenderNodeDrawable:RequestFrame");
216 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
217 if (UNLIKELY(!renderEngine)) {
218 RS_LOGE("RSDisplayRenderNodeDrawable::RequestFrame RenderEngine is null!");
219 return nullptr;
220 }
221
222 if (!processor->InitForRenderThread(*this, INVALID_SCREEN_ID, renderEngine)) {
223 RS_LOGE("RSDisplayRenderNodeDrawable::RequestFrame processor InitForRenderThread failed!");
224 return nullptr;
225 }
226
227 if (!IsSurfaceCreated()) {
228 sptr<IBufferConsumerListener> listener = new RSUniRenderListener(surfaceHandler_);
229 if (!CreateSurface(listener)) {
230 RS_LOGE("RSDisplayRenderNodeDrawable::RequestFrame CreateSurface failed");
231 return nullptr;
232 }
233 }
234
235 auto rsSurface = GetRSSurface();
236 if (!rsSurface) {
237 RS_LOGE("RSDisplayRenderNodeDrawable::RequestFrame No RSSurface found");
238 return nullptr;
239 }
240 auto bufferConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(params.GetScreenInfo(), false,
241 params.GetNewColorSpace(), params.GetNewPixelFormat());
242 RS_LOGD("RequestFrame colorspace is %{public}d, pixelformat is %{public}d", params.GetNewColorSpace(),
243 params.GetNewPixelFormat());
244 auto renderFrame = renderEngine->RequestFrame(std::static_pointer_cast<RSSurfaceOhos>(rsSurface), bufferConfig);
245 if (!renderFrame) {
246 RS_LOGE("RSDisplayRenderNodeDrawable::RequestFrame renderEngine requestFrame is null");
247 return nullptr;
248 }
249
250 return renderFrame;
251 }
252
ClipRegion(Drawing::Canvas & canvas,Drawing::Region & region,bool clear=true)253 static void ClipRegion(Drawing::Canvas& canvas, Drawing::Region& region, bool clear = true)
254 {
255 if (region.IsEmpty()) {
256 // [planning] Remove this after frame buffer can cancel
257 canvas.ClipRect(Drawing::Rect());
258 } else if (region.IsRect()) {
259 canvas.ClipRegion(region);
260 } else {
261 RS_TRACE_NAME("RSDisplayDrawable: clipPath");
262 #ifdef RS_ENABLE_VK
263 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
264 RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
265 canvas.ClipRegion(region);
266 } else {
267 Drawing::Path dirtyPath;
268 region.GetBoundaryPath(&dirtyPath);
269 canvas.ClipPath(dirtyPath, Drawing::ClipOp::INTERSECT, true);
270 }
271 #else
272 Drawing::Path dirtyPath;
273 region.GetBoundaryPath(&dirtyPath);
274 canvas.ClipPath(dirtyPath, Drawing::ClipOp::INTERSECT, true);
275 #endif
276 }
277
278 // clear canvas after clip region if need
279 if (clear && !region.IsEmpty()) {
280 canvas.Clear(Drawing::Color::COLOR_TRANSPARENT);
281 }
282 }
283
CheckDisplayNodeSkip(RSDisplayRenderParams & params,std::shared_ptr<RSProcessor> processor)284 bool RSDisplayRenderNodeDrawable::CheckDisplayNodeSkip(
285 RSDisplayRenderParams& params, std::shared_ptr<RSProcessor> processor)
286 {
287 if (GetSyncDirtyManager()->IsCurrentFrameDirty() ||
288 (params.GetMainAndLeashSurfaceDirty() || RSUifirstManager::Instance().HasDoneNode()) ||
289 RSMainThread::Instance()->GetDirtyFlag()) {
290 return false;
291 }
292
293 RS_LOGD("DisplayNode skip");
294 RS_TRACE_NAME("DisplayNode skip");
295 GpuDirtyRegionCollection::GetInstance().AddSkipProcessFramesNumberForDFX(RSBaseRenderUtil::GetLastSendingPid());
296 #ifdef OHOS_PLATFORM
297 RSUniRenderThread::Instance().SetSkipJankAnimatorFrame(true);
298 #endif
299 auto pendingDrawables = RSUifirstManager::Instance().GetPendingPostDrawables();
300 if (!RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetForceCommitLayer() &&
301 pendingDrawables.size() == 0) {
302 RS_TRACE_NAME("DisplayNodeSkip skip commit");
303 return true;
304 }
305
306 if (!processor->InitForRenderThread(*this, INVALID_SCREEN_ID, RSUniRenderThread::Instance().GetRenderEngine())) {
307 RS_LOGE("RSDisplayRenderNodeDrawable::CheckDisplayNodeSkip processor init failed");
308 return false;
309 }
310
311 auto& hardwareDrawables =
312 RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
313 for (const auto& [displayNodeId, drawable] : hardwareDrawables) {
314 if (UNLIKELY(!drawable || !drawable->GetRenderParams()) || displayNodeId != params.GetId()) {
315 continue;
316 }
317 if (drawable->GetRenderParams()->GetHardwareEnabled()) {
318 auto surfaceDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(drawable);
319 processor->CreateLayerForRenderThread(*surfaceDrawable);
320 }
321 }
322 if (!RSMainThread::Instance()->WaitHardwareThreadTaskExecute()) {
323 RS_LOGW("RSDisplayRenderNodeDrawable::CheckDisplayNodeSkip: hardwareThread task has too many to Execute"
324 " TaskNum:[%{public}d]", RSHardwareThread::Instance().GetunExecuteTaskNum());
325 RSHardwareThread::Instance().DumpEventQueue();
326 }
327 processor->ProcessDisplaySurfaceForRenderThread(*this);
328
329 RSUifirstManager::Instance().CreateUIFirstLayer(processor);
330
331 // commit RCD layers
332 auto rcdInfo = std::make_unique<RcdInfo>();
333 const auto& screenInfo = params.GetScreenInfo();
334 DoScreenRcdTask(params.GetId(), processor, rcdInfo, screenInfo);
335 processor->PostProcess();
336 return true;
337 }
338
PostClearMemoryTask() const339 void RSDisplayRenderNodeDrawable::PostClearMemoryTask() const
340 {
341 auto& unirenderThread = RSUniRenderThread::Instance();
342 if (unirenderThread.IsDefaultClearMemoryFinished()) {
343 unirenderThread.DefaultClearMemoryCache(); //default clean with no rendering in 5s
344 unirenderThread.SetDefaultClearMemoryFinished(false);
345 }
346 }
347
SetDisplayNodeSkipFlag(RSRenderThreadParams & uniParam,bool flag)348 void RSDisplayRenderNodeDrawable::SetDisplayNodeSkipFlag(RSRenderThreadParams& uniParam, bool flag)
349 {
350 isDisplayNodeSkipStatusChanged_ = (isDisplayNodeSkip_ != flag);
351 isDisplayNodeSkip_ = flag;
352 uniParam.SetForceMirrorScreenDirty(isDisplayNodeSkipStatusChanged_ && isDisplayNodeSkip_);
353 }
354
CheckFilterCacheFullyCovered(RSSurfaceRenderParams & surfaceParams,RectI screenRect)355 void RSDisplayRenderNodeDrawable::CheckFilterCacheFullyCovered(RSSurfaceRenderParams& surfaceParams, RectI screenRect)
356 {
357 surfaceParams.SetFilterCacheFullyCovered(false);
358 bool dirtyBelowContainsFilterNode = false;
359 for (auto& filterNodeId : surfaceParams.GetVisibleFilterChild()) {
360 auto drawableAdapter = DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableById(filterNodeId);
361 if (drawableAdapter == nullptr) {
362 continue;
363 }
364 auto filterNodeDrawable = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(drawableAdapter);
365 if (filterNodeDrawable == nullptr) {
366 RS_LOGD("CheckFilterCacheFullyCovered filter node drawable is nullptr, Name[%{public}s],"
367 "NodeId[%" PRIu64 "]", surfaceParams.GetName().c_str(), filterNodeId);
368 continue;
369 }
370 auto filterParams = static_cast<RSRenderParams*>(filterNodeDrawable->GetRenderParams().get());
371 if (filterParams == nullptr || !filterParams->HasBlurFilter()) {
372 RS_LOGD("CheckFilterCacheFullyCovered filter params is nullptr or has no blur, Name[%{public}s],"
373 "NodeId[%" PRIu64 "]", surfaceParams.GetName().c_str(), filterNodeId);
374 continue;
375 }
376 // Filter cache occlusion need satisfy:
377 // 1.The filter node global alpha equals 1;
378 // 2.There is no invalid filter cache node below, which should take snapshot;
379 // 3.The filter node has no global corner;
380 // 4.The surfaceNode is transparent, the opaque surfaceNode can occlude without filter cache;
381 // 5.The node type is not EFFECT_NODE;
382 if (ROSEN_EQ(filterParams->GetGlobalAlpha(), 1.f) && !dirtyBelowContainsFilterNode &&
383 !filterParams->HasGlobalCorner() && surfaceParams.IsTransparent() &&
384 filterParams->GetType() != RSRenderNodeType::EFFECT_NODE) {
385 surfaceParams.CheckValidFilterCacheFullyCoverTarget(
386 filterNodeDrawable->IsFilterCacheValidForOcclusion(),
387 filterNodeDrawable->GetFilterCachedRegion(), screenRect);
388 }
389 RS_OPTIONAL_TRACE_NAME_FMT("CheckFilterCacheFullyCovered NodeId[%" PRIu64 "], globalAlpha: %f,"
390 "hasInvalidFilterCacheBefore: %d, hasNoCorner: %d, isTransparent: %d, isNodeTypeCorrect: %d,"
391 "isCacheValid: %d, cacheRect: %s", filterNodeId, filterParams->GetGlobalAlpha(),
392 !dirtyBelowContainsFilterNode, !filterParams->HasGlobalCorner(), surfaceParams.IsTransparent(),
393 filterParams->GetType() != RSRenderNodeType::EFFECT_NODE,
394 filterNodeDrawable->IsFilterCacheValidForOcclusion(),
395 filterNodeDrawable->GetFilterCachedRegion().ToString().c_str());
396 if (filterParams->GetEffectNodeShouldPaint() && !filterNodeDrawable->IsFilterCacheValidForOcclusion()) {
397 dirtyBelowContainsFilterNode = true;
398 }
399 }
400 }
401
CheckAndUpdateFilterCacheOcclusion(RSDisplayRenderParams & params,ScreenInfo & screenInfo)402 void RSDisplayRenderNodeDrawable::CheckAndUpdateFilterCacheOcclusion(
403 RSDisplayRenderParams& params, ScreenInfo& screenInfo)
404 {
405 if (!RSSystemParameters::GetFilterCacheOcculusionEnabled()) {
406 return;
407 }
408 bool isScreenOccluded = false;
409 RectI screenRect = {0, 0, screenInfo.width, screenInfo.height};
410 // top-down traversal all mainsurface
411 // if upper surface reuse filter cache which fully cover whole screen
412 // mark lower layers for process skip
413 auto& curAllSurfaceDrawables = params.GetAllMainAndLeashSurfaceDrawables();
414 for (auto it = curAllSurfaceDrawables.begin(); it != curAllSurfaceDrawables.end(); ++it) {
415 if (*it == nullptr || (*it)->GetNodeType() != RSRenderNodeType::SURFACE_NODE) {
416 RS_LOGD("CheckAndUpdateFilterCacheOcclusion adapter is nullptr or error type");
417 continue;
418 }
419 auto surfaceNodeDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(*it);
420 if (surfaceNodeDrawable == nullptr) {
421 RS_LOGD("CheckAndUpdateFilterCacheOcclusion surfaceNodeDrawable is nullptr");
422 continue;
423 }
424 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
425 if (surfaceParams == nullptr) {
426 RS_LOGD("CheckAndUpdateFilterCacheOcclusion surface params is nullptr");
427 continue;
428 }
429
430 CheckFilterCacheFullyCovered(*surfaceParams, screenRect);
431
432 if (surfaceParams->IsMainWindowType()) {
433 // reset occluded status for all mainwindow
434 surfaceParams->SetOccludedByFilterCache(isScreenOccluded);
435 }
436 isScreenOccluded = isScreenOccluded || surfaceParams->GetFilterCacheFullyCovered();
437 }
438 }
439
OnDraw(Drawing::Canvas & canvas)440 void RSDisplayRenderNodeDrawable::OnDraw(Drawing::Canvas& canvas)
441 {
442 SetDrawSkipType(DrawSkipType::NONE);
443 // canvas will generate in every request frame
444 (void)canvas;
445
446 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
447 if (UNLIKELY(!renderParams_ || !uniParam)) {
448 SetDrawSkipType(DrawSkipType::RENDER_PARAMS_OR_UNI_PARAMS_NULL);
449 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw renderParams/uniParam is null!");
450 return;
451 }
452 auto params = static_cast<RSDisplayRenderParams*>(renderParams_.get());
453
454 // [Attention] do not return before layer created set false, otherwise will result in buffer not released
455 auto& hardwareDrawables = uniParam->GetHardwareEnabledTypeDrawables();
456 for (const auto& [displayNodeId, drawable] : hardwareDrawables) {
457 if (UNLIKELY(!drawable || !drawable->GetRenderParams()) ||
458 displayNodeId != params->GetId()) {
459 continue;
460 }
461 drawable->GetRenderParams()->SetLayerCreated(false);
462 }
463
464 // if screen power off, skip on draw, needs to draw one more frame.
465 isRenderSkipIfScreenOff_ = RSUniRenderUtil::CheckRenderSkipIfScreenOff(true, params->GetScreenId());
466 if (isRenderSkipIfScreenOff_) {
467 SetDrawSkipType(DrawSkipType::RENDER_SKIP_IF_SCREEN_OFF);
468 return;
469 }
470
471 PostClearMemoryTask();
472
473 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
474 if (!screenManager) {
475 SetDrawSkipType(DrawSkipType::SCREEN_MANAGER_NULL);
476 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw ScreenManager is nullptr");
477 return;
478 }
479
480 if (RSSystemProperties::IsFoldScreenFlag() && screenManager->IsScreenSwitching()) {
481 SetDrawSkipType(DrawSkipType::RENDER_SKIP_IF_SCREEN_SWITCHING);
482 RS_LOGI("RSDisplayRenderNodeDrawable::OnDraw FoldScreenNodeSwitching is true, do not drawframe");
483 RS_TRACE_NAME_FMT("RSDisplayRenderNodeDrawable FoldScreenNodeSwitching is true");
484 return;
485 }
486
487 // dfx
488 RSRenderNodeDrawable::InitDfxForCacheInfo();
489 uniParam->SetIsMirrorScreen(params->IsMirrorScreen());
490 uniParam->SetCompositeType(params->GetCompositeType());
491 // check rotation for point light
492 constexpr int ROTATION_NUM = 4;
493 auto screenRotation = GetRenderParams()->GetScreenRotation();
494 ScreenId paramScreenId = params->GetScreenId();
495 if (RSSystemProperties::IsFoldScreenFlag() && paramScreenId == 0) {
496 screenRotation = static_cast<ScreenRotation>((static_cast<int>(screenRotation) + 1) % ROTATION_NUM);
497 }
498 RSPointLightManager::Instance()->SetScreenRotation(screenRotation);
499 const RectI& dirtyRegion = GetSyncDirtyManager()->GetCurrentFrameDirtyRegion();
500 const auto& activeSurfaceRect = GetSyncDirtyManager()->GetActiveSurfaceRect();
501 RS_TRACE_NAME_FMT("RSDisplayRenderNodeDrawable[%" PRIu64 "](%d, %d, %d, %d), zoomed(%d), active(%d, %d, %d, %d)",
502 paramScreenId, dirtyRegion.left_, dirtyRegion.top_, dirtyRegion.width_, dirtyRegion.height_,
503 params->GetZoomed(), activeSurfaceRect.left_, activeSurfaceRect.top_, activeSurfaceRect.width_,
504 activeSurfaceRect.height_);
505 RS_LOGD("RSDisplayRenderNodeDrawable::OnDraw node: %{public}" PRIu64 "", GetId());
506 ScreenInfo curScreenInfo = screenManager->QueryScreenInfo(paramScreenId);
507 ScreenId activeScreenId = HgmCore::Instance().GetActiveScreenId();
508 uint32_t activeScreenRefreshRate = HgmCore::Instance().GetScreenCurrentRefreshRate(activeScreenId);
509
510 // when set expectedRefreshRate, the activeScreenRefreshRate maybe change from 60 to 120
511 // so that need change whether equal vsync period and whether use virtual dirty
512 if (curScreenInfo.skipFrameStrategy == SKIP_FRAME_BY_REFRESH_RATE) {
513 bool isEqualVsyncPeriod = (activeScreenRefreshRate == curScreenInfo.expectedRefreshRate);
514 if (isEqualVsyncPeriod ^ curScreenInfo.isEqualVsyncPeriod) {
515 curScreenInfo.isEqualVsyncPeriod = isEqualVsyncPeriod;
516 screenManager->SetEqualVsyncPeriod(paramScreenId, isEqualVsyncPeriod);
517 }
518 }
519 if (SkipFrame(activeScreenRefreshRate, curScreenInfo)) {
520 SetDrawSkipType(DrawSkipType::SKIP_FRAME);
521 RS_TRACE_NAME_FMT("SkipFrame, screenId:%lu, strategy:%d, interval:%u, refreshrate:%u", paramScreenId,
522 curScreenInfo.skipFrameStrategy, curScreenInfo.skipFrameInterval, curScreenInfo.expectedRefreshRate);
523 screenManager->ForceRefreshOneFrameIfNoRNV();
524 return;
525 }
526 if (!curScreenInfo.isEqualVsyncPeriod) {
527 virtualDirtyRefresh_ = true;
528 }
529
530 auto screenInfo = params->GetScreenInfo();
531 auto processor = RSProcessorFactory::CreateProcessor(params->GetCompositeType());
532 if (!processor) {
533 SetDrawSkipType(DrawSkipType::CREATE_PROCESSOR_FAIL);
534 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw RSProcessor is null!");
535 return;
536 }
537
538 auto mirrorDrawable = params->GetMirrorSourceDrawable().lock();
539 auto mirrorParams = mirrorDrawable ? mirrorDrawable->GetRenderParams().get() : nullptr;
540 if (mirrorParams || params->GetCompositeType() == RSDisplayRenderNode::CompositeType::UNI_RENDER_EXPAND_COMPOSITE) {
541 if (!processor->InitForRenderThread(*this,
542 mirrorParams ? mirrorParams->GetScreenId() : INVALID_SCREEN_ID,
543 RSUniRenderThread::Instance().GetRenderEngine())) {
544 SetDrawSkipType(DrawSkipType::RENDER_ENGINE_NULL);
545 syncDirtyManager_->ResetDirtyAsSurfaceSize();
546 syncDirtyManager_->UpdateDirty(false);
547 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw processor init failed!");
548 return;
549 }
550 if (mirrorParams) {
551 if (params->GetCompositeType() == RSDisplayRenderNode::CompositeType::UNI_RENDER_COMPOSITE) {
552 SetDrawSkipType(DrawSkipType::WIRED_SCREEN_PROJECTION);
553 RS_LOGD("RSDisplayRenderNodeDrawable::OnDraw wired screen projection.");
554 WiredScreenProjection(*params, processor);
555 return;
556 }
557 castScreenEnableSkipWindow_ = screenManager->GetCastScreenEnableSkipWindow(paramScreenId);
558 if (castScreenEnableSkipWindow_) {
559 RS_LOGD("RSDisplayRenderNodeDrawable::OnDraw, Enable CastScreen SkipWindow.");
560 screenManager->GetCastScreenBlackList(currentBlackList_);
561 } else {
562 RS_LOGD("RSDisplayRenderNodeDrawable::OnDraw, Enable RecordScreen SkipWindow.");
563 currentBlackList_ = screenManager->GetVirtualScreenBlackList(paramScreenId);
564 }
565 RSUniRenderThread::Instance().SetBlackList(currentBlackList_);
566 RSUniRenderThread::Instance().SetWhiteList(screenInfo.whiteList);
567 curSecExemption_ = params->GetSecurityExemption();
568 uniParam->SetSecExemption(curSecExemption_);
569 RS_LOGD("RSDisplayRenderNodeDrawable::OnDraw Mirror screen.");
570 DrawMirrorScreen(*params, processor);
571 lastBlackList_ = currentBlackList_;
572 lastSecExemption_ = curSecExemption_;
573 } else {
574 bool isOpDropped = uniParam->IsOpDropped();
575 uniParam->SetOpDropped(false);
576 auto expandProcessor = RSProcessor::ReinterpretCast<RSUniRenderVirtualProcessor>(processor);
577 if (!expandProcessor) {
578 SetDrawSkipType(DrawSkipType::EXPAND_PROCESSOR_NULL);
579 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw expandProcessor is null!");
580 return;
581 }
582 RSDirtyRectsDfx rsDirtyRectsDfx(*this);
583 std::vector<RectI> damageRegionRects;
584 // disable expand screen dirty when isEqualVsyncPeriod is false, because the dirty history is incorrect
585 if (uniParam->IsExpandScreenDirtyEnabled() && uniParam->IsVirtualDirtyEnabled() &&
586 curScreenInfo.isEqualVsyncPeriod) {
587 int32_t bufferAge = expandProcessor->GetBufferAge();
588 damageRegionRects = RSUniRenderUtil::MergeDirtyHistory(
589 *this, bufferAge, screenInfo, rsDirtyRectsDfx, *params);
590 uniParam->Reset();
591 if (!uniParam->IsVirtualDirtyDfxEnabled()) {
592 expandProcessor->SetDirtyInfo(damageRegionRects);
593 }
594 } else {
595 std::vector<RectI> emptyRects = {};
596 expandProcessor->SetRoiRegionToCodec(emptyRects);
597 }
598 rsDirtyRectsDfx.SetVirtualDirtyRects(damageRegionRects, screenInfo);
599 DrawExpandScreen(*expandProcessor);
600 if (curCanvas_) {
601 rsDirtyRectsDfx.OnDrawVirtual(*curCanvas_);
602 }
603 uniParam->SetOpDropped(isOpDropped);
604 }
605 DrawCurtainScreen();
606 processor->PostProcess();
607 SetDrawSkipType(DrawSkipType::MIRROR_DRAWABLE_SKIP);
608 return;
609 }
610
611 bool isHdrOn = params->GetHDRPresent();
612 // 0 means defalut hdrBrightnessRatio
613 float hdrBrightnessRatio = RSLuminanceControl::Get().GetHdrBrightnessRatio(paramScreenId, 0);
614 if (!isHdrOn) {
615 params->SetBrightnessRatio(hdrBrightnessRatio);
616 hdrBrightnessRatio = 1.0f;
617 }
618 RS_LOGD("RSDisplayRenderNodeDrawable::OnDraw HDR content in UniRender:%{public}d, BrightnessRatio:%{public}f",
619 isHdrOn, hdrBrightnessRatio);
620
621 if (uniParam->IsOpDropped() && CheckDisplayNodeSkip(*params, processor)) {
622 RSMainThread::Instance()->SetFrameIsRender(false);
623 SetDrawSkipType(DrawSkipType::DISPLAY_NODE_SKIP);
624 SetDisplayNodeSkipFlag(*uniParam, true);
625 return;
626 }
627 SetDisplayNodeSkipFlag(*uniParam, false);
628 RSMainThread::Instance()->SetFrameIsRender(true);
629
630 CheckAndUpdateFilterCacheOcclusion(*params, curScreenInfo);
631 RS_LOGD("RSDisplayRenderNodeDrawable::OnDraw HDR isHdrOn: %{public}d", isHdrOn);
632 if (isHdrOn) {
633 params->SetNewPixelFormat(GRAPHIC_PIXEL_FMT_RGBA_1010102);
634 }
635 RSUniRenderThread::Instance().WaitUntilDisplayNodeBufferReleased(*this);
636 // displayNodeSp to get rsSurface witch only used in renderThread
637 auto renderFrame = RequestFrame(*params, processor);
638 if (!renderFrame) {
639 SetDrawSkipType(DrawSkipType::REQUEST_FRAME_FAIL);
640 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw failed to request frame");
641 return;
642 }
643
644 UpdateSlrScale(screenInfo);
645 RSDirtyRectsDfx rsDirtyRectsDfx(*this);
646 std::vector<RectI> damageRegionrects;
647 Drawing::Region clipRegion;
648 if (uniParam->IsPartialRenderEnabled()) {
649 damageRegionrects = RSUniRenderUtil::MergeDirtyHistory(
650 *this, renderFrame->GetBufferAge(), screenInfo, rsDirtyRectsDfx, *params);
651 uniParam->Reset();
652 clipRegion = GetFlippedRegion(damageRegionrects, screenInfo);
653 RS_TRACE_NAME_FMT("SetDamageRegion damageRegionrects num: %zu, info: %s",
654 damageRegionrects.size(), RectVectorToString(damageRegionrects).c_str());
655 if (!uniParam->IsRegionDebugEnabled()) {
656 renderFrame->SetDamageRegion(damageRegionrects);
657 }
658 }
659
660 auto drSurface = renderFrame->GetFrame()->GetSurface();
661 if (!drSurface) {
662 SetDrawSkipType(DrawSkipType::SURFACE_NULL);
663 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw DrawingSurface is null");
664 return;
665 }
666
667 curCanvas_ = std::make_shared<RSPaintFilterCanvas>(drSurface.get());
668 if (!curCanvas_) {
669 SetDrawSkipType(DrawSkipType::CANVAS_NULL);
670 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw failed to create canvas");
671 return;
672 }
673
674 curCanvas_->SetTargetColorGamut(params->GetNewColorSpace());
675 curCanvas_->SetScreenId(paramScreenId);
676 curCanvas_->SetDisableFilterCache(params->GetZoomed());
677
678 #ifdef DDGR_ENABLE_FEATURE_OPINC
679 if (autoCacheEnable_) {
680 screenRectInfo_ = {0, 0, screenInfo.width, screenInfo.height};
681 }
682 #endif
683
684 // canvas draw
685 {
686 RSOverDrawDfx rsOverDrawDfx(curCanvas_);
687 {
688 RSSkpCaptureDfx capture(curCanvas_);
689 Drawing::AutoCanvasRestore acr(*curCanvas_, true);
690
691 bool isOpDropped = uniParam->IsOpDropped();
692 bool needOffscreen = params->GetNeedOffscreen() || isHdrOn || screenInfo.isSamplingOn;
693 if (needOffscreen) {
694 uniParam->SetOpDropped(false);
695 // draw black background in rotation for camera
696 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
697 ScaleCanvasIfNeeded(screenInfo);
698 PrepareOffscreenRender(*this, !screenInfo.isSamplingOn, !screenInfo.isSamplingOn);
699 }
700
701 if (uniParam->IsOpDropped()) {
702 uniParam->SetClipRegion(clipRegion);
703 ClipRegion(*curCanvas_, clipRegion);
704 } else {
705 curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
706 }
707
708 if (!params->GetNeedOffscreen()) {
709 curCanvas_->ConcatMatrix(params->GetMatrix());
710 }
711
712 curCanvas_->SetHighContrast(RSUniRenderThread::Instance().IsHighContrastTextModeOn());
713 RSRenderNodeDrawable::OnDraw(*curCanvas_);
714 rsDirtyRectsDfx.OnDraw(*curCanvas_);
715 DrawCurtainScreen();
716 if (screenInfo.isSamplingOn) {
717 // In expand screen down-sampling situation, process watermark and color filter during offscreen render.
718 DrawWatermarkIfNeed(*params, *curCanvas_);
719 SwitchColorFilter(*curCanvas_, hdrBrightnessRatio);
720 }
721 if (needOffscreen && canvasBackup_) {
722 Drawing::AutoCanvasRestore acr(*canvasBackup_, true);
723 if (params->GetNeedOffscreen()) {
724 canvasBackup_->ConcatMatrix(params->GetMatrix());
725 }
726 ClearTransparentBeforeSaveLayer();
727 FinishOffscreenRender(Drawing::SamplingOptions(Drawing::FilterMode::NEAREST,
728 Drawing::MipmapMode::NONE), screenInfo.isSamplingOn, hdrBrightnessRatio);
729 uniParam->SetOpDropped(isOpDropped);
730 }
731 if (!screenInfo.isSamplingOn) {
732 // In normal situation, process watermark and color filter after offscreen render.
733 DrawWatermarkIfNeed(*params, *curCanvas_);
734 SwitchColorFilter(*curCanvas_, hdrBrightnessRatio);
735 }
736 auto dirtyManager = GetSyncDirtyManager();
737 const auto& activeRect = dirtyManager->GetActiveSurfaceRect();
738 if (!activeRect.IsEmpty() && (!dirtyManager->GetDirtyRegion().IsInsideOf(activeRect) ||
739 !uniParam->IsPartialRenderEnabled() || uniParam->IsRegionDebugEnabled())) {
740 RS_TRACE_NAME_FMT("global dirty region:[%s] is not inside of active surface rect:[%s], "
741 "clear extra area to black", dirtyManager->GetDirtyRegion().ToString().c_str(),
742 activeRect.ToString().c_str());
743 curCanvas_->Save();
744 auto activeRegion = RSUniRenderUtil::ScreenIntersectDirtyRects(
745 Occlusion::Region(activeRect), screenInfo);
746 curCanvas_->ClipRegion(GetFlippedRegion(activeRegion, screenInfo), Drawing::ClipOp::DIFFERENCE);
747 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
748 curCanvas_->Restore();
749 }
750 }
751 if ((RSSystemProperties::IsFoldScreenFlag() || RSSystemProperties::IsTabletType())
752 && !params->IsRotationChanged()) {
753 offscreenSurface_ = nullptr;
754 }
755
756 specialLayerType_ = GetSpecialLayerType(*params);
757 if (RSSystemProperties::GetDrawMirrorCacheImageEnabled() && uniParam->HasMirrorDisplay() &&
758 curCanvas_->GetSurface() != nullptr && specialLayerType_ != HAS_SPECIAL_LAYER) {
759 cacheImgForCapture_ = curCanvas_->GetSurface()->GetImageSnapshot();
760 } else {
761 SetCacheImgForCapture(nullptr);
762 }
763 }
764 RSMainThread::Instance()->SetDirtyFlag(false);
765
766 if (Drawing::PerformanceCaculate::GetDrawingFlushPrint()) {
767 RS_LOGI("Drawing Performance Flush start %{public}lld", Drawing::PerformanceCaculate::GetUpTime(false));
768 }
769 RS_TRACE_BEGIN("RSDisplayRenderNodeDrawable Flush");
770 renderFrame->Flush();
771 RS_TRACE_END();
772 if (Drawing::PerformanceCaculate::GetDrawingFlushPrint()) {
773 RS_LOGI("Drawing Performance Flush end %{public}lld", Drawing::PerformanceCaculate::GetUpTime(false));
774 Drawing::PerformanceCaculate::ResetCaculateTimeCount();
775 }
776
777 // process round corner display
778 auto rcdInfo = std::make_unique<RcdInfo>();
779 DoScreenRcdTask(params->GetId(), processor, rcdInfo, screenInfo);
780
781 if (!RSMainThread::Instance()->WaitHardwareThreadTaskExecute()) {
782 RS_LOGW("RSDisplayRenderNodeDrawable::ondraw: hardwareThread task has too many to Execute"
783 " TaskNum:[%{public}d]", RSHardwareThread::Instance().GetunExecuteTaskNum());
784 RSHardwareThread::Instance().DumpEventQueue();
785 }
786
787 RS_TRACE_BEGIN("RSDisplayRenderNodeDrawable CommitLayer");
788 for (const auto& [displayNodeId, drawable] : hardwareDrawables) {
789 if (UNLIKELY(!drawable || !drawable->GetRenderParams())) {
790 continue;
791 }
792 auto surfaceDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(drawable);
793 if (!surfaceDrawable || displayNodeId != params->GetId()) {
794 continue;
795 }
796 if (drawable->GetRenderParams()->GetHardwareEnabled()) {
797 processor->CreateLayerForRenderThread(*surfaceDrawable);
798 }
799 }
800 if (screenInfo.activeRect.IsEmpty() ||
801 screenInfo.activeRect == RectI(0, 0, screenInfo.width, screenInfo.height)) {
802 SetDirtyRects(damageRegionrects);
803 } else {
804 SetDirtyRects({GetSyncDirtyManager()->GetRectFlipWithinSurface(screenInfo.activeRect)});
805 }
806 processor->ProcessDisplaySurfaceForRenderThread(*this);
807 RSUifirstManager::Instance().CreateUIFirstLayer(processor);
808 processor->PostProcess();
809 RS_TRACE_END();
810
811 #ifdef OHOS_BUILD_ENABLE_MAGICCURSOR
812 if (!mirrorDrawable) {
813 RSPointerRenderManager::GetInstance().ProcessColorPicker(processor, curCanvas_->GetGPUContext());
814 RSPointerRenderManager::GetInstance().SetCacheImgForPointer(nullptr);
815 }
816 #endif
817 }
818
DrawMirrorScreen(RSDisplayRenderParams & params,std::shared_ptr<RSProcessor> processor)819 void RSDisplayRenderNodeDrawable::DrawMirrorScreen(
820 RSDisplayRenderParams& params, std::shared_ptr<RSProcessor> processor)
821 {
822 // uniParam/drawable/mirroredParams/renderParams_ not null in caller
823 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
824 auto mirroredDrawable =
825 std::static_pointer_cast<RSDisplayRenderNodeDrawable>(params.GetMirrorSourceDrawable().lock());
826 auto& mirroredParams = mirroredDrawable->GetRenderParams();
827
828 specialLayerType_ = GetSpecialLayerType(static_cast<RSDisplayRenderParams&>(*mirroredParams));
829 auto virtualProcesser = RSProcessor::ReinterpretCast<RSUniRenderVirtualProcessor>(processor);
830 if (!virtualProcesser) {
831 RS_LOGE("RSDisplayRenderNodeDrawable::DrawMirrorScreen virtualProcesser is null");
832 return;
833 }
834
835 auto hardwareDrawables = uniParam->GetHardwareEnabledTypeDrawables();
836 //if specialLayer is visible and no CacheImg
837 if ((mirroredParams->GetSecurityDisplay() != params.GetSecurityDisplay() &&
838 specialLayerType_ == HAS_SPECIAL_LAYER) || !mirroredDrawable->GetCacheImgForCapture()) {
839 DrawMirror(params, virtualProcesser,
840 &RSDisplayRenderNodeDrawable::OnCapture, *uniParam);
841 } else {
842 DrawMirrorCopy(*mirroredDrawable, params, virtualProcesser, *uniParam);
843 }
844 }
845
UpdateDisplayDirtyManager(int32_t bufferage,bool useAlignedDirtyRegion)846 void RSDisplayRenderNodeDrawable::UpdateDisplayDirtyManager(int32_t bufferage, bool useAlignedDirtyRegion)
847 {
848 // syncDirtyManager_ not null in caller
849 syncDirtyManager_->SetBufferAge(bufferage);
850 syncDirtyManager_->UpdateDirty(useAlignedDirtyRegion);
851 }
852
GetSpecialLayerType(RSDisplayRenderParams & params)853 int32_t RSDisplayRenderNodeDrawable::GetSpecialLayerType(RSDisplayRenderParams& params)
854 {
855 auto& uniRenderThread = RSUniRenderThread::Instance();
856 auto hasGeneralSpecialLayer = params.HasSecurityLayer() || params.HasSkipLayer() ||
857 params.HasProtectedLayer() || params.GetHDRPresent() || uniRenderThread.IsColorFilterModeOn();
858 if (RSUniRenderThread::GetCaptureParam().isSnapshot_) {
859 hasGeneralSpecialLayer |= (params.HasSnapshotSkipLayer() || uniRenderThread.IsCurtainScreenOn());
860 return hasGeneralSpecialLayer ? HAS_SPECIAL_LAYER :
861 (params.HasCaptureWindow() ? CAPTURE_WINDOW : NO_SPECIAL_LAYER);
862 }
863 if (hasGeneralSpecialLayer || (!uniRenderThread.GetWhiteList().empty()) || !currentBlackList_.empty()) {
864 return HAS_SPECIAL_LAYER;
865 } else if (params.HasCaptureWindow()) {
866 return CAPTURE_WINDOW;
867 }
868 return NO_SPECIAL_LAYER;
869 }
870
CalculateVirtualDirty(std::shared_ptr<RSUniRenderVirtualProcessor> virtualProcesser,RSDisplayRenderParams & params,Drawing::Matrix canvasMatrix)871 std::vector<RectI> RSDisplayRenderNodeDrawable::CalculateVirtualDirty(
872 std::shared_ptr<RSUniRenderVirtualProcessor> virtualProcesser, RSDisplayRenderParams& params,
873 Drawing::Matrix canvasMatrix)
874 {
875 // uniParam/drawable/mirroredParams not null in caller
876 std::vector<RectI> mappedDamageRegionRects;
877 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
878 auto drawable = params.GetMirrorSourceDrawable().lock();
879 auto mirroredDrawable = std::static_pointer_cast<RSDisplayRenderNodeDrawable>(drawable);
880 auto mirrorParams = static_cast<RSDisplayRenderParams*>(mirroredDrawable->GetRenderParams().get());
881 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
882 if (!screenManager) {
883 RS_LOGE("RSDisplayRenderNodeDrawable::CalculateVirtualDirty ScreenManager is nullptr");
884 virtualProcesser->SetRoiRegionToCodec(mappedDamageRegionRects);
885 return mappedDamageRegionRects;
886 }
887 ScreenInfo curScreenInfo = screenManager->QueryScreenInfo(params.GetScreenId());
888 if (!curScreenInfo.isEqualVsyncPeriod) {
889 RS_LOGD("RSDisplayRenderNodeDrawable::CalculateVirtualDirty frame rate is irregular");
890 virtualProcesser->SetRoiRegionToCodec(mappedDamageRegionRects);
891 return mappedDamageRegionRects;
892 }
893 ScreenInfo mainScreenInfo = screenManager->QueryScreenInfo(mirrorParams->GetScreenId());
894 int32_t bufferAge = virtualProcesser->GetBufferAge();
895 std::vector<RectI> damageRegionRects = RSUniRenderUtil::MergeDirtyHistoryInVirtual(
896 *mirroredDrawable, bufferAge, mainScreenInfo);
897 std::shared_ptr<RSObjAbsGeometry> tmpGeo = std::make_shared<RSObjAbsGeometry>();
898 for (auto& rect : damageRegionRects) {
899 RectI mappedRect = tmpGeo->MapRect(rect.ConvertTo<float>(), canvasMatrix);
900 mappedDamageRegionRects.emplace_back(mappedRect);
901 }
902 if (!(lastMatrix_ == canvasMatrix) || !(lastMirrorMatrix_ == mirrorParams->GetMatrix()) ||
903 uniParam->GetForceMirrorScreenDirty() || lastBlackList_ != currentBlackList_ ||
904 mirrorParams->IsSpecialLayerChanged() || lastSecExemption_ != curSecExemption_ || virtualDirtyRefresh_) {
905 GetSyncDirtyManager()->ResetDirtyAsSurfaceSize();
906 virtualDirtyRefresh_ = false;
907 lastMatrix_ = canvasMatrix;
908 lastMirrorMatrix_ = mirrorParams->GetMatrix();
909 }
910 RectI hwcRect = mirroredDrawable->GetSyncDirtyManager()->GetHwcDirtyRegion();
911 if (!hwcRect.IsEmpty()) {
912 RectI mappedHwcRect = tmpGeo->MapRect(hwcRect.ConvertTo<float>(), canvasMatrix);
913 GetSyncDirtyManager()->MergeDirtyRect(mappedHwcRect);
914 }
915 UpdateDisplayDirtyManager(bufferAge, false);
916 auto extraDirty = GetSyncDirtyManager()->GetDirtyRegion();
917 if (!extraDirty.IsEmpty()) {
918 mappedDamageRegionRects.emplace_back(extraDirty);
919 }
920 if (!uniParam->IsVirtualDirtyDfxEnabled()) {
921 virtualProcesser->SetDirtyInfo(mappedDamageRegionRects);
922 RS_TRACE_NAME_FMT("SetDamageRegion damageRegionrects num: %zu, info: %s",
923 mappedDamageRegionRects.size(), RectVectorToString(mappedDamageRegionRects).c_str());
924 }
925 return mappedDamageRegionRects;
926 }
927
DrawMirror(RSDisplayRenderParams & params,std::shared_ptr<RSUniRenderVirtualProcessor> virtualProcesser,DrawFuncPtr drawFunc,RSRenderThreadParams & uniParam)928 void RSDisplayRenderNodeDrawable::DrawMirror(RSDisplayRenderParams& params,
929 std::shared_ptr<RSUniRenderVirtualProcessor> virtualProcesser, DrawFuncPtr drawFunc, RSRenderThreadParams& uniParam)
930 {
931 // uniParam/drawable/mirroredParams not null in caller
932 auto drawable = params.GetMirrorSourceDrawable().lock();
933 auto mirroredDrawable = std::static_pointer_cast<RSDisplayRenderNodeDrawable>(drawable);
934 auto& mirroredParams = mirroredDrawable->GetRenderParams();
935
936 curCanvas_ = virtualProcesser->GetCanvas();
937 if (curCanvas_ == nullptr) {
938 RS_LOGE("RSDisplayRenderNodeDrawable::DrawMirror failed to get canvas.");
939 return;
940 }
941 // for HDR
942 curCanvas_->SetCapture(true);
943 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
944 curCanvas_->SetDisableFilterCache(true);
945 auto mirroedDisplayParams = static_cast<RSDisplayRenderParams*>(mirroredParams.get());
946 auto hasSecSurface = mirroedDisplayParams->GetDisplayHasSecSurface();
947 if (hasSecSurface[mirroredParams->GetScreenId()] && !uniParam.GetSecExemption()) {
948 std::vector<RectI> emptyRects = {};
949 virtualProcesser->SetRoiRegionToCodec(emptyRects);
950 SetCanvasBlack(*virtualProcesser);
951 curCanvas_->RestoreToCount(0);
952 return;
953 }
954 curCanvas_->Save();
955 virtualProcesser->ScaleMirrorIfNeed(GetOriginScreenRotation(), *curCanvas_);
956
957 RSDirtyRectsDfx rsDirtyRectsDfx(*this);
958 if (uniParam.IsVirtualDirtyEnabled()) {
959 Drawing::Matrix matrix = curCanvas_->GetTotalMatrix();
960 std::vector<RectI> dirtyRects = CalculateVirtualDirty(virtualProcesser, params, matrix);
961 rsDirtyRectsDfx.SetVirtualDirtyRects(dirtyRects, params.GetScreenInfo());
962 } else {
963 std::vector<RectI> emptyRects = {};
964 virtualProcesser->SetRoiRegionToCodec(emptyRects);
965 }
966 // Clean up the content of the previous frame
967 curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
968
969 // set mirror screen capture param
970 // Don't need to scale here since the canvas has been switched from mirror frame to offscreen
971 // surface in PrepareOffscreenRender() above. The offscreen surface has the same size as
972 // the main display that's why no need additional scale.
973 RSUniRenderThread::SetCaptureParam(CaptureParam(false, false, true, 1.0f, 1.0f));
974
975 RSRenderParams::SetParentSurfaceMatrix(curCanvas_->GetTotalMatrix());
976 bool isOpDropped = uniParam.IsOpDropped();
977 uniParam.SetOpDropped(false); // disable partial render
978 (mirroredDrawable.get()->*drawFunc)(*curCanvas_);
979 uniParam.SetOpDropped(isOpDropped);
980 RSUniRenderThread::ResetCaptureParam();
981 // Restore the initial state of the canvas to avoid state accumulation
982 curCanvas_->RestoreToCount(0);
983 rsDirtyRectsDfx.OnDrawVirtual(*curCanvas_);
984 RSUniRenderThread::Instance().SetBlackList({});
985 RSUniRenderThread::Instance().SetWhiteList({});
986 uniParam.SetSecExemption(false);
987 }
988
DrawMirrorCopy(RSDisplayRenderNodeDrawable & mirrorDrawable,RSDisplayRenderParams & params,std::shared_ptr<RSUniRenderVirtualProcessor> virtualProcesser,RSRenderThreadParams & uniParam)989 void RSDisplayRenderNodeDrawable::DrawMirrorCopy(
990 RSDisplayRenderNodeDrawable& mirrorDrawable, RSDisplayRenderParams& params,
991 std::shared_ptr<RSUniRenderVirtualProcessor> virtualProcesser, RSRenderThreadParams& uniParam)
992 {
993 auto cacheImage = mirrorDrawable.GetCacheImgForCapture();
994 bool isOpDropped = uniParam.IsOpDropped();
995 uniParam.SetOpDropped(false);
996 mirrorDrawable.SetOriginScreenRotation(GetOriginScreenRotation());
997 virtualProcesser->CalculateTransform(mirrorDrawable);
998 RSDirtyRectsDfx rsDirtyRectsDfx(*this);
999 if (uniParam.IsVirtualDirtyEnabled()) {
1000 auto dirtyRects = CalculateVirtualDirty(
1001 virtualProcesser, params, virtualProcesser->GetCanvasMatrix());
1002 rsDirtyRectsDfx.SetVirtualDirtyRects(dirtyRects, params.GetScreenInfo());
1003 } else {
1004 std::vector<RectI> emptyRects = {};
1005 virtualProcesser->SetRoiRegionToCodec(emptyRects);
1006 }
1007 curCanvas_ = virtualProcesser->GetCanvas();
1008 if (!curCanvas_) {
1009 RS_LOGE("RSDisplayRenderNodeDrawable::DrawMirrorCopy failed to get canvas.");
1010 return;
1011 }
1012 // Clean up the content of the previous frame
1013 curCanvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
1014 virtualProcesser->CanvasClipRegionForUniscaleMode();
1015 RSUniRenderThread::SetCaptureParam(CaptureParam(false, false, true, 1.0f, 1.0f));
1016 mirrorDrawable.DrawHardwareEnabledNodesMissedInCacheImage(*curCanvas_);
1017 if (cacheImage && RSSystemProperties::GetDrawMirrorCacheImageEnabled()) {
1018 RS_TRACE_NAME("DrawMirrorCopy with cacheImage");
1019 RSUniRenderUtil::ProcessCacheImage(*curCanvas_, *cacheImage);
1020 } else {
1021 RS_TRACE_NAME("DrawMirrorCopy with displaySurface");
1022 virtualProcesser->ProcessDisplaySurfaceForRenderThread(mirrorDrawable);
1023 }
1024 mirrorDrawable.DrawHardwareEnabledTopNodesMissedInCacheImage(*curCanvas_);
1025 RSUniRenderThread::ResetCaptureParam();
1026 uniParam.SetOpDropped(isOpDropped);
1027 // Restore the initial state of the canvas to avoid state accumulation
1028 curCanvas_->RestoreToCount(0);
1029 rsDirtyRectsDfx.OnDrawVirtual(*curCanvas_);
1030 }
1031
DrawExpandScreen(RSUniRenderVirtualProcessor & processor)1032 void RSDisplayRenderNodeDrawable::DrawExpandScreen(RSUniRenderVirtualProcessor& processor)
1033 {
1034 curCanvas_ = processor.GetCanvas();
1035 if (curCanvas_ == nullptr) {
1036 RS_LOGE("RSDisplayRenderNodeDrawable::DrawExpandScreen failed to get canvas.");
1037 return;
1038 }
1039 float scaleX = 1.0f;
1040 float scaleY = 1.0f;
1041 // set expand screen capture param(isSnapshot, isSingleSurface, isMirror)
1042 RSUniRenderThread::SetCaptureParam(CaptureParam(false, false, false, scaleX, scaleY));
1043 RSRenderNodeDrawable::OnCapture(*curCanvas_);
1044 RSUniRenderThread::ResetCaptureParam();
1045 // Restore the initial state of the canvas to avoid state accumulation
1046 curCanvas_->RestoreToCount(0);
1047 }
1048
WiredScreenProjection(RSDisplayRenderParams & params,std::shared_ptr<RSProcessor> processor)1049 void RSDisplayRenderNodeDrawable::WiredScreenProjection(
1050 RSDisplayRenderParams& params, std::shared_ptr<RSProcessor> processor)
1051 {
1052 RSUniRenderThread::Instance().WaitUntilDisplayNodeBufferReleased(*this);
1053 auto renderFrame = RequestFrame(params, processor);
1054 if (!renderFrame) {
1055 RS_LOGE("RSDisplayRenderNodeDrawable::WiredScreenProjection failed to request frame");
1056 return;
1057 }
1058 auto drSurface = renderFrame->GetFrame()->GetSurface();
1059 if (!drSurface) {
1060 RS_LOGE("RSDisplayRenderNodeDrawable::WiredScreenProjection DrawingSurface is null");
1061 return;
1062 }
1063 curCanvas_ = std::make_shared<RSPaintFilterCanvas>(drSurface.get());
1064 if (!curCanvas_) {
1065 RS_LOGE("RSDisplayRenderNodeDrawable::WiredScreenProjection failed to create canvas");
1066 return;
1067 }
1068 auto mirroredDrawable =
1069 std::static_pointer_cast<RSDisplayRenderNodeDrawable>(params.GetMirrorSourceDrawable().lock());
1070 if (!mirroredDrawable) {
1071 RS_LOGE("RSDisplayRenderNodeDrawable::WiredScreenProjection mirroredDrawable is null");
1072 return;
1073 }
1074 curCanvas_->Save();
1075 ScaleAndRotateMirrorForWiredScreen(*mirroredDrawable);
1076 RSDirtyRectsDfx rsDirtyRectsDfx(*mirroredDrawable);
1077 std::vector<RectI> damageRegionRects =
1078 CalculateVirtualDirtyForWiredScreen(renderFrame, params, curCanvas_->GetTotalMatrix());
1079 rsDirtyRectsDfx.SetVirtualDirtyRects(damageRegionRects, params.GetScreenInfo());
1080 // HDR does not support wired screen
1081 if (!mirroredDrawable->GetRenderParams()) {
1082 RS_LOGE("RSDisplayRenderNodeDrawable::WiredScreenProjection mirroredDrawable GetRenderParams is null");
1083 return;
1084 }
1085 auto& mirroredParams = static_cast<RSDisplayRenderParams&>(*mirroredDrawable->GetRenderParams());
1086 if (RSSystemParameters::GetWiredScreenOndrawEnabled() &&
1087 (params.GetHDRPresent() || mirroredParams.HasSecurityLayer())) {
1088 DrawWiredMirrorOnDraw(*mirroredDrawable, params);
1089 } else {
1090 DrawWiredMirrorCopy(*mirroredDrawable);
1091 }
1092 curCanvas_->Restore();
1093 rsDirtyRectsDfx.OnDrawVirtual(*curCanvas_);
1094 renderFrame->Flush();
1095 processor->ProcessDisplaySurfaceForRenderThread(*this);
1096 processor->PostProcess();
1097 }
1098
DrawWiredMirrorCopy(RSDisplayRenderNodeDrawable & mirroredDrawable)1099 void RSDisplayRenderNodeDrawable::DrawWiredMirrorCopy(RSDisplayRenderNodeDrawable& mirroredDrawable)
1100 {
1101 auto cacheImage = mirroredDrawable.GetCacheImgForCapture();
1102 if (cacheImage && RSSystemProperties::GetDrawMirrorCacheImageEnabled()) {
1103 RS_TRACE_NAME("DrawWiredMirrorCopy with cacheImage");
1104 RSUniRenderUtil::ProcessCacheImage(*curCanvas_, *cacheImage);
1105 } else {
1106 RS_TRACE_NAME("DrawWiredMirrorCopy with displaySurface");
1107 auto drawParams = RSUniRenderUtil::CreateBufferDrawParam(
1108 *mirroredDrawable.GetRSSurfaceHandlerOnDraw(), false); // false: draw with gpu
1109 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
1110 drawParams.isMirror = true;
1111 renderEngine->DrawDisplayNodeWithParams(*curCanvas_,
1112 *mirroredDrawable.GetRSSurfaceHandlerOnDraw(), drawParams);
1113 }
1114 }
1115
DrawWiredMirrorOnDraw(RSDisplayRenderNodeDrawable & mirroredDrawable,RSDisplayRenderParams & params)1116 void RSDisplayRenderNodeDrawable::DrawWiredMirrorOnDraw(
1117 RSDisplayRenderNodeDrawable& mirroredDrawable, RSDisplayRenderParams& params)
1118 {
1119 auto& uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams();
1120 if (uniParam == nullptr) {
1121 return;
1122 }
1123 curCanvas_->SetCapture(true);
1124 const auto mirroredParams = static_cast<RSDisplayRenderParams*>(mirroredDrawable.GetRenderParams().get());
1125 if (mirroredParams == nullptr) {
1126 return;
1127 }
1128 curCanvas_->SetDisableFilterCache(true);
1129 if (RSMainThread::Instance()->GetDeviceType() != DeviceType::PC) {
1130 auto hasSecSurface = mirroredParams->GetDisplayHasSecSurface();
1131 if (hasSecSurface[mirroredParams->GetScreenId()]) {
1132 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
1133 RS_LOGI("RSDisplayRenderNodeDrawable::DrawWiredMirrorOnDraw, "
1134 "set canvas to black because of security layer.");
1135 return;
1136 }
1137 }
1138 curCanvas_->SetHighContrast(RSUniRenderThread::Instance().IsHighContrastTextModeOn());
1139 bool isOpDropped = uniParam->IsOpDropped();
1140 uniParam->SetOpDropped(false);
1141
1142 auto screenInfo = mirroredParams->GetScreenInfo();
1143 uniParam->SetScreenInfo(screenInfo);
1144 Drawing::Rect rect(0, 0, screenInfo.width, screenInfo.height);
1145 RSUniRenderThread::SetCaptureParam(CaptureParam(false, false, true, 1.0f, 1.0f));
1146 curCanvas_->ClipRect(rect, Drawing::ClipOp::INTERSECT, false);
1147 curCanvas_->ConcatMatrix(mirroredParams->GetMatrix());
1148 RSRenderParams::SetParentSurfaceMatrix(curCanvas_->GetTotalMatrix());
1149 mirroredDrawable.RSRenderNodeDrawable::OnDraw(*curCanvas_);
1150 DrawCurtainScreen();
1151 DrawWatermarkIfNeed(*mirroredParams, *curCanvas_);
1152 SwitchColorFilter(*curCanvas_, 1.f); // 1.f: wired screen not use hdr, use default value 1.f
1153 RSUniRenderThread::ResetCaptureParam();
1154
1155 uniParam->SetOpDropped(isOpDropped);
1156 }
1157
CalculateVirtualDirtyForWiredScreen(std::unique_ptr<RSRenderFrame> & renderFrame,RSDisplayRenderParams & params,Drawing::Matrix canvasMatrix)1158 std::vector<RectI> RSDisplayRenderNodeDrawable::CalculateVirtualDirtyForWiredScreen(
1159 std::unique_ptr<RSRenderFrame>& renderFrame, RSDisplayRenderParams& params, Drawing::Matrix canvasMatrix)
1160 {
1161 std::vector<RectI> damageRegionRects;
1162 auto mirroredDrawable =
1163 std::static_pointer_cast<RSDisplayRenderNodeDrawable>(params.GetMirrorSourceDrawable().lock());
1164 if (!mirroredDrawable || !mirroredDrawable->GetRenderParams()) {
1165 RS_LOGE("RSDisplayRenderNodeDrawable::CalculateVirtualDirtyForWiredScreen mirroredNode is null");
1166 return damageRegionRects;
1167 }
1168 auto uniParam = RSUniRenderThread::Instance().GetRSRenderThreadParams().get();
1169 if (uniParam == nullptr || !uniParam->IsVirtualDirtyEnabled()) {
1170 RS_LOGE("RSDisplayRenderNodeDrawable::CalculateVirtualDirtyForWiredScreen invalid uniparam");
1171 return damageRegionRects;
1172 }
1173 sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
1174 if (screenManager == nullptr) {
1175 RS_LOGE("RSDisplayRenderNodeDrawable::CalculateVirtualDirtyForWiredScreen screenManager is null");
1176 return damageRegionRects;
1177 }
1178 auto curScreenInfo = params.GetScreenInfo();
1179 if (!curScreenInfo.isEqualVsyncPeriod) {
1180 RS_LOGD("RSDisplayRenderNodeDrawable::CalculateVirtualDirtyForWiredScreen frame rate is irregular");
1181 return damageRegionRects;
1182 }
1183 int32_t bufferAge = renderFrame->GetBufferAge();
1184 auto& mirroredParams = mirroredDrawable->GetRenderParams();
1185 ScreenInfo mainScreenInfo = screenManager->QueryScreenInfo(mirroredParams->GetScreenId());
1186 std::shared_ptr<RSObjAbsGeometry> tmpGeo = std::make_shared<RSObjAbsGeometry>();
1187 // merge history dirty and map to mirrored wired screen by matrix
1188 auto tempDamageRegionRects = RSUniRenderUtil::MergeDirtyHistoryInVirtual(
1189 *mirroredDrawable, bufferAge, mainScreenInfo);
1190 for (auto& rect : tempDamageRegionRects) {
1191 RectI mappedRect = tmpGeo->MapRect(rect.ConvertTo<float>(), canvasMatrix);
1192 damageRegionRects.emplace_back(mappedRect);
1193 }
1194
1195 auto syncDirtyManager = GetSyncDirtyManager();
1196 // reset dirty rect as mirrored wired screen size when first time connection or matrix changed
1197 if (!(lastMatrix_ == canvasMatrix)) {
1198 syncDirtyManager->ResetDirtyAsSurfaceSize();
1199 lastMatrix_ = canvasMatrix;
1200 }
1201 UpdateDisplayDirtyManager(bufferAge, false);
1202 auto extraDirty = syncDirtyManager->GetDirtyRegion();
1203 if (!extraDirty.IsEmpty()) {
1204 damageRegionRects.emplace_back(extraDirty);
1205 }
1206 if (!uniParam->IsVirtualDirtyDfxEnabled()) {
1207 renderFrame->SetDamageRegion(damageRegionRects);
1208 }
1209 return damageRegionRects;
1210 }
1211
ScaleAndRotateMirrorForWiredScreen(RSDisplayRenderNodeDrawable & mirroredDrawable)1212 void RSDisplayRenderNodeDrawable::ScaleAndRotateMirrorForWiredScreen(RSDisplayRenderNodeDrawable& mirroredDrawable)
1213 {
1214 const auto& mirroredParams = mirroredDrawable.GetRenderParams();
1215 if (!mirroredParams) {
1216 RS_LOGE("RSDisplayRenderNodeDrawable::ScaleAndRotateMirrorForWiredScreen mirroredParams is null");
1217 return;
1218 }
1219 const auto& nodeParams = GetRenderParams();
1220 if (!nodeParams) {
1221 RS_LOGE("RSDisplayRenderNodeDrawable::ScaleAndRotateMirrorForWiredScreen nodeParams is null");
1222 return;
1223 }
1224 auto mainScreenInfo = mirroredParams->GetScreenInfo();
1225 auto mainWidth = static_cast<float>(mainScreenInfo.width);
1226 auto mainHeight = static_cast<float>(mainScreenInfo.height);
1227 auto mirrorScreenInfo = nodeParams->GetScreenInfo();
1228 auto mirrorWidth = static_cast<float>(mirrorScreenInfo.width);
1229 auto mirrorHeight = static_cast<float>(mirrorScreenInfo.height);
1230 auto rotation = mirroredParams->GetScreenRotation();
1231 auto screenManager = CreateOrGetScreenManager();
1232 if (screenManager) {
1233 auto screenCorrection = screenManager->GetScreenCorrection(mirroredParams->GetScreenId());
1234 if (screenCorrection != ScreenRotation::INVALID_SCREEN_ROTATION &&
1235 screenCorrection != ScreenRotation::ROTATION_0) {
1236 // Recaculate rotation if mirrored screen has additional rotation angle
1237 rotation = static_cast<ScreenRotation>((static_cast<int>(rotation) + SCREEN_ROTATION_NUM
1238 - static_cast<int>(screenCorrection)) % SCREEN_ROTATION_NUM);
1239 }
1240 }
1241 if (rotation == ScreenRotation::ROTATION_90 || rotation == ScreenRotation::ROTATION_270) {
1242 std::swap(mainWidth, mainHeight);
1243 }
1244 curCanvas_->Clear(SK_ColorBLACK);
1245 // Scale
1246 if (mainWidth > 0 && mainHeight > 0) {
1247 auto scaleNum = std::min(mirrorWidth / mainWidth, mirrorHeight / mainHeight);
1248 // 2 for calc X and Y
1249 curCanvas_->Translate((mirrorWidth - (scaleNum * mainWidth)) / 2, (mirrorHeight - (scaleNum * mainHeight)) / 2);
1250 curCanvas_->Scale(scaleNum, scaleNum);
1251 }
1252 // Rotate
1253 RotateMirrorCanvas(rotation, static_cast<float>(mainScreenInfo.width), static_cast<float>(mainScreenInfo.height));
1254 }
1255
SetCanvasBlack(RSProcessor & processor)1256 void RSDisplayRenderNodeDrawable::SetCanvasBlack(RSProcessor& processor)
1257 {
1258 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
1259 processor.PostProcess();
1260 RS_LOGI("RSDisplayRenderNodeDrawable::SetCanvasBlack, set canvas to black because of security layer.");
1261 curCanvas_->SetDisableFilterCache(false);
1262 }
1263
RotateMirrorCanvas(ScreenRotation & rotation,float mainWidth,float mainHeight)1264 void RSDisplayRenderNodeDrawable::RotateMirrorCanvas(ScreenRotation& rotation, float mainWidth, float mainHeight)
1265 {
1266 switch (rotation) {
1267 case ScreenRotation::ROTATION_0:
1268 break;
1269 case ScreenRotation::ROTATION_90:
1270 curCanvas_->Rotate(90, 0, 0); // 90 is the rotate angle
1271 curCanvas_->Translate(0, -mainHeight);
1272 break;
1273 case ScreenRotation::ROTATION_180:
1274 // 180 is the rotate angle, calculate half width and half height requires divide by 2
1275 curCanvas_->Rotate(180, mainWidth / 2, mainHeight / 2);
1276 break;
1277 case ScreenRotation::ROTATION_270:
1278 curCanvas_->Rotate(270, 0, 0); // 270 is the rotate angle
1279 curCanvas_->Translate(-mainWidth, 0);
1280 break;
1281 default:
1282 break;
1283 }
1284 }
1285
OnCapture(Drawing::Canvas & canvas)1286 void RSDisplayRenderNodeDrawable::OnCapture(Drawing::Canvas& canvas)
1287 {
1288 auto params = static_cast<RSDisplayRenderParams*>(GetRenderParams().get());
1289 if (!params) {
1290 RS_LOGE("RSDisplayRenderNodeDrawable::OnCapture params is null!");
1291 return;
1292 }
1293
1294 auto rscanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
1295 if (!rscanvas) {
1296 RS_LOGE("RSDisplayRenderNodeDrawable::OnCapture, rscanvas us nullptr");
1297 return;
1298 }
1299
1300 Drawing::AutoCanvasRestore acr(canvas, true);
1301
1302 specialLayerType_ = GetSpecialLayerType(*params);
1303 if (specialLayerType_ != NO_SPECIAL_LAYER || UNLIKELY(RSUniRenderThread::GetCaptureParam().isMirror_) ||
1304 isRenderSkipIfScreenOff_) {
1305 RS_LOGD("RSDisplayRenderNodeDrawable::OnCapture: \
1306 process RSDisplayRenderNode(id:[%{public}" PRIu64 "]) Not using UniRender buffer.",
1307 params->GetId());
1308 RS_TRACE_NAME("Process RSDisplayRenderNodeDrawable[" +
1309 std::to_string(params->GetScreenId()) + "] Not using UniRender buffer.");
1310
1311 // Adding matrix affine transformation logic
1312 if (!UNLIKELY(RSUniRenderThread::GetCaptureParam().isMirror_)) {
1313 rscanvas->ConcatMatrix(params->GetMatrix());
1314 }
1315
1316 RSRenderNodeDrawable::OnCapture(canvas);
1317 DrawWatermarkIfNeed(*params, *rscanvas);
1318 RSDirtyRectsDfx rsDirtyRectsDfx(*this);
1319 rsDirtyRectsDfx.OnDraw(*rscanvas);
1320 } else {
1321 DrawHardwareEnabledNodes(canvas, *params);
1322 }
1323 }
1324
DrawHardwareEnabledNodes(Drawing::Canvas & canvas,RSDisplayRenderParams & params)1325 void RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodes(Drawing::Canvas& canvas, RSDisplayRenderParams& params)
1326 {
1327 auto rscanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
1328 if (!rscanvas) {
1329 RS_LOGE("RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodes, rscanvas us nullptr");
1330 return;
1331 }
1332
1333 FindHardwareEnabledNodes(params);
1334
1335 if (GetRSSurfaceHandlerOnDraw()->GetBuffer() == nullptr) {
1336 RS_LOGE("RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodes: buffer is null!");
1337 return;
1338 }
1339
1340 uint32_t hwcNodesNum = static_cast<uint32_t>(params.GetHardwareEnabledDrawables().size());
1341 uint32_t hwcTopNodesNum = static_cast<uint32_t>(params.GetHardwareEnabledTopDrawables().size());
1342
1343 RS_LOGI("RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodes: \
1344 process RSDisplayRenderNode(id:[%{public}" PRIu64 "]) \
1345 using UniRender buffer with hwcNodes(%{public}u, %{public}u)",
1346 GetId(), hwcNodesNum, hwcTopNodesNum);
1347 RS_TRACE_NAME_FMT("Process RSDisplayRenderNodeDrawable[%" PRIu64 "] \
1348 using UniRender buffer with hwcNodes(%u, %u)",
1349 params.GetScreenId(), hwcNodesNum, hwcTopNodesNum);
1350
1351 if (hwcNodesNum > 0) {
1352 AdjustZOrderAndDrawSurfaceNode(params.GetHardwareEnabledDrawables(), canvas, params);
1353 }
1354
1355 auto renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
1356 auto drawParams = RSUniRenderUtil::CreateBufferDrawParam(*GetRSSurfaceHandlerOnDraw(), false);
1357
1358 // To get dump image
1359 // execute "param set rosen.dumpsurfacetype.enabled 4 && setenforce 0 && param set rosen.afbc.enabled 0"
1360 RSBaseRenderUtil::WriteSurfaceBufferToPng(drawParams.buffer);
1361 renderEngine->DrawDisplayNodeWithParams(*rscanvas, *GetRSSurfaceHandlerOnDraw(), drawParams);
1362
1363 if (hwcTopNodesNum > 0) {
1364 AdjustZOrderAndDrawSurfaceNode(params.GetHardwareEnabledTopDrawables(), canvas, params);
1365 }
1366 }
1367
DrawHardwareEnabledNodes(Drawing::Canvas & canvas)1368 void RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodes(Drawing::Canvas& canvas)
1369 {
1370 if (!renderParams_) {
1371 RS_LOGE("RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodes params is null!");
1372 return;
1373 }
1374
1375 auto displayParams = static_cast<RSDisplayRenderParams*>(renderParams_.get());
1376 Drawing::AutoCanvasRestore acr(canvas, true);
1377 DrawHardwareEnabledNodes(canvas, *displayParams);
1378 }
1379
DrawHardwareEnabledNodesMissedInCacheImage(Drawing::Canvas & canvas)1380 void RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodesMissedInCacheImage(Drawing::Canvas& canvas)
1381 {
1382 auto params = static_cast<RSDisplayRenderParams*>(GetRenderParams().get());
1383 if (!params) {
1384 RS_LOGE("RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodesMissedInCacheImage params is null!");
1385 return;
1386 }
1387
1388 Drawing::AutoCanvasRestore acr(canvas, true);
1389 FindHardwareEnabledNodes(*params);
1390 if (params->GetHardwareEnabledDrawables().size() != 0) {
1391 AdjustZOrderAndDrawSurfaceNode(params->GetHardwareEnabledDrawables(), canvas, *params);
1392 }
1393 }
1394
DrawHardwareEnabledTopNodesMissedInCacheImage(Drawing::Canvas & canvas)1395 void RSDisplayRenderNodeDrawable::DrawHardwareEnabledTopNodesMissedInCacheImage(Drawing::Canvas& canvas)
1396 {
1397 auto params = static_cast<RSDisplayRenderParams*>(GetRenderParams().get());
1398 if (!params) {
1399 RS_LOGE("RSDisplayRenderNodeDrawable::DrawHardwareEnabledNodesMissedInCacheImage params is null!");
1400 return;
1401 }
1402
1403 Drawing::AutoCanvasRestore acr(canvas, true);
1404 if (params->GetHardwareEnabledTopDrawables().size() != 0) {
1405 AdjustZOrderAndDrawSurfaceNode(params->GetHardwareEnabledTopDrawables(), canvas, *params);
1406 }
1407 }
1408
SwitchColorFilter(RSPaintFilterCanvas & canvas,float hdrBrightnessRatio) const1409 void RSDisplayRenderNodeDrawable::SwitchColorFilter(RSPaintFilterCanvas& canvas, float hdrBrightnessRatio) const
1410 {
1411 const auto& renderEngine = RSUniRenderThread::Instance().GetRenderEngine();
1412 if (!renderEngine) {
1413 RS_LOGE("RSDisplayRenderNodeDrawable::SwitchColorFilter renderEngine is null");
1414 return;
1415 }
1416 ColorFilterMode colorFilterMode = renderEngine->GetColorFilterMode();
1417 if (colorFilterMode == ColorFilterMode::INVERT_COLOR_DISABLE_MODE ||
1418 colorFilterMode >= ColorFilterMode::DALTONIZATION_NORMAL_MODE) {
1419 return;
1420 }
1421
1422 Drawing::AutoCanvasRestore acr(*curCanvas_, true);
1423 RS_TRACE_NAME_FMT("RSDisplayRenderNodeDrawable::SetColorFilterModeToPaint mode:%d",
1424 static_cast<int32_t>(colorFilterMode));
1425 Drawing::Brush brush;
1426 RSBaseRenderUtil::SetColorFilterModeToPaint(colorFilterMode, brush, hdrBrightnessRatio);
1427 #if defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)
1428 #ifdef NEW_RENDER_CONTEXT
1429 RSTagTracker tagTracker(
1430 renderEngine->GetDrawingContext()->GetDrawingContext(),
1431 RSTagTracker::TAG_SAVELAYER_COLOR_FILTER);
1432 #else
1433 RSTagTracker tagTracker(
1434 renderEngine->GetRenderContext()->GetDrGPUContext(),
1435 RSTagTracker::TAG_SAVELAYER_COLOR_FILTER);
1436 #endif
1437 #endif
1438 Drawing::SaveLayerOps slr(nullptr, &brush, Drawing::SaveLayerOps::INIT_WITH_PREVIOUS);
1439 canvas.SaveLayer(slr);
1440 }
1441
FindHardwareEnabledNodes(RSDisplayRenderParams & params)1442 void RSDisplayRenderNodeDrawable::FindHardwareEnabledNodes(RSDisplayRenderParams& params)
1443 {
1444 params.GetHardwareEnabledTopDrawables().clear();
1445 params.GetHardwareEnabledDrawables().clear();
1446 auto& hardwareDrawables =
1447 RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
1448 for (const auto& [displayNodeId, drawable] : hardwareDrawables) {
1449 auto surfaceNodeDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(drawable);
1450 if (!surfaceNodeDrawable || !surfaceNodeDrawable->ShouldPaint() ||
1451 displayNodeId != params.GetId()) {
1452 continue;
1453 }
1454 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(surfaceNodeDrawable->GetRenderParams().get());
1455 if (surfaceParams == nullptr || !surfaceParams->GetHardwareEnabled()) {
1456 continue;
1457 }
1458 // To get dump image
1459 // execute "param set rosen.dumpsurfacetype.enabled 4 && setenforce 0 && param set rosen.afbc.enabled 0"
1460 auto buffer = surfaceParams->GetBuffer();
1461 RSBaseRenderUtil::WriteSurfaceBufferToPng(buffer, surfaceParams->GetId());
1462 if (surfaceNodeDrawable->IsHardwareEnabledTopSurface() || surfaceParams->IsLayerTop()) {
1463 // surfaceNode which should be drawn above displayNode like pointer window
1464 params.GetHardwareEnabledTopDrawables().emplace_back(drawable);
1465 } else {
1466 // surfaceNode which should be drawn below displayNode
1467 params.GetHardwareEnabledDrawables().emplace_back(drawable);
1468 }
1469 }
1470 }
1471
1472
AdjustZOrderAndDrawSurfaceNode(std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr> & drawables,Drawing::Canvas & canvas,RSDisplayRenderParams & params) const1473 void RSDisplayRenderNodeDrawable::AdjustZOrderAndDrawSurfaceNode(
1474 std::vector<DrawableV2::RSRenderNodeDrawableAdapter::SharedPtr>& drawables,
1475 Drawing::Canvas& canvas, RSDisplayRenderParams& params) const
1476 {
1477 if (!RSSystemProperties::GetHardwareComposerEnabled()) {
1478 RS_LOGW("RSDisplayRenderNodeDrawable::AdjustZOrderAndDrawSurfaceNode: \
1479 HardwareComposer is not enabled.");
1480 return;
1481 }
1482
1483 // sort the surfaceNodes by ZOrder
1484 std::stable_sort(drawables.begin(), drawables.end(), [](const auto& first, const auto& second) -> bool {
1485 auto firstDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(first);
1486 auto secondDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(second);
1487 if (!firstDrawable || !firstDrawable->GetRenderParams() ||
1488 !secondDrawable || !secondDrawable->GetRenderParams()) {
1489 return false;
1490 }
1491 return firstDrawable->GetRenderParams()->GetLayerInfo().zOrder <
1492 secondDrawable->GetRenderParams()->GetLayerInfo().zOrder;
1493 });
1494
1495 Drawing::AutoCanvasRestore acr(canvas, true);
1496 auto rscanvas = static_cast<RSPaintFilterCanvas*>(&canvas);
1497 if (!rscanvas) {
1498 RS_LOGE("RSDisplayRenderNodeDrawable::AdjustZOrderAndDrawSurfaceNode, rscanvas is nullptr");
1499 return;
1500 }
1501 // draw hardware-composition nodes
1502 for (auto& drawable : drawables) {
1503 Drawing::AutoCanvasRestore acr(canvas, true);
1504 if (!drawable || !drawable->GetRenderParams()) {
1505 RS_LOGE("RSDisplayRenderNodeDrawable::AdjustZOrderAndDrawSurfaceNode surfaceParams is nullptr");
1506 continue;
1507 }
1508 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
1509 // SelfDrawingNodes need to use LayerMatrix(totalMatrix) when doing capturing
1510 auto matrix = surfaceParams->GetLayerInfo().matrix;
1511 canvas.ConcatMatrix(matrix);
1512 auto surfaceNodeDrawable = std::static_pointer_cast<RSSurfaceRenderNodeDrawable>(drawable);
1513 surfaceNodeDrawable->DealWithSelfDrawingNodeBuffer(*rscanvas, *surfaceParams);
1514 }
1515 }
1516
DrawWatermarkIfNeed(RSDisplayRenderParams & params,RSPaintFilterCanvas & canvas) const1517 void RSDisplayRenderNodeDrawable::DrawWatermarkIfNeed(RSDisplayRenderParams& params, RSPaintFilterCanvas& canvas) const
1518 {
1519 if (!RSUniRenderThread::Instance().GetWatermarkFlag()) {
1520 return;
1521 }
1522 auto image = RSUniRenderThread::Instance().GetWatermarkImg();
1523 if (image == nullptr) {
1524 return;
1525 }
1526 if (auto screenManager = CreateOrGetScreenManager()) {
1527 RS_TRACE_FUNC();
1528 auto screenInfo = screenManager->QueryScreenInfo(params.GetScreenId());
1529 auto mainWidth = static_cast<float>(screenInfo.width);
1530 auto mainHeight = static_cast<float>(screenInfo.height);
1531
1532 // in certain cases (such as fold screen), the width and height must be swapped to fix the screen rotation.
1533 int angle = RSUniRenderUtil::GetRotationFromMatrix(canvas.GetTotalMatrix());
1534 if (angle == RS_ROTATION_90 || angle == RS_ROTATION_270) {
1535 std::swap(mainWidth, mainHeight);
1536 }
1537 auto srcRect = Drawing::Rect(0, 0, image->GetWidth(), image->GetHeight());
1538 auto dstRect = Drawing::Rect(0, 0, mainWidth, mainHeight);
1539 Drawing::Brush rectBrush;
1540 canvas.AttachBrush(rectBrush);
1541 canvas.DrawImageRect(*image, srcRect, dstRect, Drawing::SamplingOptions(),
1542 Drawing::SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT);
1543 canvas.DetachBrush();
1544 }
1545 }
1546
DrawCurtainScreen() const1547 void RSDisplayRenderNodeDrawable::DrawCurtainScreen() const
1548 {
1549 if (!RSUniRenderThread::Instance().IsCurtainScreenOn() || !curCanvas_) {
1550 return;
1551 }
1552 RS_TRACE_FUNC();
1553 curCanvas_->Clear(Drawing::Color::COLOR_BLACK);
1554 }
1555
UpdateSlrScale(ScreenInfo & screenInfo)1556 void RSDisplayRenderNodeDrawable::UpdateSlrScale(ScreenInfo& screenInfo)
1557 {
1558 if (screenInfo.isSamplingOn && RSSystemProperties::GetSLRScaleEnabled()) {
1559 if (slrScale_ == nullptr) {
1560 slrScale_ = std::make_unique<RSSLRScaleFunction>(
1561 screenInfo.phyWidth, screenInfo.phyHeight, screenInfo.width, screenInfo.height);
1562 } else {
1563 slrScale_->CheckOrRefreshScreen(
1564 screenInfo.phyWidth, screenInfo.phyHeight, screenInfo.width, screenInfo.height);
1565 }
1566 screenInfo.samplingDistance = slrScale_->GetKernelSize();
1567 } else {
1568 slrScale_ = nullptr;
1569 }
1570 }
1571
ScaleCanvasIfNeeded(const ScreenInfo & screenInfo)1572 void RSDisplayRenderNodeDrawable::ScaleCanvasIfNeeded(const ScreenInfo& screenInfo)
1573 {
1574 if (!screenInfo.isSamplingOn) {
1575 slrScale_ = nullptr;
1576 return;
1577 }
1578 if (RSSystemProperties::GetSLRScaleEnabled() && slrScale_ != nullptr) {
1579 slrScale_->CanvasScale(*curCanvas_);
1580 return;
1581 }
1582 slrScale_ = nullptr;
1583 curCanvas_->Translate(screenInfo.samplingTranslateX, screenInfo.samplingTranslateY);
1584 curCanvas_->Scale(screenInfo.samplingScale, screenInfo.samplingScale);
1585 }
1586
ClearTransparentBeforeSaveLayer()1587 void RSDisplayRenderNodeDrawable::ClearTransparentBeforeSaveLayer()
1588 {
1589 if (!canvasBackup_) {
1590 return;
1591 }
1592 RS_TRACE_NAME("ClearTransparentBeforeSaveLayer");
1593 auto& hardwareDrawables =
1594 RSUniRenderThread::Instance().GetRSRenderThreadParams()->GetHardwareEnabledTypeDrawables();
1595 if (UNLIKELY(!renderParams_)) {
1596 RS_LOGE("RSDisplayRenderNodeDrawable::OnDraw renderParams is null!");
1597 return;
1598 }
1599 auto params = static_cast<RSDisplayRenderParams*>(renderParams_.get());
1600 for (const auto& [displayNodeId, drawable] : hardwareDrawables) {
1601 auto surfaceDrawable = static_cast<RSSurfaceRenderNodeDrawable*>(drawable.get());
1602 if (!surfaceDrawable || displayNodeId != params->GetId()) {
1603 continue;
1604 }
1605 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(drawable->GetRenderParams().get());
1606 if (!surfaceParams || !surfaceParams->GetHardwareEnabled()) {
1607 continue;
1608 }
1609 RSAutoCanvasRestore arc(canvasBackup_.get());
1610 canvasBackup_->SetMatrix(surfaceParams->GetLayerInfo().matrix);
1611 canvasBackup_->ClipRect(surfaceParams->GetBounds());
1612 canvasBackup_->Clear(Drawing::Color::COLOR_TRANSPARENT);
1613 }
1614 }
1615
PrepareHdrDraw(int32_t offscreenWidth,int32_t offscreenHeight)1616 void RSDisplayRenderNodeDrawable::PrepareHdrDraw(int32_t offscreenWidth, int32_t offscreenHeight)
1617 {
1618 RS_LOGD("HDR PrepareHdrDraw");
1619 offscreenSurface_ = curCanvas_->GetSurface()->MakeSurface(offscreenWidth, offscreenHeight);
1620 }
1621
FinishHdrDraw(Drawing::Brush & paint,float hdrBrightnessRatio)1622 void RSDisplayRenderNodeDrawable::FinishHdrDraw(Drawing::Brush& paint, float hdrBrightnessRatio)
1623 {
1624 RS_LOGD("HDR FinishHdrDraw");
1625 Drawing::Filter filter = paint.GetFilter();
1626 Drawing::ColorMatrix luminanceMatrix;
1627 luminanceMatrix.SetScale(hdrBrightnessRatio, hdrBrightnessRatio, hdrBrightnessRatio, 1.0f);
1628 auto luminanceColorFilter = std::make_shared<Drawing::ColorFilter>(Drawing::ColorFilter::FilterType::MATRIX,
1629 luminanceMatrix);
1630 filter.SetColorFilter(luminanceColorFilter);
1631 paint.SetFilter(filter);
1632 }
1633
PrepareOffscreenRender(const RSDisplayRenderNodeDrawable & displayDrawable,bool useFixedSize,bool useCanvasSize)1634 void RSDisplayRenderNodeDrawable::PrepareOffscreenRender(const RSDisplayRenderNodeDrawable& displayDrawable,
1635 bool useFixedSize, bool useCanvasSize)
1636 {
1637 RS_TRACE_NAME_FMT("%s: useFixedSize:%d, useCanvasSize:%d", __func__, useFixedSize, useCanvasSize);
1638 // params not null in caller
1639 auto params = static_cast<RSDisplayRenderParams*>(displayDrawable.GetRenderParams().get());
1640 // cleanup
1641 canvasBackup_ = nullptr;
1642 // check offscreen size and hardware renderer
1643 useFixedOffscreenSurfaceSize_ = false;
1644 const ScreenInfo& screenInfo = params->GetScreenInfo();
1645 int32_t offscreenWidth = static_cast<int32_t>(screenInfo.width);
1646 int32_t offscreenHeight = static_cast<int32_t>(screenInfo.height);
1647 // use fixed surface size in order to reduce create texture
1648 if (useFixedSize && (RSSystemProperties::IsFoldScreenFlag() || RSSystemProperties::IsTabletType())
1649 && params->IsRotationChanged()) {
1650 useFixedOffscreenSurfaceSize_ = true;
1651 int32_t maxRenderSize =
1652 static_cast<int32_t>(std::max(params->GetScreenInfo().width, params->GetScreenInfo().height));
1653 offscreenWidth = maxRenderSize;
1654 offscreenHeight = maxRenderSize;
1655 }
1656 if (params->IsRotationChanged()) {
1657 if (RSUniRenderThread::Instance().GetVmaOptimizeFlag()) {
1658 Drawing::StaticFactory::SetVmaCacheStatus(true); // render this frame with vma cache on
1659 }
1660 }
1661
1662 if (offscreenWidth <= 0 || offscreenHeight <= 0) {
1663 RS_LOGE("RSDisplayRenderNodeDrawable::PrepareOffscreenRender, offscreenWidth or offscreenHeight is invalid");
1664 return;
1665 }
1666 if (curCanvas_->GetSurface() == nullptr) {
1667 curCanvas_->ClipRect(Drawing::Rect(0, 0, offscreenWidth, offscreenHeight), Drawing::ClipOp::INTERSECT, false);
1668 RS_LOGE("RSDisplayRenderNodeDrawable::PrepareOffscreenRender, current surface is nullptr");
1669 return;
1670 }
1671 if (!(params->GetNeedOffscreen() && useFixedOffscreenSurfaceSize_ && offscreenSurface_ != nullptr)) {
1672 RS_TRACE_NAME_FMT("make offscreen surface with fixed size: [%d, %d]", offscreenWidth, offscreenHeight);
1673 if (!params->GetNeedOffscreen() && params->GetHDRPresent()) {
1674 offscreenWidth = curCanvas_->GetWidth();
1675 offscreenHeight = curCanvas_->GetHeight();
1676 }
1677 if (params->GetHDRPresent()) {
1678 PrepareHdrDraw(offscreenWidth, offscreenHeight);
1679 } else {
1680 offscreenSurface_ = curCanvas_->GetSurface()->MakeSurface(offscreenWidth, offscreenHeight);
1681 }
1682 }
1683
1684 if (offscreenSurface_ == nullptr) {
1685 RS_LOGE("RSDisplayRenderNodeDrawable::PrepareOffscreenRender, offscreenSurface is nullptr");
1686 curCanvas_->ClipRect(Drawing::Rect(0, 0, offscreenWidth, offscreenHeight), Drawing::ClipOp::INTERSECT, false);
1687 return;
1688 }
1689 auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface_.get());
1690
1691 // copy HDR properties into offscreen canvas
1692 offscreenCanvas->CopyHDRConfiguration(*curCanvas_);
1693 // copy current canvas properties into offscreen canvas
1694 offscreenCanvas->CopyConfigurationToOffscreenCanvas(*curCanvas_);
1695
1696 // backup current canvas and replace with offscreen canvas
1697 canvasBackup_ = std::exchange(curCanvas_, offscreenCanvas);
1698 }
1699
FinishOffscreenRender(const Drawing::SamplingOptions & sampling,bool isSamplingOn,float hdrBrightnessRatio)1700 void RSDisplayRenderNodeDrawable::FinishOffscreenRender(
1701 const Drawing::SamplingOptions& sampling, bool isSamplingOn, float hdrBrightnessRatio)
1702 {
1703 RS_TRACE_NAME_FMT("%s: isSamplingOn:%d, hdrBrightnessRatio:%f", __func__, isSamplingOn, hdrBrightnessRatio);
1704 if (canvasBackup_ == nullptr) {
1705 RS_LOGE("RSDisplayRenderNodeDrawable::FinishOffscreenRender, canvasBackup_ is nullptr");
1706 return;
1707 }
1708 if (offscreenSurface_ == nullptr) {
1709 RS_LOGE("RSDisplayRenderNodeDrawable::FinishOffscreenRender, offscreenSurface_ is nullptr");
1710 return;
1711 }
1712 auto image = offscreenSurface_->GetImageSnapshot();
1713 if (image == nullptr) {
1714 RS_LOGE("RSDisplayRenderNodeDrawable::FinishOffscreenRender, Surface::GetImageSnapshot is nullptr");
1715 return;
1716 }
1717 // draw offscreen surface to current canvas
1718 Drawing::Brush paint;
1719 if (ROSEN_LNE(hdrBrightnessRatio, 1.0f)) {
1720 FinishHdrDraw(paint, hdrBrightnessRatio);
1721 }
1722 paint.SetAntiAlias(true);
1723 canvasBackup_->AttachBrush(paint);
1724 if (isSamplingOn) {
1725 if (RSSystemProperties::GetSLRScaleEnabled() && slrScale_) {
1726 slrScale_->ProcessOffscreenImage(*canvasBackup_, *image);
1727 } else {
1728 canvasBackup_->DrawImage(*image, 0, 0, sampling);
1729 }
1730 } else {
1731 canvasBackup_->DrawImage(*image, 0, 0, sampling);
1732 }
1733 canvasBackup_->DetachBrush();
1734 // restore current canvas and cleanup
1735 if (!useFixedOffscreenSurfaceSize_) {
1736 offscreenSurface_ = nullptr;
1737 }
1738 curCanvas_ = std::move(canvasBackup_);
1739 }
1740
1741 #ifndef ROSEN_CROSS_PLATFORM
CreateSurface(sptr<IBufferConsumerListener> listener)1742 bool RSDisplayRenderNodeDrawable::CreateSurface(sptr<IBufferConsumerListener> listener)
1743 {
1744 auto consumer = surfaceHandler_->GetConsumer();
1745 if (consumer != nullptr && surface_ != nullptr) {
1746 RS_LOGI("RSDisplayRenderNode::CreateSurface already created, return");
1747 return true;
1748 }
1749 consumer = IConsumerSurface::Create("DisplayNode");
1750 if (consumer == nullptr) {
1751 RS_LOGE("RSDisplayRenderNode::CreateSurface get consumer surface fail");
1752 return false;
1753 }
1754 SurfaceError ret = consumer->RegisterConsumerListener(listener);
1755 if (ret != SURFACE_ERROR_OK) {
1756 RS_LOGE("RSDisplayRenderNode::CreateSurface RegisterConsumerListener fail");
1757 return false;
1758 }
1759 consumerListener_ = listener;
1760 auto producer = consumer->GetProducer();
1761 sptr<Surface> surface = Surface::CreateSurfaceAsProducer(producer);
1762 if (!surface) {
1763 RS_LOGE("RSDisplayRenderNode::CreateSurface CreateSurfaceAsProducer fail");
1764 return false;
1765 }
1766 surface->SetQueueSize(BUFFER_SIZE);
1767 auto client = std::static_pointer_cast<RSRenderServiceClient>(RSIRenderClient::CreateRenderServiceClient());
1768 surface_ = client->CreateRSSurface(surface);
1769 RS_LOGI("RSDisplayRenderNode::CreateSurface end");
1770 surfaceCreated_ = true;
1771 surfaceHandler_->SetConsumer(consumer);
1772 return true;
1773 }
1774 #endif
1775
SkipFrameByInterval(uint32_t refreshRate,uint32_t skipFrameInterval)1776 bool RSDisplayRenderNodeDrawable::SkipFrameByInterval(uint32_t refreshRate, uint32_t skipFrameInterval)
1777 {
1778 if (refreshRate == 0 || skipFrameInterval <= 1) {
1779 return false;
1780 }
1781 int64_t currentTime = std::chrono::duration_cast<std::chrono::nanoseconds>(
1782 std::chrono::steady_clock::now().time_since_epoch()).count();
1783 // the skipFrameInterval is equal to 60 divide the virtual screen refresh rate
1784 int64_t refreshInterval = currentTime - lastRefreshTime_;
1785 // 1000000000ns == 1s, 110/100 allows 10% over.
1786 bool needSkip = refreshInterval < (1000000000LL / refreshRate) * (skipFrameInterval - 1) * 110 / 100;
1787 if (!needSkip) {
1788 lastRefreshTime_ = currentTime;
1789 }
1790 return needSkip;
1791 }
1792
SkipFrameByRefreshRate(uint32_t refreshRate,uint32_t expectedRefreshRate)1793 bool RSDisplayRenderNodeDrawable::SkipFrameByRefreshRate(uint32_t refreshRate, uint32_t expectedRefreshRate)
1794 {
1795 if (refreshRate == 0 || expectedRefreshRate == 0 || refreshRate == expectedRefreshRate) {
1796 return false;
1797 }
1798 int64_t currentTime = RSMainThread::Instance()->GetCurrentVsyncTime();
1799 int64_t minFrameInterval = 1000000000LL / expectedRefreshRate;
1800 if (minFrameInterval == 0) {
1801 return false;
1802 }
1803 // lastRefreshTime_ is next frame expected refresh time for virtual display
1804 if (lastRefreshTime_ <= 0) {
1805 lastRefreshTime_ = currentTime + minFrameInterval;
1806 return false;
1807 }
1808 if (currentTime < (lastRefreshTime_ - MAX_JITTER_NS)) {
1809 return true;
1810 }
1811 int64_t intervalNums = (currentTime - lastRefreshTime_ + MAX_JITTER_NS) / minFrameInterval;
1812 lastRefreshTime_ += (intervalNums + 1) * minFrameInterval;
1813 return false;
1814 }
1815
SkipFrame(uint32_t refreshRate,ScreenInfo screenInfo)1816 bool RSDisplayRenderNodeDrawable::SkipFrame(uint32_t refreshRate, ScreenInfo screenInfo)
1817 {
1818 bool needSkip = false;
1819 switch (screenInfo.skipFrameStrategy) {
1820 case SKIP_FRAME_BY_INTERVAL:
1821 needSkip = SkipFrameByInterval(refreshRate, screenInfo.skipFrameInterval);
1822 break;
1823 case SKIP_FRAME_BY_REFRESH_RATE:
1824 needSkip = SkipFrameByRefreshRate(refreshRate, screenInfo.expectedRefreshRate);
1825 break;
1826 default:
1827 break;
1828 }
1829 return needSkip;
1830 }
1831 } // namespace OHOS::Rosen::DrawableV2
1832