• 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 "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