• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "pipeline/rs_draw_frame.h"
17 
18 #include <hitrace_meter.h>
19 #include <parameters.h>
20 
21 #include "rs_trace.h"
22 
23 #include "memory/rs_memory_manager.h"
24 #include "pipeline/rs_main_thread.h"
25 #include "pipeline/rs_render_node_gc.h"
26 #include "pipeline/rs_surface_buffer_callback_manager.h"
27 #include "pipeline/rs_uifirst_manager.h"
28 #include "pipeline/rs_uni_render_thread.h"
29 #include "property/rs_filter_cache_manager.h"
30 #include "rs_frame_report.h"
31 
32 #include "rs_profiler.h"
33 
34 namespace OHOS {
35 namespace Rosen {
RSDrawFrame()36 RSDrawFrame::RSDrawFrame()
37     : unirenderInstance_(RSUniRenderThread::Instance()), rsParallelType_(RSSystemParameters::GetRsParallelType())
38 {}
39 
~RSDrawFrame()40 RSDrawFrame::~RSDrawFrame() noexcept {}
41 
SetRenderThreadParams(std::unique_ptr<RSRenderThreadParams> & stagingRenderThreadParams)42 void RSDrawFrame::SetRenderThreadParams(std::unique_ptr<RSRenderThreadParams>& stagingRenderThreadParams)
43 {
44     stagingRenderThreadParams_ = std::move(stagingRenderThreadParams);
45 }
46 
47 bool RSDrawFrame::debugTraceEnabled_ =
48     std::atoi((OHOS::system::GetParameter("persist.sys.graphic.openDebugTrace", "0")).c_str()) != 0;
49 
RenderFrame()50 void RSDrawFrame::RenderFrame()
51 {
52     HitracePerfScoped perfTrace(RSDrawFrame::debugTraceEnabled_, HITRACE_TAG_GRAPHIC_AGP, "OnRenderFramePerfCount");
53     RS_TRACE_NAME_FMT("RenderFrame");
54     if (RsFrameReport::GetInstance().GetEnable()) {
55         RsFrameReport::GetInstance().RSRenderStart();
56     }
57     JankStatsRenderFrameStart();
58     unirenderInstance_.IncreaseFrameCount();
59     RSUifirstManager::Instance().ProcessSubDoneNode();
60     Sync();
61     RSSurfaceBufferCallbackManager::Instance().RunSurfaceBufferCallback();
62     const bool doJankStats = IsUniRenderAndOnVsync();
63     JankStatsRenderFrameAfterSync(doJankStats);
64     RSMainThread::Instance()->ProcessUiCaptureTasks();
65     RSUifirstManager::Instance().PostUifistSubTasks();
66     UnblockMainThread();
67     Render();
68     ReleaseSelfDrawingNodeBuffer();
69     NotifyClearGpuCache();
70     if (RsFrameReport::GetInstance().GetEnable()) {
71         RsFrameReport::GetInstance().RSRenderEnd();
72     }
73     RSMainThread::Instance()->CallbackDrawContextStatusToWMS(true);
74     RSRenderNodeGC::Instance().ReleaseDrawableMemory();
75     if (RSSystemProperties::GetPurgeBetweenFramesEnabled()) {
76         unirenderInstance_.PurgeCacheBetweenFrames();
77     }
78     unirenderInstance_.MemoryManagementBetweenFrames();
79     MemoryManager::MemoryOverCheck(unirenderInstance_.GetRenderEngine()->GetRenderContext()->GetDrGPUContext());
80     JankStatsRenderFrameEnd(doJankStats);
81 }
82 
NotifyClearGpuCache()83 void RSDrawFrame::NotifyClearGpuCache()
84 {
85     if (RSFilterCacheManager::GetFilterInvalid()) {
86         unirenderInstance_.ClearMemoryCache(ClearMemoryMoment::FILTER_INVALID, true);
87         RSFilterCacheManager::SetFilterInvalid(false);
88     }
89 }
90 
ReleaseSelfDrawingNodeBuffer()91 void RSDrawFrame::ReleaseSelfDrawingNodeBuffer()
92 {
93     unirenderInstance_.ReleaseSelfDrawingNodeBuffer();
94 }
95 
PostAndWait()96 void RSDrawFrame::PostAndWait()
97 {
98     RS_TRACE_NAME_FMT("PostAndWait, parallel type %d", static_cast<int>(rsParallelType_));
99     uint32_t renderFrameNumber = RS_PROFILER_GET_FRAME_NUMBER();
100     switch (rsParallelType_) {
101         case RsParallelType::RS_PARALLEL_TYPE_SYNC: { // wait until render finish in render thread
102             unirenderInstance_.PostSyncTask([this, renderFrameNumber]() {
103                 unirenderInstance_.SetMainLooping(true);
104                 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
105                 RenderFrame();
106                 unirenderInstance_.RunImageReleaseTask();
107                 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
108                 unirenderInstance_.SetMainLooping(false);
109             });
110             break;
111         }
112         case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: { // render in main thread
113             RenderFrame();
114             unirenderInstance_.RunImageReleaseTask();
115             break;
116         }
117         case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
118         default: {
119             std::unique_lock<std::mutex> frameLock(frameMutex_);
120             canUnblockMainThread = false;
121             unirenderInstance_.PostTask([this, renderFrameNumber]() {
122                 unirenderInstance_.SetMainLooping(true);
123                 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
124                 RenderFrame();
125                 unirenderInstance_.RunImageReleaseTask();
126                 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
127                 unirenderInstance_.SetMainLooping(false);
128             });
129 
130             frameCV_.wait(frameLock, [this] { return canUnblockMainThread; });
131         }
132     }
133 }
134 
PostDirectCompositionJankStats(const JankDurationParams & rsParams)135 void RSDrawFrame::PostDirectCompositionJankStats(const JankDurationParams& rsParams)
136 {
137     RS_TRACE_NAME_FMT("PostDirectCompositionJankStats, parallel type %d", static_cast<int>(rsParallelType_));
138     switch (rsParallelType_) {
139         case RsParallelType::RS_PARALLEL_TYPE_SYNC: // wait until render finish in render thread
140         case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: // render in main thread
141         case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
142         default: {
143             bool isReportTaskDelayed = unirenderInstance_.IsMainLooping();
144             auto task = [rsParams, isReportTaskDelayed]() -> void {
145                 RSJankStats::GetInstance().HandleDirectComposition(rsParams, isReportTaskDelayed);
146             };
147             unirenderInstance_.PostTask(task);
148         }
149     }
150 }
151 
Sync()152 void RSDrawFrame::Sync()
153 {
154     RS_TRACE_NAME_FMT("Sync");
155     RSMainThread::Instance()->GetContext().GetGlobalRootRenderNode()->Sync();
156 
157     auto& pendingSyncNodes = RSMainThread::Instance()->GetContext().pendingSyncNodes_;
158     for (auto& [id, weakPtr] : pendingSyncNodes) {
159         if (auto node = weakPtr.lock()) {
160             if (!RSUifirstManager::Instance().CollectSkipSyncNode(node)) {
161                 node->Sync();
162             } else {
163                 node->SkipSync();
164             }
165         }
166     }
167     pendingSyncNodes.clear();
168 
169     unirenderInstance_.Sync(std::move(stagingRenderThreadParams_));
170 }
171 
UnblockMainThread()172 void RSDrawFrame::UnblockMainThread()
173 {
174     RS_TRACE_NAME_FMT("UnlockMainThread");
175     std::unique_lock<std::mutex> frameLock(frameMutex_);
176     if (!canUnblockMainThread) {
177         canUnblockMainThread = true;
178         frameCV_.notify_all();
179     }
180 }
181 
Render()182 void RSDrawFrame::Render()
183 {
184     unirenderInstance_.Render();
185 }
186 
JankStatsRenderFrameStart()187 void RSDrawFrame::JankStatsRenderFrameStart()
188 {
189     unirenderInstance_.SetSkipJankAnimatorFrame(false);
190 }
191 
IsUniRenderAndOnVsync() const192 bool RSDrawFrame::IsUniRenderAndOnVsync() const
193 {
194     const auto& renderThreadParams = unirenderInstance_.GetRSRenderThreadParams();
195     if (!renderThreadParams) {
196         return false;
197     }
198     return renderThreadParams->IsUniRenderAndOnVsync();
199 }
200 
JankStatsRenderFrameAfterSync(bool doJankStats)201 void RSDrawFrame::JankStatsRenderFrameAfterSync(bool doJankStats)
202 {
203     if (!doJankStats) {
204         return;
205     }
206     RSJankStats::GetInstance().SetStartTime();
207     RSJankStats::GetInstance().SetAccumulatedBufferCount(RSBaseRenderUtil::GetAccumulatedBufferCount());
208     unirenderInstance_.UpdateDisplayNodeScreenId();
209 }
210 
JankStatsRenderFrameEnd(bool doJankStats)211 void RSDrawFrame::JankStatsRenderFrameEnd(bool doJankStats)
212 {
213     if (!doJankStats) {
214         unirenderInstance_.SetDiscardJankFrames(false);
215         return;
216     }
217     const auto& renderThreadParams = unirenderInstance_.GetRSRenderThreadParams();
218     if (renderThreadParams == nullptr) {
219         return;
220     }
221     RSJankStats::GetInstance().SetOnVsyncStartTime(
222         renderThreadParams->GetOnVsyncStartTime(),
223         renderThreadParams->GetOnVsyncStartTimeSteady(),
224         renderThreadParams->GetOnVsyncStartTimeSteadyFloat());
225     RSJankStats::GetInstance().SetImplicitAnimationEnd(renderThreadParams->GetImplicitAnimationEnd());
226     RSJankStats::GetInstance().SetEndTime(
227         unirenderInstance_.GetSkipJankAnimatorFrame(),
228         unirenderInstance_.GetDiscardJankFrames() || renderThreadParams->GetDiscardJankFrames(),
229         unirenderInstance_.GetDynamicRefreshRate());
230     unirenderInstance_.SetDiscardJankFrames(false);
231 }
232 } // namespace Rosen
233 } // namespace OHOS
234