1 /*
2 * Copyright (c) 2021-2023 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 #include "pipeline/rs_uni_render_thread.h"
16
17 #include <malloc.h>
18 #include <memory>
19 #include <parameters.h>
20
21 #include "common/rs_common_def.h"
22 #include "common/rs_optional_trace.h"
23 #include "common/rs_singleton.h"
24 #include "drawable/rs_display_render_node_drawable.h"
25 #include "drawable/rs_property_drawable_utils.h"
26 #include "drawable/rs_surface_render_node_drawable.h"
27 #include "graphic_common_c.h"
28 #include "hgm_core.h"
29 #include "include/core/SkGraphics.h"
30 #include "include/gpu/GrDirectContext.h"
31 #include "static_factory.h"
32 #include "memory/rs_memory_manager.h"
33 #include "params/rs_display_render_params.h"
34 #include "params/rs_surface_render_params.h"
35 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
36 #include "pipeline/round_corner_display/rs_round_corner_display.h"
37 #include "pipeline/rs_hardware_thread.h"
38 #include "pipeline/rs_main_thread.h"
39 #include "pipeline/rs_render_node_gc.h"
40 #include "pipeline/rs_surface_handler.h"
41 #include "pipeline/rs_task_dispatcher.h"
42 #include "pipeline/rs_uifirst_manager.h"
43 #include "pipeline/rs_uni_render_engine.h"
44 #include "pipeline/rs_uni_render_util.h"
45 #include "pipeline/sk_resource_manager.h"
46 #include "platform/common/rs_log.h"
47 #include "platform/ohos/rs_jank_stats.h"
48 #include "platform/ohos/rs_node_stats.h"
49 #include "rs_trace.h"
50 #include "surface.h"
51 #include "sync_fence.h"
52 #include "system/rs_system_parameters.h"
53 #ifdef RES_SCHED_ENABLE
54 #include "system_ability_definition.h"
55 #include "if_system_ability_manager.h"
56 #include <iservice_registry.h>
57 #endif
58
59 #ifdef SOC_PERF_ENABLE
60 #include "socperf_client.h"
61 #endif
62
63 namespace OHOS {
64 namespace Rosen {
65 namespace {
66 constexpr const char* CLEAR_GPU_CACHE = "ClearGpuCache";
67 constexpr const char* DEFAULT_CLEAR_GPU_CACHE = "DefaultClearGpuCache";
68 constexpr const char* PURGE_CACHE_BETWEEN_FRAMES = "PurgeCacheBetweenFrames";
69 constexpr const char* SUPPRESS_GPUCACHE_BELOW_CERTAIN_RATIO = "SuppressGpuCacheBelowCertainRatio";
70 const std::string PERF_FOR_BLUR_IF_NEEDED_TASK_NAME = "PerfForBlurIfNeeded";
71 constexpr uint32_t TIME_OF_EIGHT_FRAMES = 8000;
72 constexpr uint32_t TIME_OF_THE_FRAMES = 1000;
73 constexpr uint32_t TIME_OF_DEFAULT_CLEAR_GPU_CACHE = 5000;
74 constexpr uint32_t WAIT_FOR_RELEASED_BUFFER_TIMEOUT = 3000;
75 constexpr uint32_t RELEASE_IN_HARDWARE_THREAD_TASK_NUM = 4;
76 constexpr uint64_t PERF_PERIOD_BLUR = 480000000;
77 constexpr uint64_t PERF_PERIOD_BLUR_TIMEOUT = 80000000;
78 constexpr uint64_t ONE_MEGABYTE = 1000 * 1000;
79
80 const std::map<int, int32_t> BLUR_CNT_TO_BLUR_CODE {
81 { 1, 10021 },
82 { 2, 10022 },
83 { 3, 10023 },
84 };
85
PerfRequest(int32_t perfRequestCode,bool onOffTag)86 void PerfRequest(int32_t perfRequestCode, bool onOffTag)
87 {
88 #ifdef SOC_PERF_ENABLE
89 OHOS::SOCPERF::SocPerfClient::GetInstance().PerfRequestEx(perfRequestCode, onOffTag, "");
90 RS_LOGD("RSUniRenderThread::soc perf info [%{public}d %{public}d]", perfRequestCode, onOffTag);
91 #endif
92 }
93 };
94
95 thread_local CaptureParam RSUniRenderThread::captureParam_ = {};
96
SetCaptureParam(const CaptureParam & param)97 void RSUniRenderThread::SetCaptureParam(const CaptureParam& param)
98 {
99 captureParam_ = param;
100 }
101
GetCaptureParam()102 CaptureParam& RSUniRenderThread::GetCaptureParam()
103 {
104 return captureParam_;
105 }
106
ResetCaptureParam()107 void RSUniRenderThread::ResetCaptureParam()
108 {
109 captureParam_ = {};
110 }
111
IsInCaptureProcess()112 bool RSUniRenderThread::IsInCaptureProcess()
113 {
114 return captureParam_.isSnapshot_ || captureParam_.isMirror_;
115 }
116
Instance()117 RSUniRenderThread& RSUniRenderThread::Instance()
118 {
119 static RSUniRenderThread instance;
120 return instance;
121 }
122
RSUniRenderThread()123 RSUniRenderThread::RSUniRenderThread()
124 :postImageReleaseTaskFlag_(Rosen::RSSystemProperties::GetImageReleaseUsingPostTask())
125 {}
126
~RSUniRenderThread()127 RSUniRenderThread::~RSUniRenderThread() noexcept {}
128
InitGrContext()129 void RSUniRenderThread::InitGrContext()
130 {
131 // uniRenderEngine must be inited on the same thread with requestFrame
132 uniRenderEngine_ = std::make_shared<RSUniRenderEngine>();
133 if (!uniRenderEngine_) {
134 RS_LOGE("uniRenderEngine_ is nullptr");
135 return;
136 }
137 uniRenderEngine_->Init();
138 #ifdef RS_ENABLE_VK
139 if (Drawing::SystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
140 Drawing::SystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
141 uniRenderEngine_->GetSkContext()->RegisterPostFunc([](const std::function<void()>& task) {
142 RSUniRenderThread::Instance().PostImageReleaseTask(task);
143 });
144 }
145 if (Drawing::SystemProperties::GetGpuApiType() == GpuApiType::VULKAN) {
146 if (RSSystemProperties::IsFoldScreenFlag()) {
147 vmaOptimizeFlag_ = true;
148 }
149 }
150 #endif
151 auto renderContext = uniRenderEngine_->GetRenderContext();
152 if (!renderContext) {
153 return;
154 }
155 auto grContext = renderContext->GetDrGPUContext();
156 if (!grContext) {
157 return;
158 }
159 MemoryManager::SetGpuMemoryAsyncReclaimerSwitch(
160 grContext, RSSystemProperties::GetGpuMemoryAsyncReclaimerEnabled());
161 MemoryManager::SetGpuCacheSuppressWindowSwitch(
162 grContext, RSSystemProperties::GetGpuCacheSuppressWindowEnabled());
163 }
164
Inittcache()165 void RSUniRenderThread::Inittcache()
166 {
167 if (RSSystemParameters::GetTcacheEnabled()) {
168 // enable cache
169 mallopt(M_SET_THREAD_CACHE, M_THREAD_CACHE_ENABLE);
170 }
171 }
172
Start()173 void RSUniRenderThread::Start()
174 {
175 runner_ = AppExecFwk::EventRunner::Create("RSUniRenderThread");
176 if (!runner_) {
177 RS_LOGE("RSUniRenderThread Start runner null");
178 return;
179 }
180 handler_ = std::make_shared<AppExecFwk::EventHandler>(runner_);
181 runner_->Run();
182 auto postTaskProxy = [](RSTaskMessage::RSTask task, const std::string& name, int64_t delayTime,
183 AppExecFwk::EventQueue::Priority priority) {
184 RSUniRenderThread::Instance().PostTask(task, name, delayTime, priority);
185 };
186 RSRenderNodeGC::Instance().SetRenderTask(postTaskProxy);
187 PostSyncTask([this] {
188 RS_LOGE("RSUniRenderThread Started ...");
189 Inittcache();
190 InitGrContext();
191 tid_ = gettid();
192 #ifdef RES_SCHED_ENABLE
193 SubScribeSystemAbility();
194 #endif
195 });
196
197 auto taskDispatchFunc = [this](const RSTaskDispatcher::RSTask& task, bool isSyncTask = false) {
198 if (isSyncTask) {
199 PostSyncTask(task);
200 } else {
201 PostTask(task);
202 }
203 };
204 RSTaskDispatcher::GetInstance().RegisterTaskDispatchFunc(tid_, taskDispatchFunc);
205
206 if (!rootNodeDrawable_) {
207 const std::shared_ptr<RSBaseRenderNode> rootNode =
208 RSMainThread::Instance()->GetContext().GetGlobalRootRenderNode();
209 if (!rootNode) {
210 RS_LOGE("rootNode is nullptr");
211 return;
212 }
213 auto ptr = DrawableV2::RSRenderNodeDrawableAdapter::OnGenerate(rootNode);
214 rootNodeDrawable_ = std::static_pointer_cast<DrawableV2::RSRenderNodeDrawable>(ptr);
215 }
216 }
217
GetRenderEngine() const218 std::shared_ptr<RSBaseRenderEngine> RSUniRenderThread::GetRenderEngine() const
219 {
220 return uniRenderEngine_;
221 }
222
PostTask(const std::function<void ()> & task)223 void RSUniRenderThread::PostTask(const std::function<void()>& task)
224 {
225 if (!handler_) {
226 return;
227 }
228 handler_->PostTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
229 }
230
PostRTTask(const std::function<void ()> & task)231 void RSUniRenderThread::PostRTTask(const std::function<void()>& task)
232 {
233 auto tid = gettid();
234 if (tid == tid_) {
235 task();
236 } else {
237 PostTask(task);
238 }
239 }
240
PostImageReleaseTask(const std::function<void ()> & task)241 void RSUniRenderThread::PostImageReleaseTask(const std::function<void()>& task)
242 {
243 imageReleaseCount_++;
244 if (postImageReleaseTaskFlag_) {
245 PostRTTask(task);
246 return;
247 }
248 if (tid_ == gettid()) {
249 task();
250 return;
251 }
252 std::unique_lock<std::mutex> releaseLock(imageReleaseMutex_);
253 imageReleaseTasks_.push_back(task);
254 }
255
RunImageReleaseTask()256 void RSUniRenderThread::RunImageReleaseTask()
257 {
258 if (postImageReleaseTaskFlag_) { // release using post task
259 RS_TRACE_NAME_FMT("RunImageReleaseTask using PostTask: count %d", imageReleaseCount_);
260 imageReleaseCount_ = 0;
261 return;
262 }
263 std::vector<Callback> tasks;
264 {
265 std::unique_lock<std::mutex> releaseLock(imageReleaseMutex_);
266 std::swap(imageReleaseTasks_, tasks);
267 }
268 if (tasks.empty()) {
269 return;
270 }
271 RS_TRACE_NAME_FMT("RunImageReleaseTask: count %d", imageReleaseCount_);
272 imageReleaseCount_ = 0;
273 for (auto task : tasks) {
274 task();
275 }
276 }
277
ClearResource()278 void RSUniRenderThread::ClearResource()
279 {
280 RunImageReleaseTask();
281 DrawableV2::RSRenderNodeDrawableAdapter::ClearResource();
282 }
283
PostTask(RSTaskMessage::RSTask task,const std::string & name,int64_t delayTime,AppExecFwk::EventQueue::Priority priority)284 void RSUniRenderThread::PostTask(RSTaskMessage::RSTask task, const std::string& name, int64_t delayTime,
285 AppExecFwk::EventQueue::Priority priority)
286 {
287 if (handler_) {
288 handler_->PostTask(task, name, delayTime, priority);
289 }
290 }
291
RemoveTask(const std::string & name)292 void RSUniRenderThread::RemoveTask(const std::string& name)
293 {
294 if (handler_) {
295 handler_->RemoveTask(name);
296 }
297 }
298
PostSyncTask(const std::function<void ()> & task)299 void RSUniRenderThread::PostSyncTask(const std::function<void()>& task)
300 {
301 if (!handler_) {
302 return;
303 }
304 handler_->PostSyncTask(task, AppExecFwk::EventQueue::Priority::IMMEDIATE);
305 }
306
IsIdle() const307 bool RSUniRenderThread::IsIdle() const
308 {
309 return handler_ ? handler_->IsIdle() : false;
310 }
311
Sync(std::unique_ptr<RSRenderThreadParams> && stagingRenderThreadParams)312 void RSUniRenderThread::Sync(std::unique_ptr<RSRenderThreadParams>&& stagingRenderThreadParams)
313 {
314 RSRenderThreadParamsManager::Instance().SetRSRenderThreadParams(std::move(stagingRenderThreadParams));
315 }
316
Render()317 void RSUniRenderThread::Render()
318 {
319 if (!rootNodeDrawable_) {
320 RS_LOGE("rootNodeDrawable is nullptr");
321 }
322 if (vmaOptimizeFlag_) { // render this frame with vma cache on/off
323 std::lock_guard<std::mutex> lock(vmaCacheCountMutex_);
324 if (vmaCacheCount_ > 0) {
325 vmaCacheCount_--;
326 Drawing::StaticFactory::SetVmaCacheStatus(true);
327 } else {
328 Drawing::StaticFactory::SetVmaCacheStatus(false);
329 }
330 }
331 Drawing::Canvas canvas;
332 RSNodeStats::GetInstance().ClearNodeStats();
333 rootNodeDrawable_->OnDraw(canvas);
334 RSNodeStats::GetInstance().ReportRSNodeLimitExceeded();
335 PerfForBlurIfNeeded();
336 }
337
ReleaseSelfDrawingNodeBuffer()338 void RSUniRenderThread::ReleaseSelfDrawingNodeBuffer()
339 {
340 auto& renderThreadParams = GetRSRenderThreadParams();
341 if (!renderThreadParams) {
342 return;
343 }
344 std::vector<std::function<void()>> releaseTasks;
345 for (const auto& drawable : renderThreadParams->GetSelfDrawables()) {
346 if (UNLIKELY(!drawable)) {
347 continue;
348 }
349 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
350 auto& params = surfaceDrawable->GetRenderParams();
351 if (UNLIKELY(!params)) {
352 continue;
353 }
354 auto surfaceParams = static_cast<RSSurfaceRenderParams*>(params.get());
355 if (UNLIKELY(!surfaceParams)) {
356 continue;
357 }
358 bool needRelease = !surfaceParams->GetHardwareEnabled() || !surfaceParams->GetLayerCreated();
359 if (needRelease && surfaceParams->GetLastFrameHardwareEnabled()) {
360 surfaceParams->releaseInHardwareThreadTaskNum_ = RELEASE_IN_HARDWARE_THREAD_TASK_NUM;
361 }
362 if (needRelease) {
363 auto preBuffer = params->GetPreBuffer();
364 if (preBuffer == nullptr) {
365 if (surfaceParams->releaseInHardwareThreadTaskNum_ > 0) {
366 surfaceParams->releaseInHardwareThreadTaskNum_--;
367 }
368 continue;
369 }
370 auto surfaceDrawable = std::static_pointer_cast<DrawableV2::RSSurfaceRenderNodeDrawable>(drawable);
371 auto releaseTask = [buffer = preBuffer, consumer = surfaceDrawable->GetConsumerOnDraw(),
372 useReleaseFence = surfaceParams->GetLastFrameHardwareEnabled(),
373 acquireFence = acquireFence_]() mutable {
374 auto ret = consumer->ReleaseBuffer(buffer, useReleaseFence ?
375 RSHardwareThread::Instance().releaseFence_ : acquireFence);
376 if (ret != OHOS::SURFACE_ERROR_OK) {
377 RS_LOGD("ReleaseSelfDrawingNodeBuffer failed ret:%{public}d", ret);
378 }
379 };
380 params->SetPreBuffer(nullptr);
381 if (surfaceParams->releaseInHardwareThreadTaskNum_ > 0) {
382 releaseTasks.emplace_back(releaseTask);
383 surfaceParams->releaseInHardwareThreadTaskNum_--;
384 } else {
385 releaseTask();
386 }
387 }
388 }
389 if (releaseTasks.empty()) {
390 return;
391 }
392 auto releaseBufferTask = [releaseTasks]() {
393 for (const auto& task : releaseTasks) {
394 task();
395 }
396 };
397 auto delayTime = RSHardwareThread::Instance().delayTime_;
398 if (delayTime > 0) {
399 RSHardwareThread::Instance().PostDelayTask(releaseBufferTask, delayTime);
400 } else {
401 RSHardwareThread::Instance().PostTask(releaseBufferTask);
402 }
403 }
404
ReleaseSurface()405 void RSUniRenderThread::ReleaseSurface()
406 {
407 std::lock_guard<std::mutex> lock(mutex_);
408 while (tmpSurfaces_.size() > 0) {
409 auto tmp = tmpSurfaces_.front();
410 tmpSurfaces_.pop();
411 tmp = nullptr;
412 }
413 }
414
AddToReleaseQueue(std::shared_ptr<Drawing::Surface> && surface)415 void RSUniRenderThread::AddToReleaseQueue(std::shared_ptr<Drawing::Surface>&& surface)
416 {
417 std::lock_guard<std::mutex> lock(mutex_);
418 tmpSurfaces_.push(std::move(surface));
419 }
420
GetCurrentTimestamp() const421 uint64_t RSUniRenderThread::GetCurrentTimestamp() const
422 {
423 auto& renderThreadParams = GetRSRenderThreadParams();
424 return renderThreadParams ? renderThreadParams->GetCurrentTimestamp() : 0;
425 }
426
GetPendingScreenRefreshRate() const427 uint32_t RSUniRenderThread::GetPendingScreenRefreshRate() const
428 {
429 auto& renderThreadParams = GetRSRenderThreadParams();
430 return renderThreadParams ? renderThreadParams->GetPendingScreenRefreshRate() : 0;
431 }
432
GetPendingConstraintRelativeTime() const433 uint64_t RSUniRenderThread::GetPendingConstraintRelativeTime() const
434 {
435 auto& renderThreadParams = GetRSRenderThreadParams();
436 return renderThreadParams ? renderThreadParams->GetPendingConstraintRelativeTime() : 0;
437 }
438
439 #ifdef RES_SCHED_ENABLE
SubScribeSystemAbility()440 void RSUniRenderThread::SubScribeSystemAbility()
441 {
442 RS_LOGD("%{public}s", __func__);
443 sptr<ISystemAbilityManager> systemAbilityManager =
444 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
445 if (!systemAbilityManager) {
446 RS_LOGE("%{public}s failed to get system ability manager client", __func__);
447 return;
448 }
449 std::string threadName = "RSHardwareThread";
450 std::string strUid = std::to_string(getuid());
451 std::string strPid = std::to_string(getpid());
452 std::string strTid = std::to_string(gettid());
453
454 saStatusChangeListener_ = new (std::nothrow)VSyncSystemAbilityListener(threadName, strUid, strPid, strTid);
455 int32_t ret = systemAbilityManager->SubscribeSystemAbility(RES_SCHED_SYS_ABILITY_ID, saStatusChangeListener_);
456 if (ret != ERR_OK) {
457 RS_LOGE("%{public}s subscribe system ability %{public}d failed.", __func__, RES_SCHED_SYS_ABILITY_ID);
458 saStatusChangeListener_ = nullptr;
459 }
460 }
461 #endif
WaitUntilDisplayNodeBufferReleased(DrawableV2::RSDisplayRenderNodeDrawable & displayNodeDrawable)462 bool RSUniRenderThread::WaitUntilDisplayNodeBufferReleased(
463 DrawableV2::RSDisplayRenderNodeDrawable& displayNodeDrawable)
464 {
465 std::unique_lock<std::mutex> lock(displayNodeBufferReleasedMutex_);
466 displayNodeBufferReleased_ = false; // prevent spurious wakeup of condition variable
467 if (!displayNodeDrawable.IsSurfaceCreated()) {
468 return true;
469 }
470 auto consumer = displayNodeDrawable.GetRSSurfaceHandlerOnDraw()->GetConsumer();
471 if (consumer && consumer->QueryIfBufferAvailable()) {
472 return true;
473 }
474 return displayNodeBufferReleasedCond_.wait_until(lock, std::chrono::system_clock::now() +
475 std::chrono::milliseconds(WAIT_FOR_RELEASED_BUFFER_TIMEOUT), [this]() { return displayNodeBufferReleased_; });
476 }
477
NotifyDisplayNodeBufferReleased()478 void RSUniRenderThread::NotifyDisplayNodeBufferReleased()
479 {
480 RS_TRACE_NAME("RSUniRenderThread::NotifyDisplayNodeBufferReleased");
481 std::lock_guard<std::mutex> lock(displayNodeBufferReleasedMutex_);
482 displayNodeBufferReleased_ = true;
483 displayNodeBufferReleasedCond_.notify_one();
484 }
485
PerfForBlurIfNeeded()486 void RSUniRenderThread::PerfForBlurIfNeeded()
487 {
488 if (!handler_) {
489 return;
490 }
491 handler_->RemoveTask(PERF_FOR_BLUR_IF_NEEDED_TASK_NAME);
492 static uint64_t prePerfTimestamp = 0;
493 static int preBlurCnt = 0;
494 static int cnt = 0;
495 auto params = GetRSRenderThreadParams().get();
496 if (!params) {
497 return;
498 }
499 auto threadTimestamp = params->GetCurrentTimestamp();
500
501 auto task = [this]() {
502 if (preBlurCnt == 0) {
503 return;
504 }
505 auto now = std::chrono::steady_clock::now().time_since_epoch();
506 auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
507 RS_OPTIONAL_TRACE_NAME_FMT("PerfForBlurIfNeeded now[%ld] timestamp[%ld] preBlurCnt[%d]",
508 now, timestamp, preBlurCnt);
509 if (static_cast<uint64_t>(timestamp) - prePerfTimestamp > PERF_PERIOD_BLUR_TIMEOUT) {
510 PerfRequest(BLUR_CNT_TO_BLUR_CODE.at(preBlurCnt), false);
511 prePerfTimestamp = 0;
512 preBlurCnt = 0;
513 }
514 };
515
516 // delay 100ms
517 handler_->PostTask(task, PERF_FOR_BLUR_IF_NEEDED_TASK_NAME, 100);
518 int blurCnt = RSPropertyDrawableUtils::GetAndResetBlurCnt();
519 // clamp blurCnt to 0~3.
520 blurCnt = std::clamp<int>(blurCnt, 0, 3);
521 cnt = (blurCnt < preBlurCnt) ? (cnt + 1) : 0;
522
523 // if blurCnt > preBlurCnt, than change perf code;
524 // if blurCnt < preBlurCnt 10 times continuously, than change perf code.
525 bool cntIsMatch = blurCnt > preBlurCnt || cnt > 10;
526 if (cntIsMatch && preBlurCnt != 0) {
527 RS_OPTIONAL_TRACE_NAME_FMT("PerfForBlurIfNeeded Perf close, preBlurCnt[%d] blurCnt[%ld]", preBlurCnt, blurCnt);
528 PerfRequest(BLUR_CNT_TO_BLUR_CODE.at(preBlurCnt), false);
529 preBlurCnt = blurCnt == 0 ? 0 : preBlurCnt;
530 }
531 if (blurCnt == 0) {
532 return;
533 }
534 if (threadTimestamp - prePerfTimestamp > PERF_PERIOD_BLUR || cntIsMatch) {
535 RS_OPTIONAL_TRACE_NAME_FMT("PerfForBlurIfNeeded PerfRequest, preBlurCnt[%d] blurCnt[%ld]", preBlurCnt, blurCnt);
536 PerfRequest(BLUR_CNT_TO_BLUR_CODE.at(blurCnt), true);
537 prePerfTimestamp = threadTimestamp;
538 preBlurCnt = blurCnt;
539 }
540 }
541
GetClearMemoryFinished() const542 bool RSUniRenderThread::GetClearMemoryFinished() const
543 {
544 std::lock_guard<std::mutex> lock(clearMemoryMutex_);
545 return clearMemoryFinished_;
546 }
547
GetClearMemDeeply() const548 bool RSUniRenderThread::GetClearMemDeeply() const
549 {
550 std::lock_guard<std::mutex> lock(clearMemoryMutex_);
551 return clearMemDeeply_;
552 }
553
SetClearMoment(ClearMemoryMoment moment)554 void RSUniRenderThread::SetClearMoment(ClearMemoryMoment moment)
555 {
556 clearMoment_ = moment;
557 }
558
GetClearMoment() const559 ClearMemoryMoment RSUniRenderThread::GetClearMoment() const
560 {
561 std::lock_guard<std::mutex> lock(clearMemoryMutex_);
562 return clearMoment_;
563 }
564
GetRefreshRate() const565 uint32_t RSUniRenderThread::GetRefreshRate() const
566 {
567 auto screenManager = CreateOrGetScreenManager();
568 if (!screenManager) {
569 RS_LOGE("RSUniRenderThread::GetRefreshRate screenManager is nullptr");
570 return 60; // The default refreshrate is 60
571 }
572 return HgmCore::Instance().GetScreenCurrentRefreshRate(screenManager->GetDefaultScreenId());
573 }
574
GetWatermarkImg()575 std::shared_ptr<Drawing::Image> RSUniRenderThread::GetWatermarkImg()
576 {
577 auto& renderThreadParams = GetRSRenderThreadParams();
578 return renderThreadParams ? renderThreadParams->GetWatermarkImg() : nullptr;
579 }
580
GetWatermarkFlag() const581 bool RSUniRenderThread::GetWatermarkFlag() const
582 {
583 auto& renderThreadParams = GetRSRenderThreadParams();
584 return renderThreadParams ? renderThreadParams->GetWatermarkFlag() : false;
585 }
586
IsCurtainScreenOn() const587 bool RSUniRenderThread::IsCurtainScreenOn() const
588 {
589 auto& renderThreadParams = GetRSRenderThreadParams();
590 return renderThreadParams ? renderThreadParams->IsCurtainScreenOn() : false;
591 }
592
FormatNumber(size_t number)593 std::string FormatNumber(size_t number)
594 {
595 constexpr uint8_t FORMATE_NUM_STEP = 3;
596 std::string strNumber = std::to_string(number);
597 int n = strNumber.length();
598 for (int i = n - FORMATE_NUM_STEP; i > 0; i -= FORMATE_NUM_STEP) {
599 strNumber.insert(i, ",");
600 }
601 return strNumber;
602 }
603
TrimMemEmptyType(Drawing::GPUContext * gpuContext)604 static void TrimMemEmptyType(Drawing::GPUContext* gpuContext)
605 {
606 gpuContext->Flush();
607 SkGraphics::PurgeAllCaches();
608 gpuContext->FreeGpuResources();
609 gpuContext->PurgeUnlockedResources(true);
610 #ifdef NEW_RENDER_CONTEXT
611 MemoryHandler::ClearShader();
612 #else
613 std::shared_ptr<RenderContext> rendercontext = std::make_shared<RenderContext>();
614 rendercontext->CleanAllShaderCache();
615 #endif
616 gpuContext->FlushAndSubmit(true);
617 }
618
TrimMemShaderType()619 static void TrimMemShaderType()
620 {
621 #ifdef NEW_RENDER_CONTEXT
622 MemoryHandler::ClearShader();
623 #else
624 std::shared_ptr<RenderContext> rendercontext = std::make_shared<RenderContext>();
625 rendercontext->CleanAllShaderCache();
626 #endif
627 }
628
TrimMemGpuLimitType(Drawing::GPUContext * gpuContext,std::string & dumpString,std::string & type,const std::string & typeGpuLimit)629 static void TrimMemGpuLimitType(Drawing::GPUContext* gpuContext, std::string& dumpString,
630 std::string& type, const std::string& typeGpuLimit)
631 {
632 size_t cacheLimit = 0;
633 int maxResources;
634 gpuContext->GetResourceCacheLimits(&maxResources, &cacheLimit);
635
636 constexpr int MAX_GPU_LIMIT_SIZE = 4000;
637 std::string strM = type.substr(typeGpuLimit.length());
638 size_t maxResourcesBytes = cacheLimit; // max 4G
639 char* end = nullptr;
640 errno = 0;
641 long long sizeM = std::strtoll(strM.c_str(), &end, 10);
642 if (end != nullptr && end != strM.c_str() && errno == 0 && *end == '\0' &&
643 sizeM > 0 && sizeM <= MAX_GPU_LIMIT_SIZE) {
644 maxResourcesBytes = sizeM * ONE_MEGABYTE;
645 }
646
647 gpuContext->SetResourceCacheLimits(maxResources, maxResourcesBytes);
648 dumpString.append("setgpulimit: " + FormatNumber(cacheLimit)
649 + "==>" + FormatNumber(maxResourcesBytes) + "\n");
650 }
651
IsColorFilterModeOn() const652 bool RSUniRenderThread::IsColorFilterModeOn() const
653 {
654 if (!uniRenderEngine_) {
655 return false;
656 }
657 ColorFilterMode colorFilterMode = uniRenderEngine_->GetColorFilterMode();
658 if (colorFilterMode == ColorFilterMode::INVERT_COLOR_DISABLE_MODE ||
659 colorFilterMode >= ColorFilterMode::DALTONIZATION_NORMAL_MODE) {
660 return false;
661 }
662 return true;
663 }
664
IsHighContrastTextModeOn() const665 bool RSUniRenderThread::IsHighContrastTextModeOn() const
666 {
667 if (!uniRenderEngine_) {
668 return false;
669 }
670 return uniRenderEngine_->IsHighContrastEnabled();
671 }
672
TrimMem(std::string & dumpString,std::string & type)673 void RSUniRenderThread::TrimMem(std::string& dumpString, std::string& type)
674 {
675 auto task = [this, &dumpString, &type] {
676 std::string typeGpuLimit = "setgpulimit";
677 if (!uniRenderEngine_) {
678 return;
679 }
680 auto renderContext = uniRenderEngine_->GetRenderContext();
681 if (!renderContext) {
682 return;
683 }
684 auto gpuContext = renderContext->GetDrGPUContext();
685 if (gpuContext == nullptr) {
686 return;
687 }
688 if (type.empty()) {
689 TrimMemEmptyType(gpuContext);
690 } else if (type == "cpu") {
691 gpuContext->Flush();
692 SkGraphics::PurgeAllCaches();
693 gpuContext->FlushAndSubmit(true);
694 } else if (type == "gpu") {
695 gpuContext->Flush();
696 gpuContext->FreeGpuResources();
697 gpuContext->FlushAndSubmit(true);
698 } else if (type == "uihidden") {
699 gpuContext->Flush();
700 gpuContext->PurgeUnlockAndSafeCacheGpuResources();
701 gpuContext->FlushAndSubmit(true);
702 } else if (type == "unlock") {
703 gpuContext->Flush();
704 gpuContext->PurgeUnlockedResources(false);
705 gpuContext->FlushAndSubmit(true);
706 } else if (type == "shader") {
707 TrimMemShaderType();
708 } else if (type == "flushcache") {
709 int ret = mallopt(M_FLUSH_THREAD_CACHE, 0);
710 dumpString.append("flushcache " + std::to_string(ret) + "\n");
711 } else if (type.substr(0, typeGpuLimit.length()) == typeGpuLimit) {
712 TrimMemGpuLimitType(gpuContext, dumpString, type, typeGpuLimit);
713 } else {
714 uint32_t pid = static_cast<uint32_t>(std::stoll(type));
715 Drawing::GPUResourceTag tag(pid, 0, 0, 0, "TrimMem");
716 MemoryManager::ReleaseAllGpuResource(gpuContext, tag);
717 }
718 dumpString.append("trimMem: " + type + "\n");
719 };
720 PostSyncTask(task);
721 }
722
DumpMem(DfxString & log)723 void RSUniRenderThread::DumpMem(DfxString& log)
724 {
725 std::vector<std::pair<NodeId, std::string>> nodeTags;
726 const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
727 nodeMap.TraverseSurfaceNodes([&nodeTags](const std::shared_ptr<RSSurfaceRenderNode> node) {
728 std::string name = node->GetName() + " " + std::to_string(node->GetId());
729 nodeTags.push_back({node->GetId(), name});
730 });
731 PostSyncTask([&log, &nodeTags, this]() {
732 if (!uniRenderEngine_) {
733 return;
734 }
735 auto renderContext = uniRenderEngine_->GetRenderContext();
736 if (!renderContext) {
737 return;
738 }
739 auto gpuContext = renderContext->GetDrGPUContext();
740 MemoryManager::DumpDrawingGpuMemory(log, gpuContext, nodeTags);
741 });
742 }
743
ClearMemoryCache(ClearMemoryMoment moment,bool deeply,pid_t pid)744 void RSUniRenderThread::ClearMemoryCache(ClearMemoryMoment moment, bool deeply, pid_t pid)
745 {
746 if (!RSSystemProperties::GetReleaseResourceEnabled()) {
747 return;
748 }
749 {
750 std::lock_guard<std::mutex> lock(clearMemoryMutex_);
751 clearMemDeeply_ = clearMemDeeply_ || deeply;
752 SetClearMoment(moment);
753 clearMemoryFinished_ = false;
754 exitedPidSet_.emplace(pid);
755 }
756 PostClearMemoryTask(moment, deeply, false);
757 }
758
DefaultClearMemoryCache()759 void RSUniRenderThread::DefaultClearMemoryCache()
760 {
761 // To clean memory when no render in 5s
762 if (!RSSystemProperties::GetReleaseResourceEnabled()) {
763 return;
764 }
765 PostClearMemoryTask(ClearMemoryMoment::DEFAULT_CLEAN, false, true);
766 }
767
PostClearMemoryTask(ClearMemoryMoment moment,bool deeply,bool isDefaultClean)768 void RSUniRenderThread::PostClearMemoryTask(ClearMemoryMoment moment, bool deeply, bool isDefaultClean)
769 {
770 auto task = [this, moment, deeply, isDefaultClean]() {
771 if (!uniRenderEngine_) {
772 return;
773 }
774 auto renderContext = uniRenderEngine_->GetRenderContext();
775 if (!renderContext) {
776 return;
777 }
778 auto grContext = renderContext->GetDrGPUContext();
779 if (UNLIKELY(!grContext)) {
780 return;
781 }
782 RS_LOGD("Clear memory cache %{public}d", moment);
783 RS_TRACE_NAME_FMT("Clear memory cache, cause the moment [%d] happen", moment);
784 std::lock_guard<std::mutex> lock(clearMemoryMutex_);
785 SKResourceManager::Instance().ReleaseResource();
786 grContext->Flush();
787 SkGraphics::PurgeAllCaches(); // clear cpu cache
788 auto pid = *(this->exitedPidSet_.begin());
789 if (this->exitedPidSet_.size() == 1 && pid == -1) { // no exited app, just clear scratch resource
790 if (deeply || this->deviceType_ != DeviceType::PHONE) {
791 MemoryManager::ReleaseUnlockAndSafeCacheGpuResource(grContext);
792 } else {
793 MemoryManager::ReleaseUnlockGpuResource(grContext);
794 }
795 } else {
796 MemoryManager::ReleaseUnlockGpuResource(grContext, this->exitedPidSet_);
797 }
798 auto screenManager_ = CreateOrGetScreenManager();
799 screenManager_->ClearFrameBufferIfNeed();
800 grContext->FlushAndSubmit(true);
801 if (this->vmaOptimizeFlag_) {
802 MemoryManager::VmaDefragment(grContext);
803 }
804 if (RSSystemProperties::GetRenderNodePurgeEnabled()) {
805 auto purgeDrawables =
806 DrawableV2::RSRenderNodeDrawableAdapter::GetDrawableVectorById(nodesNeedToBeClearMemory_);
807 for (auto& drawable : purgeDrawables) {
808 drawable->Purge();
809 }
810 }
811 nodesNeedToBeClearMemory_.clear();
812 if (!isDefaultClean) {
813 this->clearMemoryFinished_ = true;
814 } else {
815 this->isDefaultCleanTaskFinished_ = true;
816 if (RSSystemProperties::GetRenderNodePurgeEnabled()) {
817 RS_TRACE_NAME_FMT("Purge unlocked resources when clear memory");
818 grContext->PurgeUnlockedResources(false);
819 }
820 }
821 RSUifirstManager::Instance().TryReleaseTextureForIdleThread();
822 this->clearMemDeeply_ = false;
823 this->SetClearMoment(ClearMemoryMoment::NO_CLEAR);
824 };
825 if (!isDefaultClean) {
826 PostTask(task, CLEAR_GPU_CACHE,
827 (this->deviceType_ == DeviceType::PHONE ? TIME_OF_EIGHT_FRAMES : TIME_OF_THE_FRAMES) / GetRefreshRate());
828 } else {
829 PostTask(task, DEFAULT_CLEAR_GPU_CACHE, TIME_OF_DEFAULT_CLEAR_GPU_CACHE);
830 }
831 }
832
ResetClearMemoryTask(const std::unordered_map<NodeId,bool> && ids,bool isDoDirectComposition)833 void RSUniRenderThread::ResetClearMemoryTask(const std::unordered_map<NodeId, bool>&& ids, bool isDoDirectComposition)
834 {
835 for (auto [nodeId, purgeFlag] : ids) {
836 if (purgeFlag) {
837 nodesNeedToBeClearMemory_.insert(nodeId);
838 } else {
839 nodesNeedToBeClearMemory_.erase(nodeId);
840 }
841 }
842 if (!GetClearMemoryFinished()) {
843 RemoveTask(CLEAR_GPU_CACHE);
844 if (!isDoDirectComposition) {
845 ClearMemoryCache(clearMoment_, clearMemDeeply_);
846 }
847 }
848 if (!isDefaultCleanTaskFinished_) {
849 RemoveTask(DEFAULT_CLEAR_GPU_CACHE);
850 if (!isDoDirectComposition) {
851 DefaultClearMemoryCache();
852 }
853 }
854 }
855
SetDefaultClearMemoryFinished(bool isFinished)856 void RSUniRenderThread::SetDefaultClearMemoryFinished(bool isFinished)
857 {
858 isDefaultCleanTaskFinished_ = isFinished;
859 }
860
IsDefaultClearMemroyFinished()861 bool RSUniRenderThread::IsDefaultClearMemroyFinished()
862 {
863 return isDefaultCleanTaskFinished_;
864 }
865
PurgeCacheBetweenFrames()866 void RSUniRenderThread::PurgeCacheBetweenFrames()
867 {
868 if (!RSSystemProperties::GetReleaseResourceEnabled()) {
869 return;
870 }
871 RS_TRACE_NAME_FMT("MEM PurgeCacheBetweenFrames add task");
872 PostTask(
873 [this]() {
874 if (!uniRenderEngine_) {
875 return;
876 }
877 auto renderContext = uniRenderEngine_->GetRenderContext();
878 if (!renderContext) {
879 return;
880 }
881 auto grContext = renderContext->GetDrGPUContext();
882 if (!grContext) {
883 return;
884 }
885 RS_TRACE_NAME_FMT("PurgeCacheBetweenFrames");
886 std::set<int> protectedPidSet = { RSMainThread::Instance()->GetDesktopPidForRotationScene() };
887 MemoryManager::PurgeCacheBetweenFrames(grContext, true, this->exitedPidSet_, protectedPidSet);
888 RemoveTask(PURGE_CACHE_BETWEEN_FRAMES);
889 },
890 PURGE_CACHE_BETWEEN_FRAMES, 0, AppExecFwk::EventQueue::Priority::LOW);
891 }
892
FlushGpuMemoryInWaitQueueBetweenFrames()893 void RSUniRenderThread::FlushGpuMemoryInWaitQueueBetweenFrames()
894 {
895 if (!uniRenderEngine_) {
896 return;
897 }
898 auto renderContext = uniRenderEngine_->GetRenderContext();
899 if (!renderContext) {
900 return;
901 }
902 auto grContext = renderContext->GetDrGPUContext();
903 if (!grContext) {
904 return;
905 }
906 MemoryManager::FlushGpuMemoryInWaitQueue(grContext);
907 }
908
SuppressGpuCacheBelowCertainRatioBetweenFrames()909 void RSUniRenderThread::SuppressGpuCacheBelowCertainRatioBetweenFrames()
910 {
911 RemoveTask(SUPPRESS_GPUCACHE_BELOW_CERTAIN_RATIO);
912 PostTask(
913 [this]() {
914 if (!uniRenderEngine_) {
915 return;
916 }
917 auto renderContext = uniRenderEngine_->GetRenderContext();
918 if (!renderContext) {
919 return;
920 }
921 auto grContext = renderContext->GetDrGPUContext();
922 if (!grContext) {
923 return;
924 }
925 RS_TRACE_NAME_FMT("SuppressGpuCacheBelowCertainRatio");
926 MemoryManager::SuppressGpuCacheBelowCertainRatio(grContext, [this]() -> bool {
927 return this->handler_->HasPreferEvent(static_cast<int>(AppExecFwk::EventQueue::Priority::HIGH));
928 });
929 },
930 SUPPRESS_GPUCACHE_BELOW_CERTAIN_RATIO, 0, AppExecFwk::EventQueue::Priority::LOW);
931 }
932
MemoryManagementBetweenFrames()933 void RSUniRenderThread::MemoryManagementBetweenFrames()
934 {
935 if (RSSystemProperties::GetGpuMemoryAsyncReclaimerEnabled()) {
936 FlushGpuMemoryInWaitQueueBetweenFrames();
937 }
938 if (RSSystemProperties::GetGpuCacheSuppressWindowEnabled()) {
939 SuppressGpuCacheBelowCertainRatioBetweenFrames();
940 }
941 }
942
RenderServiceTreeDump(std::string & dumpString)943 void RSUniRenderThread::RenderServiceTreeDump(std::string& dumpString)
944 {
945 PostSyncTask([this, &dumpString]() {
946 if (!rootNodeDrawable_) {
947 dumpString.append("rootNode is null\n");
948 return;
949 }
950 rootNodeDrawable_->DumpDrawableTree(0, dumpString, RSMainThread::Instance()->GetContext());
951 });
952 }
953
UpdateDisplayNodeScreenId()954 void RSUniRenderThread::UpdateDisplayNodeScreenId()
955 {
956 const std::shared_ptr<RSBaseRenderNode> rootNode =
957 RSMainThread::Instance()->GetContext().GetGlobalRootRenderNode();
958 if (!rootNode) {
959 RS_LOGE("RSUniRenderThread::UpdateDisplayNodeScreenId rootNode is nullptr");
960 return;
961 }
962 auto child = rootNode->GetFirstChild();
963 if (child != nullptr && child->IsInstanceOf<RSDisplayRenderNode>()) {
964 auto displayNode = child->ReinterpretCastTo<RSDisplayRenderNode>();
965 if (displayNode) {
966 displayNodeScreenId_ = displayNode->GetScreenId();
967 }
968 }
969 }
970
GetDynamicRefreshRate() const971 uint32_t RSUniRenderThread::GetDynamicRefreshRate() const
972 {
973 uint32_t refreshRate = OHOS::Rosen::HgmCore::Instance().GetScreenCurrentRefreshRate(displayNodeScreenId_);
974 if (refreshRate == 0) {
975 RS_LOGE("RSUniRenderThread::GetDynamicRefreshRate refreshRate is invalid");
976 return STANDARD_REFRESH_RATE;
977 }
978 return refreshRate;
979 }
980
SetAcquireFence(sptr<SyncFence> acquireFence)981 void RSUniRenderThread::SetAcquireFence(sptr<SyncFence> acquireFence)
982 {
983 acquireFence_ = acquireFence;
984 }
985
SetVmaCacheStatus(bool flag)986 void RSUniRenderThread::SetVmaCacheStatus(bool flag)
987 {
988 static constexpr int MAX_VMA_CACHE_COUNT = 600;
989 RS_LOGD("RSUniRenderThread::SetVmaCacheStatus(): %d, %d", vmaOptimizeFlag_, flag);
990 if (!vmaOptimizeFlag_) {
991 return;
992 }
993 std::lock_guard<std::mutex> lock(vmaCacheCountMutex_);
994 vmaCacheCount_ = flag ? MAX_VMA_CACHE_COUNT : 0;
995 }
996 } // namespace Rosen
997 } // namespace OHOS
998