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