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 if (RsFrameReport::GetInstance().GetEnable()) {
54 RsFrameReport::GetInstance().RSRenderStart();
55 }
56 JankStatsRenderFrameStart();
57 unirenderInstance_.IncreaseFrameCount();
58 RSUifirstManager::Instance().ProcessSubDoneNode();
59 Sync();
60 const bool doJankStats = IsUniRenderAndOnVsync();
61 JankStatsRenderFrameAfterSync(doJankStats);
62 RSMainThread::Instance()->ProcessUiCaptureTasks();
63 RSUifirstManager::Instance().PostUifistSubTasks();
64 UnblockMainThread();
65 Render();
66 ReleaseSelfDrawingNodeBuffer();
67 NotifyClearGpuCache();
68 if (RsFrameReport::GetInstance().GetEnable()) {
69 RsFrameReport::GetInstance().RSRenderEnd();
70 }
71 RSMainThread::Instance()->CallbackDrawContextStatusToWMS(true);
72 RSRenderNodeGC::Instance().ReleaseDrawableMemory();
73 if (RSSystemProperties::GetPurgeBetweenFramesEnabled()) {
74 unirenderInstance_.PurgeCacheBetweenFrames();
75 }
76 unirenderInstance_.MemoryManagementBetweenFrames();
77 MemoryManager::MemoryOverCheck(unirenderInstance_.GetRenderEngine()->GetRenderContext()->GetDrGPUContext());
78 JankStatsRenderFrameEnd(doJankStats);
79 }
80
NotifyClearGpuCache()81 void RSDrawFrame::NotifyClearGpuCache()
82 {
83 if (RSFilterCacheManager::GetFilterInvalid()) {
84 unirenderInstance_.ClearMemoryCache(ClearMemoryMoment::FILTER_INVALID, true);
85 RSFilterCacheManager::SetFilterInvalid(false);
86 }
87 }
88
ReleaseSelfDrawingNodeBuffer()89 void RSDrawFrame::ReleaseSelfDrawingNodeBuffer()
90 {
91 unirenderInstance_.ReleaseSelfDrawingNodeBuffer();
92 }
93
PostAndWait()94 void RSDrawFrame::PostAndWait()
95 {
96 RS_TRACE_NAME_FMT("PostAndWait, parallel type %d", static_cast<int>(rsParallelType_));
97 uint32_t renderFrameNumber = RS_PROFILER_GET_FRAME_NUMBER();
98 switch (rsParallelType_) {
99 case RsParallelType::RS_PARALLEL_TYPE_SYNC: { // wait until render finish in render thread
100 unirenderInstance_.PostSyncTask([this, renderFrameNumber]() {
101 unirenderInstance_.SetMainLooping(true);
102 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
103 RenderFrame();
104 unirenderInstance_.RunImageReleaseTask();
105 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
106 unirenderInstance_.SetMainLooping(false);
107 });
108 break;
109 }
110 case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: { // render in main thread
111 RenderFrame();
112 unirenderInstance_.RunImageReleaseTask();
113 break;
114 }
115 case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
116 default: {
117 std::unique_lock<std::mutex> frameLock(frameMutex_);
118 canUnblockMainThread = false;
119 unirenderInstance_.PostTask([this, renderFrameNumber]() {
120 unirenderInstance_.SetMainLooping(true);
121 RS_PROFILER_ON_PARALLEL_RENDER_BEGIN();
122 RenderFrame();
123 unirenderInstance_.RunImageReleaseTask();
124 RS_PROFILER_ON_PARALLEL_RENDER_END(renderFrameNumber);
125 unirenderInstance_.SetMainLooping(false);
126 });
127
128 frameCV_.wait(frameLock, [this] { return canUnblockMainThread; });
129 }
130 }
131 }
132
PostDirectCompositionJankStats(const JankDurationParams & rsParams)133 void RSDrawFrame::PostDirectCompositionJankStats(const JankDurationParams& rsParams)
134 {
135 RS_TRACE_NAME_FMT("PostDirectCompositionJankStats, parallel type %d", static_cast<int>(rsParallelType_));
136 switch (rsParallelType_) {
137 case RsParallelType::RS_PARALLEL_TYPE_SYNC: // wait until render finish in render thread
138 case RsParallelType::RS_PARALLEL_TYPE_SINGLE_THREAD: // render in main thread
139 case RsParallelType::RS_PARALLEL_TYPE_ASYNC: // wait until sync finish in render thread
140 default: {
141 bool isReportTaskDelayed = unirenderInstance_.IsMainLooping();
142 auto task = [rsParams, isReportTaskDelayed]() -> void {
143 RSJankStats::GetInstance().HandleDirectComposition(rsParams, isReportTaskDelayed);
144 };
145 unirenderInstance_.PostTask(task);
146 }
147 }
148 }
149
Sync()150 void RSDrawFrame::Sync()
151 {
152 RS_TRACE_NAME_FMT("Sync");
153 RSMainThread::Instance()->GetContext().GetGlobalRootRenderNode()->Sync();
154
155 auto& pendingSyncNodes = RSMainThread::Instance()->GetContext().pendingSyncNodes_;
156 for (auto& [id, weakPtr] : pendingSyncNodes) {
157 if (auto node = weakPtr.lock()) {
158 if (!RSUifirstManager::Instance().CollectSkipSyncNode(node)) {
159 node->Sync();
160 } else {
161 node->SkipSync();
162 }
163 }
164 }
165 pendingSyncNodes.clear();
166
167 unirenderInstance_.Sync(std::move(stagingRenderThreadParams_));
168 }
169
UnblockMainThread()170 void RSDrawFrame::UnblockMainThread()
171 {
172 RS_TRACE_NAME_FMT("UnlockMainThread");
173 std::unique_lock<std::mutex> frameLock(frameMutex_);
174 if (!canUnblockMainThread) {
175 canUnblockMainThread = true;
176 frameCV_.notify_all();
177 }
178 }
179
Render()180 void RSDrawFrame::Render()
181 {
182 RS_TRACE_NAME_FMT("Render vsyncId: %" PRIu64 "", unirenderInstance_.GetVsyncId());
183 unirenderInstance_.Render();
184 }
185
JankStatsRenderFrameStart()186 void RSDrawFrame::JankStatsRenderFrameStart()
187 {
188 unirenderInstance_.SetSkipJankAnimatorFrame(false);
189 }
190
IsUniRenderAndOnVsync() const191 bool RSDrawFrame::IsUniRenderAndOnVsync() const
192 {
193 const auto& renderThreadParams = unirenderInstance_.GetRSRenderThreadParams();
194 if (!renderThreadParams) {
195 return false;
196 }
197 return renderThreadParams->IsUniRenderAndOnVsync();
198 }
199
JankStatsRenderFrameAfterSync(bool doJankStats)200 void RSDrawFrame::JankStatsRenderFrameAfterSync(bool doJankStats)
201 {
202 if (!doJankStats) {
203 return;
204 }
205 RSJankStats::GetInstance().SetStartTime();
206 RSJankStats::GetInstance().SetAccumulatedBufferCount(RSBaseRenderUtil::GetAccumulatedBufferCount());
207 unirenderInstance_.UpdateDisplayNodeScreenId();
208 }
209
JankStatsRenderFrameEnd(bool doJankStats)210 void RSDrawFrame::JankStatsRenderFrameEnd(bool doJankStats)
211 {
212 if (!doJankStats) {
213 unirenderInstance_.SetDiscardJankFrames(false);
214 return;
215 }
216 const auto& renderThreadParams = unirenderInstance_.GetRSRenderThreadParams();
217 if (renderThreadParams == nullptr) {
218 return;
219 }
220 RSJankStats::GetInstance().SetOnVsyncStartTime(
221 renderThreadParams->GetOnVsyncStartTime(),
222 renderThreadParams->GetOnVsyncStartTimeSteady(),
223 renderThreadParams->GetOnVsyncStartTimeSteadyFloat());
224 RSJankStats::GetInstance().SetImplicitAnimationEnd(renderThreadParams->GetImplicitAnimationEnd());
225 RSJankStats::GetInstance().SetEndTime(
226 unirenderInstance_.GetSkipJankAnimatorFrame(),
227 unirenderInstance_.GetDiscardJankFrames() || renderThreadParams->GetDiscardJankFrames(),
228 unirenderInstance_.GetDynamicRefreshRate());
229 unirenderInstance_.SetDiscardJankFrames(false);
230 }
231 } // namespace Rosen
232 } // namespace OHOS
233