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