1 /*
2 * Copyright (c) 2020-2021 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 "core/render_manager.h"
17
18 #include "components/root_view.h"
19 #include "gfx_utils/graphic_log.h"
20 #include "hal_tick.h"
21 #include "securec.h"
22 #if ENABLE_WINDOW
23 #include "window/window_impl.h"
24 #endif
25
26 namespace OHOS {
RenderManager()27 RenderManager::RenderManager() : fps_(0.f), needResetFPS_(true), onFPSChangedListener_(nullptr) {}
28
~RenderManager()29 RenderManager::~RenderManager() {}
30
GetInstance()31 RenderManager& RenderManager::GetInstance()
32 {
33 static RenderManager instance;
34 return instance;
35 }
36
Init()37 void RenderManager::Init()
38 {
39 Task::Init();
40 }
41
Callback()42 void RenderManager::Callback()
43 {
44 #if ENABLE_WINDOW
45 ListNode<Window*>* winNode = winList_.Begin();
46 while (winNode != winList_.End()) {
47 WindowImpl* windowImpl = reinterpret_cast<WindowImpl*>(winNode->data_);
48 windowImpl->Render();
49 winNode = winNode->next_;
50 }
51 #else
52 RootView::GetInstance()->Measure();
53 RootView::GetInstance()->Render();
54 #endif
55
56 #if ENABLE_FPS_SUPPORT
57 UpdateFPS();
58 #endif
59 }
60
61 #if ENABLE_FPS_SUPPORT
UpdateFPS()62 void RenderManager::UpdateFPS()
63 {
64 SysInfo::FPSCalculateType type = SysInfo::FPS_CT_FIXED_TIME;
65 if (onFPSChangedListener_) {
66 type = onFPSChangedListener_->GetFPSCalculateType();
67 }
68 if (type == SysInfo::FPS_CT_FIXED_TIME) {
69 UpdateFPSByFixedTimeMethod();
70 } else if (type == SysInfo::FPS_CT_AVERAGE_SAMPLING) {
71 UpdateFPSByAverageSamplingMethod();
72 } else if (type == SysInfo::FPS_CT_PRECISE_SAMPLING) {
73 UpdateFPSByPreciseSamplingMethod();
74 }
75 OnFPSChanged(fps_);
76 }
77
UpdateFPSByFixedTimeMethod()78 void RenderManager::UpdateFPSByFixedTimeMethod()
79 {
80 static uint16_t frameCount = 0;
81 static uint32_t lastTime = HALTick::GetInstance().GetTime();
82 if (needResetFPS_) {
83 frameCount = 0;
84 lastTime = HALTick::GetInstance().GetTime();
85 needResetFPS_ = false;
86 fps_ = 0.f;
87 return;
88 }
89
90 frameCount++;
91
92 uint32_t curTime = HALTick::GetInstance().GetTime();
93 if (curTime - lastTime > MILLISECONDS_PER_SECOND) {
94 fps_ = 1.f * frameCount / (curTime - lastTime) * MILLISECONDS_PER_SECOND;
95 fps_ = (fps_ > MAX_FPS) ? MAX_FPS : fps_;
96 frameCount = 0;
97 lastTime = curTime;
98 }
99 }
100
UpdateFPSByAverageSamplingMethod()101 void RenderManager::UpdateFPSByAverageSamplingMethod()
102 {
103 static float avgDuration = 0.f;
104 static float alpha = 1.f / SAMPLE_NUMBER;
105 static bool firstFrame = true;
106 static uint32_t lastTime = HALTick::GetInstance().GetTime();
107 if (needResetFPS_) {
108 avgDuration = 0.f;
109 alpha = 1.f / SAMPLE_NUMBER;
110 firstFrame = true;
111 lastTime = HALTick::GetInstance().GetTime();
112 needResetFPS_ = false;
113 fps_ = 0.f;
114 return;
115 }
116 uint32_t curTime = HALTick::GetInstance().GetTime();
117 int32_t deltaTime = curTime - lastTime;
118 lastTime = curTime;
119
120 if (firstFrame) {
121 avgDuration = static_cast<float>(deltaTime);
122 firstFrame = false;
123 } else {
124 avgDuration = avgDuration * (1 - alpha) + deltaTime * alpha;
125 }
126 fps_ = 1.f / avgDuration * MILLISECONDS_PER_SECOND;
127 }
128
UpdateFPSByPreciseSamplingMethod()129 void RenderManager::UpdateFPSByPreciseSamplingMethod()
130 {
131 static int32_t deltaTimeQueue[SAMPLE_NUMBER] = {0};
132 static int32_t frameCount = 0;
133 static int32_t sumDuration = 0;
134 static bool isQueueFull = false;
135 static uint32_t lastTime = HALTick::GetInstance().GetTime();
136 if (needResetFPS_) {
137 if (memset_s(deltaTimeQueue, sizeof(deltaTimeQueue), 0, sizeof(deltaTimeQueue)) != EOK) {
138 return;
139 }
140 frameCount = 0;
141 sumDuration = 0;
142 isQueueFull = false;
143 lastTime = HALTick::GetInstance().GetTime();
144 needResetFPS_ = false;
145 fps_ = 0.f;
146 return;
147 }
148 uint32_t curTime = HALTick::GetInstance().GetTime();
149 int32_t deltaTime = curTime - lastTime;
150 lastTime = curTime;
151
152 if (!isQueueFull && (frameCount == SAMPLE_NUMBER)) {
153 isQueueFull = true;
154 }
155 frameCount %= SAMPLE_NUMBER;
156 sumDuration -= deltaTimeQueue[frameCount];
157 sumDuration += deltaTime;
158 deltaTimeQueue[frameCount++] = deltaTime;
159 if (isQueueFull) {
160 fps_ = 1.f * SAMPLE_NUMBER / sumDuration * MILLISECONDS_PER_SECOND;
161 } else {
162 fps_ = 1.f * frameCount / sumDuration * MILLISECONDS_PER_SECOND;
163 }
164 }
165 #endif
166
RenderRect(const Rect & rect,RootView * rootView)167 void RenderManager::RenderRect(const Rect& rect, RootView* rootView)
168 {
169 if (rootView == nullptr) {
170 return;
171 }
172
173 Rect mask = rect;
174 #if ENABLE_WINDOW
175 if (rootView->GetBoundWindow()) {
176 Rect winRect = rootView->GetBoundWindow()->GetRect();
177 winRect.SetPosition(0, 0);
178 mask.Intersect(rect, winRect);
179 }
180 #endif
181 #if LOCAL_RENDER
182 rootView->DrawInvalidMap(mask);
183 #else
184 UIView* topView = rootView->GetTopUIView(mask);
185 rootView->DrawTop(topView, mask);
186 #endif
187 }
188
RefreshScreen()189 void RenderManager::RefreshScreen()
190 {
191 #if ENABLE_WINDOW
192 ListNode<Window*>* winNode = winList_.Begin();
193 while (winNode != winList_.End()) {
194 WindowImpl* windowImpl = reinterpret_cast<WindowImpl*>(winNode->data_);
195 RootView* rootView = windowImpl->GetRootView();
196 if (rootView == nullptr) {
197 winNode = winNode->next_;
198 continue;
199 }
200 rootView->Invalidate();
201 winNode = winNode->next_;
202 }
203 #else
204 RootView::GetInstance()->Invalidate();
205 #endif
206 }
207
208 #if ENABLE_WINDOW
AddToDisplay(Window * window)209 void RenderManager::AddToDisplay(Window* window)
210 {
211 if (window == nullptr) {
212 return;
213 }
214 winList_.PushBack(window);
215 }
216
RemoveFromDisplay(Window * window)217 void RenderManager::RemoveFromDisplay(Window* window)
218 {
219 if (window == nullptr) {
220 return;
221 }
222 ListNode<Window*>* winNode = winList_.Begin();
223 while (winNode != winList_.End()) {
224 if (winNode->data_ == window) {
225 winList_.Remove(winNode);
226 return;
227 }
228 winNode = winNode->next_;
229 }
230 }
231 #endif
232 } // namespace OHOS
233