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