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