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