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 "rs_draw_frame.h"
17
18 #include <hitrace_meter.h>
19 #include <parameters.h>
20
21 #include "rs_trace.h"
22
23 #include "drawable/rs_canvas_drawing_render_node_drawable.h"
24 #include "feature/uifirst/rs_uifirst_manager.h"
25 #include "gfx/performance/rs_perfmonitor_reporter.h"
26 #include "memory/rs_memory_manager.h"
27 #include "pipeline/main_thread/rs_main_thread.h"
28 #include "pipeline/rs_render_node_gc.h"
29 #include "render/rs_filter_cache_manager.h"
30 #include "rs_frame_report.h"
31 #include "rs_uni_render_thread.h"
32
33 #include "rs_profiler.h"
34
35 namespace OHOS {
36 namespace Rosen {
RSDrawFrame()37 RSDrawFrame::RSDrawFrame()
38 : unirenderInstance_(RSUniRenderThread::Instance()), rsParallelType_(RSSystemParameters::GetRsParallelType())
39 {}
40
~RSDrawFrame()41 RSDrawFrame::~RSDrawFrame() noexcept {}
42
SetRenderThreadParams(std::unique_ptr<RSRenderThreadParams> & stagingRenderThreadParams)43 void RSDrawFrame::SetRenderThreadParams(std::unique_ptr<RSRenderThreadParams>& stagingRenderThreadParams)
44 {
45 stagingRenderThreadParams_ = std::move(stagingRenderThreadParams);
46 }
47
48 bool RSDrawFrame::debugTraceEnabled_ =
49 std::atoi((OHOS::system::GetParameter("persist.sys.graphic.openDebugTrace", "0")).c_str()) != 0;
50
RenderFrame()51 void RSDrawFrame::RenderFrame()
52 {
53 HitracePerfScoped perfTrace(RSDrawFrame::debugTraceEnabled_, HITRACE_TAG_GRAPHIC_AGP, "OnRenderFramePerfCount");
54 RS_TRACE_NAME_FMT("RenderFrame");
55 // The destructor of GPUCompositonCacheGuard, a memory release check will be performed
56 RSMainThread::GPUCompositonCacheGuard guard;
57 RsFrameReport::GetInstance().ReportSchedEvent(FrameSchedEvent::RS_UNI_RENDER_START, {});
58 JankStatsRenderFrameStart();
59 unirenderInstance_.IncreaseFrameCount();
60 RSUifirstManager::Instance().ProcessSubDoneNode();
61 Sync();
62 const bool doJankStats = IsUniRenderAndOnVsync();
63 JankStatsRenderFrameAfterSync(doJankStats);
64 RSMainThread::Instance()->ProcessUiCaptureTasks();
65 RSUifirstManager::Instance().PostUifistSubTasks();
66 UnblockMainThread();
67 RsFrameReport::GetInstance().UnblockMainThread();
68 Render();
69 RsFrameReport::GetInstance().ReportSchedEvent(FrameSchedEvent::RS_RENDER_END, {});
70 ReleaseSelfDrawingNodeBuffer();
71 NotifyClearGpuCache();
72 RSMainThread::Instance()->CallbackDrawContextStatusToWMS(true);
73 RSRenderNodeGC::Instance().ReleaseDrawableMemory();
74 if (RSSystemProperties::GetPurgeBetweenFramesEnabled()) {
75 unirenderInstance_.PurgeCacheBetweenFrames();
76 }
77 unirenderInstance_.MemoryManagementBetweenFrames();
78 unirenderInstance_.PurgeShaderCacheAfterAnimate();
79 MemoryManager::MemoryOverCheck(unirenderInstance_.GetRenderEngine()->GetRenderContext()->GetDrGPUContext());
80 JankStatsRenderFrameEnd(doJankStats);
81 RSPerfMonitorReporter::GetInstance().ReportAtRsFrameEnd();
82 RsFrameReport::GetInstance().RenderEnd();
83 }
84
NotifyClearGpuCache()85 void RSDrawFrame::NotifyClearGpuCache()
86 {
87 if (RSFilterCacheManager::GetFilterInvalid()) {
88 unirenderInstance_.ClearMemoryCache(ClearMemoryMoment::FILTER_INVALID, true);
89 RSFilterCacheManager::SetFilterInvalid(false);
90 }
91 }
92
ReleaseSelfDrawingNodeBuffer()93 void RSDrawFrame::ReleaseSelfDrawingNodeBuffer()
94 {
95 unirenderInstance_.ReleaseSelfDrawingNodeBuffer();
96 }
97
PostAndWait()98 void RSDrawFrame::PostAndWait()
99 {
100 RS_TRACE_NAME_FMT("PostAndWait, parallel type %d", static_cast<int>(rsParallelType_));
101 RsFrameReport& fr = RsFrameReport::GetInstance();
102 if (fr.GetEnable()) {
103 fr.SendCommandsStart();
104 fr.RenderEnd();
105 }
106
107 uint32_t renderFrameNumber = RS_PROFILER_GET_FRAME_NUMBER();
108 switch (rsParallelType_) {
109 case RsParallelType::RS_PARALLEL_TYPE_SYNC: { // wait until render finish in render thread
110 unirenderInstance_.PostSyncTask([this, renderFrameNumber]() {
111 unirenderInstance_.SetMainLooping(true);
112 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
113 RenderFrame();
114 unirenderInstance_.RunImageReleaseTask();
115 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
116 unirenderInstance_.SetMainLooping(false);
117 });
118 break;
119 }
120 case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: { // render in main thread
121 RenderFrame();
122 unirenderInstance_.RunImageReleaseTask();
123 break;
124 }
125 case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
126 default: {
127 std::unique_lock<std::mutex> frameLock(frameMutex_);
128 canUnblockMainThread = false;
129 unirenderInstance_.PostTask([this, renderFrameNumber]() {
130 unirenderInstance_.SetMainLooping(true);
131 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
132 RSMainThread::Instance()->GetRSVsyncRateReduceManager().FrameDurationBegin();
133 RenderFrame();
134 unirenderInstance_.RunImageReleaseTask();
135 RSMainThread::Instance()->GetRSVsyncRateReduceManager().FrameDurationEnd();
136 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
137 unirenderInstance_.SetMainLooping(false);
138 });
139
140 frameCV_.wait(frameLock, [this] { return canUnblockMainThread; });
141 }
142 }
143 }
144
PostDirectCompositionJankStats(const JankDurationParams & rsParams)145 void RSDrawFrame::PostDirectCompositionJankStats(const JankDurationParams& rsParams)
146 {
147 RS_TRACE_NAME_FMT("PostDirectCompositionJankStats, parallel type %d", static_cast<int>(rsParallelType_));
148 switch (rsParallelType_) {
149 case RsParallelType::RS_PARALLEL_TYPE_SYNC: // wait until render finish in render thread
150 case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: // render in main thread
151 case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
152 default: {
153 bool isReportTaskDelayed = unirenderInstance_.IsMainLooping();
154 auto task = [rsParams, isReportTaskDelayed]() -> void {
155 RSJankStats::GetInstance().HandleDirectComposition(rsParams, isReportTaskDelayed);
156 };
157 unirenderInstance_.PostTask(task);
158 }
159 }
160 }
161
CheckCanvasSkipSync(std::shared_ptr<RSRenderNode> node)162 bool RSDrawFrame::CheckCanvasSkipSync(std::shared_ptr<RSRenderNode> node)
163 {
164 if (node->GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE) {
165 auto nodeDrawable =
166 std::static_pointer_cast<DrawableV2::RSCanvasDrawingRenderNodeDrawable>(node->GetRenderDrawable());
167 if (nodeDrawable == nullptr) {
168 return true;
169 }
170 if (nodeDrawable->IsNeedDraw() && nodeDrawable->GetDrawSkipType() == DrawableV2::DrawSkipType::NONE) {
171 stagingSyncCanvasDrawingNodes_.emplace(node->GetId(), node);
172 return false;
173 }
174 }
175 return true;
176 }
177
Sync()178 void RSDrawFrame::Sync()
179 {
180 RS_TRACE_NAME_FMT("Sync");
181 RSMainThread::Instance()->GetContext().GetGlobalRootRenderNode()->Sync();
182
183 auto& pendingSyncNodes = RSMainThread::Instance()->GetContext().pendingSyncNodes_;
184 for (auto [id, weakPtr] : stagingSyncCanvasDrawingNodes_) {
185 pendingSyncNodes.emplace(id, weakPtr);
186 }
187 stagingSyncCanvasDrawingNodes_.clear();
188 for (auto& [id, weakPtr] : pendingSyncNodes) {
189 if (auto node = weakPtr.lock()) {
190 if (!CheckCanvasSkipSync(node)) {
191 node->SkipSync();
192 continue;
193 }
194 if (!RSUifirstManager::Instance().CollectSkipSyncNode(node)) {
195 node->Sync();
196 } else {
197 node->SkipSync();
198 }
199 }
200 }
201 pendingSyncNodes.clear();
202
203 unirenderInstance_.Sync(std::move(stagingRenderThreadParams_));
204 }
205
UnblockMainThread()206 void RSDrawFrame::UnblockMainThread()
207 {
208 RS_TRACE_NAME_FMT("UnlockMainThread");
209 std::unique_lock<std::mutex> frameLock(frameMutex_);
210 if (!canUnblockMainThread) {
211 canUnblockMainThread = true;
212 frameCV_.notify_all();
213 }
214 }
215
Render()216 void RSDrawFrame::Render()
217 {
218 RS_TRACE_NAME_FMT("Render vsyncId: %" PRIu64 "", unirenderInstance_.GetVsyncId());
219 unirenderInstance_.Render();
220 }
221
JankStatsRenderFrameStart()222 void RSDrawFrame::JankStatsRenderFrameStart()
223 {
224 unirenderInstance_.SetSkipJankAnimatorFrame(false);
225 }
226
IsUniRenderAndOnVsync() const227 bool RSDrawFrame::IsUniRenderAndOnVsync() const
228 {
229 const auto& renderThreadParams = unirenderInstance_.GetRSRenderThreadParams();
230 if (!renderThreadParams) {
231 return false;
232 }
233 return renderThreadParams->IsUniRenderAndOnVsync();
234 }
235
JankStatsRenderFrameAfterSync(bool doJankStats)236 void RSDrawFrame::JankStatsRenderFrameAfterSync(bool doJankStats)
237 {
238 if (!doJankStats) {
239 return;
240 }
241 RSJankStats::GetInstance().SetStartTime();
242 RSJankStats::GetInstance().SetAccumulatedBufferCount(RSBaseRenderUtil::GetAccumulatedBufferCount());
243 unirenderInstance_.UpdateDisplayNodeScreenId();
244 }
245
JankStatsRenderFrameEnd(bool doJankStats)246 void RSDrawFrame::JankStatsRenderFrameEnd(bool doJankStats)
247 {
248 if (!doJankStats) {
249 unirenderInstance_.SetDiscardJankFrames(false);
250 return;
251 }
252 const auto& renderThreadParams = unirenderInstance_.GetRSRenderThreadParams();
253 if (renderThreadParams == nullptr) {
254 return;
255 }
256 RSJankStats::GetInstance().SetOnVsyncStartTime(
257 renderThreadParams->GetOnVsyncStartTime(),
258 renderThreadParams->GetOnVsyncStartTimeSteady(),
259 renderThreadParams->GetOnVsyncStartTimeSteadyFloat());
260 RSJankStats::GetInstance().SetImplicitAnimationEnd(renderThreadParams->GetImplicitAnimationEnd());
261 RSJankStats::GetInstance().SetEndTime(
262 unirenderInstance_.GetSkipJankAnimatorFrame(),
263 unirenderInstance_.GetDiscardJankFrames() || renderThreadParams->GetDiscardJankFrames(),
264 unirenderInstance_.GetDynamicRefreshRate());
265 unirenderInstance_.SetDiscardJankFrames(false);
266 }
267 } // namespace Rosen
268 } // namespace OHOS
269