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_uifirst_manager.h"
27 #include "pipeline/rs_uni_render_thread.h"
28 #include "property/rs_filter_cache_manager.h"
29 #include "rs_frame_report.h"
30
31 #include "rs_profiler.h"
32
33 namespace OHOS {
34 namespace Rosen {
RSDrawFrame()35 RSDrawFrame::RSDrawFrame()
36 : unirenderInstance_(RSUniRenderThread::Instance()), rsParallelType_(RSSystemParameters::GetRsParallelType())
37 {}
38
~RSDrawFrame()39 RSDrawFrame::~RSDrawFrame() noexcept {}
40
SetRenderThreadParams(std::unique_ptr<RSRenderThreadParams> & stagingRenderThreadParams)41 void RSDrawFrame::SetRenderThreadParams(std::unique_ptr<RSRenderThreadParams>& stagingRenderThreadParams)
42 {
43 stagingRenderThreadParams_ = std::move(stagingRenderThreadParams);
44 }
45
46 bool RSDrawFrame::debugTraceEnabled_ =
47 std::atoi((OHOS::system::GetParameter("persist.sys.graphic.openDebugTrace", "0")).c_str()) != 0;
48
RenderFrame()49 void RSDrawFrame::RenderFrame()
50 {
51 HitracePerfScoped perfTrace(RSDrawFrame::debugTraceEnabled_, HITRACE_TAG_GRAPHIC_AGP, "OnRenderFramePerfCount");
52 RS_TRACE_NAME_FMT("RenderFrame");
53 RSMainThread::GPUCompositonCacheGuard guard;
54 if (RsFrameReport::GetInstance().GetEnable()) {
55 RsFrameReport::GetInstance().RSRenderStart();
56 }
57 JankStatsRenderFrameStart();
58 unirenderInstance_.IncreaseFrameCount();
59 RSUifirstManager::Instance().ProcessSubDoneNode();
60 Sync();
61 const bool doJankStats = IsUniRenderAndOnVsync();
62 JankStatsRenderFrameAfterSync(doJankStats);
63 RSMainThread::Instance()->ProcessUiCaptureTasks();
64 RSUifirstManager::Instance().PostUifistSubTasks();
65 UnblockMainThread();
66 Render();
67 ReleaseSelfDrawingNodeBuffer();
68 NotifyClearGpuCache();
69 if (RsFrameReport::GetInstance().GetEnable()) {
70 RsFrameReport::GetInstance().RSRenderEnd();
71 }
72 RSMainThread::Instance()->CallbackDrawContextStatusToWMS(true);
73 RSRenderNodeGC::Instance().ReleaseDrawableMemory();
74 if (RSSystemProperties::GetPurgeBetweenFramesEnabled()) {
75 unirenderInstance_.PurgeCacheBetweenFrames();
76 }
77 unirenderInstance_.MemoryManagementBetweenFrames();
78 MemoryManager::MemoryOverCheck(unirenderInstance_.GetRenderEngine()->GetRenderContext()->GetDrGPUContext());
79 JankStatsRenderFrameEnd(doJankStats);
80 }
81
NotifyClearGpuCache()82 void RSDrawFrame::NotifyClearGpuCache()
83 {
84 if (RSFilterCacheManager::GetFilterInvalid()) {
85 unirenderInstance_.ClearMemoryCache(ClearMemoryMoment::FILTER_INVALID, true);
86 RSFilterCacheManager::SetFilterInvalid(false);
87 }
88 }
89
ReleaseSelfDrawingNodeBuffer()90 void RSDrawFrame::ReleaseSelfDrawingNodeBuffer()
91 {
92 unirenderInstance_.ReleaseSelfDrawingNodeBuffer();
93 }
94
PostAndWait()95 void RSDrawFrame::PostAndWait()
96 {
97 RS_TRACE_NAME_FMT("PostAndWait, parallel type %d", static_cast<int>(rsParallelType_));
98 uint32_t renderFrameNumber = RS_PROFILER_GET_FRAME_NUMBER();
99 switch (rsParallelType_) {
100 case RsParallelType::RS_PARALLEL_TYPE_SYNC: { // wait until render finish in render thread
101 unirenderInstance_.PostSyncTask([this, renderFrameNumber]() {
102 unirenderInstance_.SetMainLooping(true);
103 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
104 RenderFrame();
105 unirenderInstance_.RunImageReleaseTask();
106 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
107 unirenderInstance_.SetMainLooping(false);
108 });
109 break;
110 }
111 case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: { // render in main thread
112 RenderFrame();
113 unirenderInstance_.RunImageReleaseTask();
114 break;
115 }
116 case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
117 default: {
118 std::unique_lock<std::mutex> frameLock(frameMutex_);
119 canUnblockMainThread = false;
120 unirenderInstance_.PostTask([this, renderFrameNumber]() {
121 unirenderInstance_.SetMainLooping(true);
122 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
123 RenderFrame();
124 unirenderInstance_.RunImageReleaseTask();
125 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
126 unirenderInstance_.SetMainLooping(false);
127 });
128
129 frameCV_.wait(frameLock, [this] { return canUnblockMainThread; });
130 }
131 }
132 }
133
PostDirectCompositionJankStats(const JankDurationParams & rsParams)134 void RSDrawFrame::PostDirectCompositionJankStats(const JankDurationParams& rsParams)
135 {
136 RS_TRACE_NAME_FMT("PostDirectCompositionJankStats, parallel type %d", static_cast<int>(rsParallelType_));
137 switch (rsParallelType_) {
138 case RsParallelType::RS_PARALLEL_TYPE_SYNC: // wait until render finish in render thread
139 case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: // render in main thread
140 case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
141 default: {
142 bool isReportTaskDelayed = unirenderInstance_.IsMainLooping();
143 auto task = [rsParams, isReportTaskDelayed]() -> void {
144 RSJankStats::GetInstance().HandleDirectComposition(rsParams, isReportTaskDelayed);
145 };
146 unirenderInstance_.PostTask(task);
147 }
148 }
149 }
150
Sync()151 void RSDrawFrame::Sync()
152 {
153 RS_TRACE_NAME_FMT("Sync");
154 RSMainThread::Instance()->GetContext().GetGlobalRootRenderNode()->Sync();
155
156 auto& pendingSyncNodes = RSMainThread::Instance()->GetContext().pendingSyncNodes_;
157 for (auto& [id, weakPtr] : pendingSyncNodes) {
158 if (auto node = weakPtr.lock()) {
159 if (!RSUifirstManager::Instance().CollectSkipSyncNode(node)) {
160 node->Sync();
161 } else {
162 node->SkipSync();
163 }
164 }
165 }
166 pendingSyncNodes.clear();
167
168 unirenderInstance_.Sync(std::move(stagingRenderThreadParams_));
169 }
170
UnblockMainThread()171 void RSDrawFrame::UnblockMainThread()
172 {
173 RS_TRACE_NAME_FMT("UnlockMainThread");
174 std::unique_lock<std::mutex> frameLock(frameMutex_);
175 if (!canUnblockMainThread) {
176 canUnblockMainThread = true;
177 frameCV_.notify_all();
178 }
179 }
180
Render()181 void RSDrawFrame::Render()
182 {
183 RS_TRACE_NAME_FMT("Render vsyncId: %" PRIu64 "", unirenderInstance_.GetVsyncId());
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