• 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.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