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